예제 #1
0
func main() {
	flag.Parse()

	file, err := ioutil.ReadFile(*file)
	checkErr(err)

	var songs []Song
	checkErr(json.Unmarshal(file, &songs))

	// Specifically don't set grpc.WithTimeout(),
	// as it messes with the QueueSong() streams.
	conn, err := grpc.Dial(
		fmt.Sprintf("%v:%v", *host, *port),
		grpc.WithInsecure(),
	)
	checkErr(err)
	defer conn.Close()

	c := playsource.NewPlaySourceClient(conn)
	stream, err := c.QueueSong(context.Background())
	checkErr(err)

	// Try to play all the songs listed in the queue file using
	// the proper protocol. Note: doesn't handle retries.
	var inFlight int
	for i := 0; i < len(songs); {
		for inFlight < *queueSize {
			log.Println("Queueing song:", songs[i])
			err := stream.Send(&playsource.QueueSongRequest{
				Song: &playsource.Song{
					SongId:  int32(i),
					Name:    songs[i].Name,
					Artists: songs[i].Artists,
				},
			})
			checkErr(err)

			i++
			inFlight++
		}

		resp, err := stream.Recv()
		checkErr(err)

		inFlight--
		if inFlight < 0 {
			log.Fatalf("Negative in flight requests")
		}

		if resp.Finished {
			log.Println("Finished:", songs[resp.SongId])
		} else if !resp.Found {
			log.Println("Not Found:", songs[resp.SongId])
		} else if !resp.Queued {
			log.Println("Not Queued (possible overqueue?):", songs[resp.SongId])
		}
	}
}
func TestQueueLoop(t *testing.T) {
	lis, err := net.Listen("tcp", "localhost:0")
	assert.NoError(t, err)

	grpcServer := grpc.NewServer()
	playsource.RegisterPlaySourceServer(
		grpcServer,
		NewTestServer(10, 0.8, 3*time.Second),
	)

	go grpcServer.Serve(lis)
	defer grpcServer.Stop()

	conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure())
	assert.NoError(t, err)
	defer conn.Close()

	c := playsource.NewPlaySourceClient(conn)

	// The general approach here is that we can keep queueing up to
	// a certain amount of songs (bounded by service). However, as a
	// client, we want to perform a local bound of how many songs we
	// queue, or have 'in-flight'. That is, we must track queue acks
	// and finished acks to determine when to send queue requests.
	// This is very similar to the networks algorithm. Funny how things
	// actually work.
	stream, err := c.QueueSong(context.Background())
	assert.NoError(t, err)

	var inFlight int

	for i := 0; i < 100; {
		for inFlight < 3 {
			log.Println("Sending request: ", i)
			err := stream.Send(&playsource.QueueSongRequest{
				Song: &playsource.Song{
					SongId:  int32(i),
					Name:    strconv.Itoa(i),
					Artists: []string{"a", "b", "c"},
				},
			})
			require.NoError(t, err)
			i++
			inFlight++
		}

		resp, err := stream.Recv()
		require.NoError(t, err)

		inFlight--
		if resp.Finished {
			log.Printf("Song %v finished playing", resp.SongId)
		} else if !resp.Found {
			log.Println("could not find song:", resp.SongId)
		}
	}
}