mirror of
https://github.com/elyby/chrly.git
synced 2024-12-24 05:59:54 +05:30
#1: Add storage integration
This commit is contained in:
parent
abea94a41f
commit
b1e18d0d01
@ -39,9 +39,9 @@ func TestDequeueN(t *testing.T) {
|
|||||||
assert.True(s.IsEmpty())
|
assert.True(s.IsEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
func createQueue() jobsQueue {
|
func createQueue() *jobsQueue {
|
||||||
s := jobsQueue{}
|
queue := &jobsQueue{}
|
||||||
s.New()
|
queue.New()
|
||||||
|
|
||||||
return s
|
return queue
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,17 @@ func (ctx *JobsQueue) GetTexturesForUsername(username string) chan *mojang.Signe
|
|||||||
})
|
})
|
||||||
|
|
||||||
responseChan := make(chan *mojang.SignedTexturesResponse)
|
responseChan := make(chan *mojang.SignedTexturesResponse)
|
||||||
|
|
||||||
|
cachedResult := ctx.Storage.Get(username)
|
||||||
|
if cachedResult != nil {
|
||||||
|
go func() {
|
||||||
|
responseChan <- cachedResult
|
||||||
|
close(responseChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return responseChan
|
||||||
|
}
|
||||||
|
|
||||||
isFirstListener := ctx.broadcast.AddListener(username, responseChan)
|
isFirstListener := ctx.broadcast.AddListener(username, responseChan)
|
||||||
if isFirstListener {
|
if isFirstListener {
|
||||||
resultChan := make(chan *mojang.SignedTexturesResponse)
|
resultChan := make(chan *mojang.SignedTexturesResponse)
|
||||||
@ -39,6 +50,7 @@ func (ctx *JobsQueue) GetTexturesForUsername(username string) chan *mojang.Signe
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
result := <-resultChan
|
result := <-resultChan
|
||||||
|
close(resultChan)
|
||||||
ctx.broadcast.BroadcastAndRemove(username, result)
|
ctx.broadcast.BroadcastAndRemove(username, result)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -108,11 +120,11 @@ func (ctx *JobsQueue) queueRound() {
|
|||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
|
|
||||||
job.RespondTo <- result
|
if shouldCache && result != nil {
|
||||||
|
ctx.Storage.Set(result)
|
||||||
if shouldCache {
|
|
||||||
// TODO: store result to cache
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
job.RespondTo <- result
|
||||||
}(job)
|
}(job)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +36,28 @@ func (o *MojangApiMocks) UuidToTextures(uuid string, signed bool) (*mojang.Signe
|
|||||||
return result, args.Error(1)
|
return result, args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MockStorage struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) Get(username string) *mojang.SignedTexturesResponse {
|
||||||
|
args := m.Called(username)
|
||||||
|
var result *mojang.SignedTexturesResponse
|
||||||
|
if casted, ok := args.Get(0).(*mojang.SignedTexturesResponse); ok {
|
||||||
|
result = casted
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) Set(textures *mojang.SignedTexturesResponse) {
|
||||||
|
m.Called(textures)
|
||||||
|
}
|
||||||
|
|
||||||
type QueueTestSuite struct {
|
type QueueTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
Queue *JobsQueue
|
Queue *JobsQueue
|
||||||
|
Storage *MockStorage
|
||||||
MojangApi *MojangApiMocks
|
MojangApi *MojangApiMocks
|
||||||
Iterate func()
|
Iterate func()
|
||||||
|
|
||||||
@ -51,7 +70,9 @@ func (suite *QueueTestSuite) SetupSuite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) SetupTest() {
|
func (suite *QueueTestSuite) SetupTest() {
|
||||||
suite.Queue = &JobsQueue{}
|
suite.Storage = &MockStorage{}
|
||||||
|
|
||||||
|
suite.Queue = &JobsQueue{Storage: suite.Storage}
|
||||||
|
|
||||||
suite.iterateChan = make(chan bool)
|
suite.iterateChan = make(chan bool)
|
||||||
forever = func() bool {
|
forever = func() bool {
|
||||||
@ -74,49 +95,48 @@ func (suite *QueueTestSuite) SetupTest() {
|
|||||||
func (suite *QueueTestSuite) TearDownTest() {
|
func (suite *QueueTestSuite) TearDownTest() {
|
||||||
suite.done()
|
suite.done()
|
||||||
suite.MojangApi.AssertExpectations(suite.T())
|
suite.MojangApi.AssertExpectations(suite.T())
|
||||||
|
suite.Storage.AssertExpectations(suite.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestReceiveTexturesForOneUsername() {
|
func (suite *QueueTestSuite) TestReceiveTexturesForOneUsername() {
|
||||||
|
expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}
|
||||||
|
|
||||||
|
suite.Storage.On("Get", mock.Anything).Return(nil)
|
||||||
|
suite.Storage.On("Set", expectedResult).Once()
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
||||||
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
||||||
}, nil)
|
}, nil)
|
||||||
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(
|
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(expectedResult, nil)
|
||||||
&mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
resultChan := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
|
|
||||||
suite.Iterate()
|
suite.Iterate()
|
||||||
|
|
||||||
result := <-resultChan
|
result := <-resultChan
|
||||||
if suite.Assert().NotNil(result) {
|
suite.Assert().Equal(expectedResult, result)
|
||||||
suite.Assert().Equal("0d252b7218b648bfb86c2ae476954d32", result.Id)
|
|
||||||
suite.Assert().Equal("maksimkurb", result.Name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestReceiveTexturesForFewUsernames() {
|
func (suite *QueueTestSuite) TestReceiveTexturesForFewUsernames() {
|
||||||
|
expectedResult1 := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}
|
||||||
|
expectedResult2 := &mojang.SignedTexturesResponse{Id: "4566e69fc90748ee8d71d7ba5aa00d20", Name: "Thinkofdeath"}
|
||||||
|
|
||||||
|
suite.Storage.On("Get", mock.Anything).Return(nil)
|
||||||
|
suite.Storage.On("Set", expectedResult1).Once()
|
||||||
|
suite.Storage.On("Set", expectedResult2).Once()
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb", "Thinkofdeath"}).Once().Return([]*mojang.ProfileInfo{
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb", "Thinkofdeath"}).Once().Return([]*mojang.ProfileInfo{
|
||||||
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
||||||
{Id: "4566e69fc90748ee8d71d7ba5aa00d20", Name: "Thinkofdeath"},
|
{Id: "4566e69fc90748ee8d71d7ba5aa00d20", Name: "Thinkofdeath"},
|
||||||
}, nil)
|
}, nil)
|
||||||
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(
|
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(expectedResult1, nil)
|
||||||
&mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
suite.MojangApi.On("UuidToTextures", "4566e69fc90748ee8d71d7ba5aa00d20", true).Once().Return(expectedResult2, nil)
|
||||||
nil,
|
|
||||||
)
|
|
||||||
suite.MojangApi.On("UuidToTextures", "4566e69fc90748ee8d71d7ba5aa00d20", true).Once().Return(
|
|
||||||
&mojang.SignedTexturesResponse{Id: "4566e69fc90748ee8d71d7ba5aa00d20", Name: "Thinkofdeath"},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
resultChan1 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan1 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
resultChan2 := suite.Queue.GetTexturesForUsername("Thinkofdeath")
|
resultChan2 := suite.Queue.GetTexturesForUsername("Thinkofdeath")
|
||||||
|
|
||||||
suite.Iterate()
|
suite.Iterate()
|
||||||
|
|
||||||
suite.Assert().NotNil(<-resultChan1)
|
suite.Assert().Equal(expectedResult1, <-resultChan1)
|
||||||
suite.Assert().NotNil(<-resultChan2)
|
suite.Assert().Equal(expectedResult2, <-resultChan2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestReceiveTexturesForMoreThan100Usernames() {
|
func (suite *QueueTestSuite) TestReceiveTexturesForMoreThan100Usernames() {
|
||||||
@ -125,6 +145,8 @@ func (suite *QueueTestSuite) TestReceiveTexturesForMoreThan100Usernames() {
|
|||||||
usernames[i] = randStr(8)
|
usernames[i] = randStr(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suite.Storage.On("Get", mock.Anything).Times(120).Return(nil)
|
||||||
|
// Storage.Set shouldn't be called
|
||||||
suite.MojangApi.On("UsernameToUuids", usernames[0:100]).Once().Return([]*mojang.ProfileInfo{}, nil)
|
suite.MojangApi.On("UsernameToUuids", usernames[0:100]).Once().Return([]*mojang.ProfileInfo{}, nil)
|
||||||
suite.MojangApi.On("UsernameToUuids", usernames[100:120]).Once().Return([]*mojang.ProfileInfo{}, nil)
|
suite.MojangApi.On("UsernameToUuids", usernames[100:120]).Once().Return([]*mojang.ProfileInfo{}, nil)
|
||||||
|
|
||||||
@ -137,41 +159,36 @@ func (suite *QueueTestSuite) TestReceiveTexturesForMoreThan100Usernames() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestReceiveTexturesForTheSameUsernames() {
|
func (suite *QueueTestSuite) TestReceiveTexturesForTheSameUsernames() {
|
||||||
|
expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}
|
||||||
|
|
||||||
|
suite.Storage.On("Get", mock.Anything).Twice().Return(nil)
|
||||||
|
suite.Storage.On("Set", expectedResult).Once()
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
||||||
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
||||||
}, nil)
|
}, nil)
|
||||||
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(
|
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(expectedResult, nil)
|
||||||
&mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
resultChan1 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan1 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
resultChan2 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan2 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
|
|
||||||
suite.Iterate()
|
suite.Iterate()
|
||||||
|
|
||||||
result1 := <-resultChan1
|
suite.Assert().Equal(expectedResult, <-resultChan1)
|
||||||
result2 := <-resultChan2
|
suite.Assert().Equal(expectedResult, <-resultChan2)
|
||||||
|
|
||||||
if suite.Assert().NotNil(result1) {
|
|
||||||
suite.Assert().Equal("0d252b7218b648bfb86c2ae476954d32", result1.Id)
|
|
||||||
suite.Assert().Equal("maksimkurb", result1.Name)
|
|
||||||
|
|
||||||
suite.Assert().Equal(result1, result2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestReceiveTexturesForUsernameThatAlreadyProcessing() {
|
func (suite *QueueTestSuite) TestReceiveTexturesForUsernameThatAlreadyProcessing() {
|
||||||
|
expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}
|
||||||
|
|
||||||
|
suite.Storage.On("Get", mock.Anything).Return(nil)
|
||||||
|
suite.Storage.On("Set", expectedResult).Once()
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
||||||
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
||||||
}, nil)
|
}, nil)
|
||||||
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).
|
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).
|
||||||
Once().
|
Once().
|
||||||
After(10*time.Millisecond). // Simulate long round trip
|
After(10*time.Millisecond). // Simulate long round trip
|
||||||
Return(
|
Return(expectedResult, nil)
|
||||||
&mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
resultChan1 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan1 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
|
|
||||||
@ -183,18 +200,13 @@ func (suite *QueueTestSuite) TestReceiveTexturesForUsernameThatAlreadyProcessing
|
|||||||
|
|
||||||
resultChan2 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan2 := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
|
|
||||||
result1 := <-resultChan1
|
suite.Assert().Equal(expectedResult, <-resultChan1)
|
||||||
result2 := <-resultChan2
|
suite.Assert().Equal(expectedResult, <-resultChan2)
|
||||||
|
|
||||||
if suite.Assert().NotNil(result1) {
|
|
||||||
suite.Assert().Equal("0d252b7218b648bfb86c2ae476954d32", result1.Id)
|
|
||||||
suite.Assert().Equal("maksimkurb", result1.Name)
|
|
||||||
|
|
||||||
suite.Assert().Equal(result1, result2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestDoNothingWhenNoTasks() {
|
func (suite *QueueTestSuite) TestDoNothingWhenNoTasks() {
|
||||||
|
suite.Storage.On("Get", mock.Anything).Return(nil)
|
||||||
|
// Storage.Set shouldn't be called
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{}, nil)
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{}, nil)
|
||||||
|
|
||||||
// Perform first iteration and await it finish
|
// Perform first iteration and await it finish
|
||||||
@ -210,6 +222,8 @@ func (suite *QueueTestSuite) TestDoNothingWhenNoTasks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestHandle429ResponseWhenExchangingUsernamesToUuids() {
|
func (suite *QueueTestSuite) TestHandle429ResponseWhenExchangingUsernamesToUuids() {
|
||||||
|
suite.Storage.On("Get", mock.Anything).Return(nil)
|
||||||
|
// Storage.Set shouldn't be called
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return(nil, &mojang.TooManyRequestsError{})
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return(nil, &mojang.TooManyRequestsError{})
|
||||||
|
|
||||||
resultChan := suite.Queue.GetTexturesForUsername("maksimkurb")
|
resultChan := suite.Queue.GetTexturesForUsername("maksimkurb")
|
||||||
@ -220,6 +234,8 @@ func (suite *QueueTestSuite) TestHandle429ResponseWhenExchangingUsernamesToUuids
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QueueTestSuite) TestHandle429ResponseWhenRequestingUsersTextures() {
|
func (suite *QueueTestSuite) TestHandle429ResponseWhenRequestingUsersTextures() {
|
||||||
|
suite.Storage.On("Get", mock.Anything).Return(nil)
|
||||||
|
// Storage.Set shouldn't be called
|
||||||
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
|
||||||
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user