Ensure that queue for Mojang textures provider is initialized before any job will be scheduled

This commit is contained in:
ErickSkrauch 2020-05-01 17:36:37 +03:00
parent dfe024756e
commit fd05220299
2 changed files with 37 additions and 36 deletions

View File

@ -130,7 +130,7 @@ func NewFullBusStrategy(delay time.Duration, batch int) *FullBusStrategy {
func (ctx *FullBusStrategy) Queue(job *job) { func (ctx *FullBusStrategy) Queue(job *job) {
n := ctx.queue.Enqueue(job) n := ctx.queue.Enqueue(job)
if n % ctx.Batch == 0 { if n%ctx.Batch == 0 {
ctx.busIsFull <- true ctx.busIsFull <- true
} }
} }
@ -194,8 +194,12 @@ func (ctx *BatchUuidsProvider) GetUuid(username string) (*mojang.ProfileInfo, er
} }
func (ctx *BatchUuidsProvider) startQueue() { func (ctx *BatchUuidsProvider) startQueue() {
// This synchronization chan is used to ensure that strategy's jobs provider
// will be initialized before any job will be scheduled
d := make(chan struct{})
go func() { go func() {
jobsChan := ctx.strategy.GetJobs(ctx.context) jobsChan := ctx.strategy.GetJobs(ctx.context)
close(d)
for { for {
select { select {
case <-ctx.context.Done(): case <-ctx.context.Done():
@ -208,6 +212,8 @@ func (ctx *BatchUuidsProvider) startQueue() {
} }
} }
}() }()
<-d
} }
func (ctx *BatchUuidsProvider) performRequest(iteration *JobsIteration) { func (ctx *BatchUuidsProvider) performRequest(iteration *JobsIteration) {

View File

@ -105,8 +105,33 @@ type batchUuidsProviderTestSuite struct {
Strategy *manualStrategy Strategy *manualStrategy
MojangApi *mojangUsernamesToUuidsRequestMock MojangApi *mojangUsernamesToUuidsRequestMock
GetUuidAsync func(username string) <-chan *batchUuidsProviderGetUuidResult stop context.CancelFunc
stop context.CancelFunc }
func (suite *batchUuidsProviderTestSuite) GetUuidAsync(username string) <-chan *batchUuidsProviderGetUuidResult {
s := make(chan struct{})
// This dirty hack ensures, that the username will be queued before we return control to the caller.
// It's needed to keep expected calls order and prevent cases when iteration happens before
// all usernames will be queued.
suite.Emitter.On("Emit",
"mojang_textures:batch_uuids_provider:queued",
username,
).Once().Run(func(args mock.Arguments) {
close(s)
})
c := make(chan *batchUuidsProviderGetUuidResult)
go func() {
profile, err := suite.Provider.GetUuid(username)
c <- &batchUuidsProviderGetUuidResult{
Result: profile,
Error: err,
}
}()
<-s
return c
} }
func (suite *batchUuidsProviderTestSuite) SetupTest() { func (suite *batchUuidsProviderTestSuite) SetupTest() {
@ -118,32 +143,6 @@ func (suite *batchUuidsProviderTestSuite) SetupTest() {
usernamesToUuids = suite.MojangApi.UsernamesToUuids usernamesToUuids = suite.MojangApi.UsernamesToUuids
suite.Provider = NewBatchUuidsProvider(ctx, suite.Strategy, suite.Emitter) suite.Provider = NewBatchUuidsProvider(ctx, suite.Strategy, suite.Emitter)
suite.GetUuidAsync = func(username string) <-chan *batchUuidsProviderGetUuidResult {
s := make(chan struct{})
// This dirty hack ensures, that the username will be queued before we return control to the caller.
// It's needed to keep expected calls order and prevent cases when iteration happens before
// all usernames will be queued.
suite.Emitter.On("Emit",
"mojang_textures:batch_uuids_provider:queued",
username,
).Once().Run(func(args mock.Arguments) {
close(s)
})
c := make(chan *batchUuidsProviderGetUuidResult)
go func() {
profile, err := suite.Provider.GetUuid(username)
c <- &batchUuidsProviderGetUuidResult{
Result: profile,
Error: err,
}
}()
<-s
return c
}
} }
func (suite *batchUuidsProviderTestSuite) TearDownTest() { func (suite *batchUuidsProviderTestSuite) TearDownTest() {
@ -196,15 +195,11 @@ func (suite *batchUuidsProviderTestSuite) TestShouldNotSendRequestWhenNoJobsAreR
close(done) close(done)
}) })
r := suite.GetUuidAsync("username") // Schedule one username to run the queue suite.GetUuidAsync("username") // Schedule one username to run the queue
suite.Strategy.Iterate(0, 1) // Return no jobs and indicate that there is one job in queue suite.Strategy.Iterate(0, 1) // Return no jobs and indicate that there is one job in queue
select {
case <-r: <-done
// fail
case <-done:
return
}
} }
// Test written for multiple usernames to ensure that the error // Test written for multiple usernames to ensure that the error