mirror of
https://github.com/elyby/chrly.git
synced 2024-11-26 16:51:59 +05:30
Implemented health checker for textures provider from Mojang's API
This commit is contained in:
parent
2ea094bbf6
commit
4c21fc5c90
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- New configuration param `QUEUE_STRATEGY` with the default value `periodic`.
|
- New configuration param `QUEUE_STRATEGY` with the default value `periodic`.
|
||||||
- New configuration params: `MOJANG_API_BASE_URL` and `MOJANG_SESSION_SERVER_BASE_URL`, that allow you to spoof
|
- New configuration params: `MOJANG_API_BASE_URL` and `MOJANG_SESSION_SERVER_BASE_URL`, that allow you to spoof
|
||||||
Mojang API base addresses.
|
Mojang API base addresses.
|
||||||
|
- New health checker, that ensures that response for textures provider from Mojang's API is valid.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Handle the case when there is no textures property in Mojang's response.
|
- Handle the case when there is no textures property in Mojang's response.
|
||||||
|
@ -189,6 +189,7 @@ func newMojangTexturesBatchUUIDsProviderFullBusStrategy(config *viper.Viper) *mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newMojangTexturesRemoteUUIDsProvider(
|
func newMojangTexturesRemoteUUIDsProvider(
|
||||||
|
container *di.Container,
|
||||||
config *viper.Viper,
|
config *viper.Viper,
|
||||||
emitter mojangtextures.Emitter,
|
emitter mojangtextures.Emitter,
|
||||||
) (*mojangtextures.RemoteApiUuidsProvider, error) {
|
) (*mojangtextures.RemoteApiUuidsProvider, error) {
|
||||||
@ -197,6 +198,20 @@ func newMojangTexturesRemoteUUIDsProvider(
|
|||||||
return nil, fmt.Errorf("unable to parse remote url: %w", err)
|
return nil, fmt.Errorf("unable to parse remote url: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := container.Provide(func(emitter es.Subscriber, config *viper.Viper) *namedHealthChecker {
|
||||||
|
config.SetDefault("healthcheck.mojang_api_textures_provider_cool_down_duration", time.Minute+10*time.Second)
|
||||||
|
|
||||||
|
return &namedHealthChecker{
|
||||||
|
Name: "mojang-api-textures-provider-response-checker",
|
||||||
|
Checker: es.MojangApiTexturesProviderResponseChecker(
|
||||||
|
emitter,
|
||||||
|
config.GetDuration("healthcheck.mojang_api_textures_provider_cool_down_duration"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &mojangtextures.RemoteApiUuidsProvider{
|
return &mojangtextures.RemoteApiUuidsProvider{
|
||||||
Emitter: emitter,
|
Emitter: emitter,
|
||||||
Url: *remoteUrl,
|
Url: *remoteUrl,
|
||||||
|
@ -32,33 +32,16 @@ func DatabaseChecker(connection Pingable) healthcheck.CheckerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MojangBatchUuidsProviderResponseChecker(dispatcher Subscriber, resetDuration time.Duration) healthcheck.CheckerFunc {
|
func MojangBatchUuidsProviderResponseChecker(dispatcher Subscriber, resetDuration time.Duration) healthcheck.CheckerFunc {
|
||||||
var mutex sync.Mutex
|
errHolder := &expiringErrHolder{D: resetDuration}
|
||||||
var lastCallErr error
|
|
||||||
var expireTimer *time.Timer
|
|
||||||
dispatcher.Subscribe(
|
dispatcher.Subscribe(
|
||||||
"mojang_textures:batch_uuids_provider:result",
|
"mojang_textures:batch_uuids_provider:result",
|
||||||
func(usernames []string, profiles []*mojang.ProfileInfo, err error) {
|
func(usernames []string, profiles []*mojang.ProfileInfo, err error) {
|
||||||
mutex.Lock()
|
errHolder.Set(err)
|
||||||
defer mutex.Unlock()
|
|
||||||
|
|
||||||
lastCallErr = err
|
|
||||||
if expireTimer != nil {
|
|
||||||
expireTimer.Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
expireTimer = time.AfterFunc(resetDuration, func() {
|
|
||||||
mutex.Lock()
|
|
||||||
lastCallErr = nil
|
|
||||||
mutex.Unlock()
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
mutex.Lock()
|
return errHolder.Get()
|
||||||
defer mutex.Unlock()
|
|
||||||
|
|
||||||
return lastCallErr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,3 +65,47 @@ func MojangBatchUuidsProviderQueueLengthChecker(dispatcher Subscriber, maxLength
|
|||||||
return errors.New("the maximum number of tasks in the queue has been exceeded")
|
return errors.New("the maximum number of tasks in the queue has been exceeded")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MojangApiTexturesProviderResponseChecker(dispatcher Subscriber, resetDuration time.Duration) healthcheck.CheckerFunc {
|
||||||
|
errHolder := &expiringErrHolder{D: resetDuration}
|
||||||
|
dispatcher.Subscribe(
|
||||||
|
"mojang_textures:mojang_api_textures_provider:after_request",
|
||||||
|
func(uuid string, profile *mojang.SignedTexturesResponse, err error) {
|
||||||
|
errHolder.Set(err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return func(ctx context.Context) error {
|
||||||
|
return errHolder.Get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type expiringErrHolder struct {
|
||||||
|
D time.Duration
|
||||||
|
err error
|
||||||
|
l sync.Mutex
|
||||||
|
t *time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *expiringErrHolder) Get() error {
|
||||||
|
h.l.Lock()
|
||||||
|
defer h.l.Unlock()
|
||||||
|
|
||||||
|
return h.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *expiringErrHolder) Set(err error) {
|
||||||
|
h.l.Lock()
|
||||||
|
defer h.l.Unlock()
|
||||||
|
if h.t != nil {
|
||||||
|
h.t.Stop()
|
||||||
|
h.t = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
h.err = err
|
||||||
|
if err != nil {
|
||||||
|
h.t = time.AfterFunc(h.D, func() {
|
||||||
|
h.Set(nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -56,7 +56,7 @@ func TestMojangBatchUuidsProviderChecker(t *testing.T) {
|
|||||||
checker := MojangBatchUuidsProviderResponseChecker(d, time.Millisecond)
|
checker := MojangBatchUuidsProviderResponseChecker(d, time.Millisecond)
|
||||||
assert.Nil(t, checker(context.Background()))
|
assert.Nil(t, checker(context.Background()))
|
||||||
})
|
})
|
||||||
//
|
|
||||||
t.Run("when no error occurred", func(t *testing.T) {
|
t.Run("when no error occurred", func(t *testing.T) {
|
||||||
d := dispatcher.New()
|
d := dispatcher.New()
|
||||||
checker := MojangBatchUuidsProviderResponseChecker(d, time.Millisecond)
|
checker := MojangBatchUuidsProviderResponseChecker(d, time.Millisecond)
|
||||||
@ -107,3 +107,40 @@ func TestMojangBatchUuidsProviderQueueLengthChecker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMojangApiTexturesProviderResponseChecker(t *testing.T) {
|
||||||
|
t.Run("empty state", func(t *testing.T) {
|
||||||
|
d := dispatcher.New()
|
||||||
|
checker := MojangApiTexturesProviderResponseChecker(d, time.Millisecond)
|
||||||
|
assert.Nil(t, checker(context.Background()))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when no error occurred", func(t *testing.T) {
|
||||||
|
d := dispatcher.New()
|
||||||
|
checker := MojangApiTexturesProviderResponseChecker(d, time.Millisecond)
|
||||||
|
d.Emit("mojang_textures:mojang_api_textures_provider:after_request",
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
&mojang.SignedTexturesResponse{},
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
assert.Nil(t, checker(context.Background()))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when error occurred", func(t *testing.T) {
|
||||||
|
d := dispatcher.New()
|
||||||
|
checker := MojangApiTexturesProviderResponseChecker(d, time.Millisecond)
|
||||||
|
err := errors.New("some error occurred")
|
||||||
|
d.Emit("mojang_textures:mojang_api_textures_provider:after_request", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", nil, err)
|
||||||
|
assert.Equal(t, err, checker(context.Background()))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should reset value after passed duration", func(t *testing.T) {
|
||||||
|
d := dispatcher.New()
|
||||||
|
checker := MojangApiTexturesProviderResponseChecker(d, 20*time.Millisecond)
|
||||||
|
err := errors.New("some error occurred")
|
||||||
|
d.Emit("mojang_textures:mojang_api_textures_provider:after_request", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", nil, err)
|
||||||
|
assert.Equal(t, err, checker(context.Background()))
|
||||||
|
time.Sleep(40 * time.Millisecond)
|
||||||
|
assert.Nil(t, checker(context.Background()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -196,10 +196,15 @@ func (suite *batchUuidsProviderTestSuite) TestShouldNotSendRequestWhenNoJobsAreR
|
|||||||
close(done)
|
close(done)
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = suite.GetUuidAsync("username") // Schedule one username to run the queue
|
r := 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
|
||||||
<-done
|
select {
|
||||||
|
case <-r:
|
||||||
|
// fail
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test written for multiple usernames to ensure that the error
|
// Test written for multiple usernames to ensure that the error
|
||||||
|
@ -13,7 +13,7 @@ type MojangApiTexturesProvider struct {
|
|||||||
func (ctx *MojangApiTexturesProvider) GetTextures(uuid string) (*mojang.SignedTexturesResponse, error) {
|
func (ctx *MojangApiTexturesProvider) GetTextures(uuid string) (*mojang.SignedTexturesResponse, error) {
|
||||||
ctx.Emit("mojang_textures:mojang_api_textures_provider:before_request", uuid)
|
ctx.Emit("mojang_textures:mojang_api_textures_provider:before_request", uuid)
|
||||||
result, err := uuidToTextures(uuid, true)
|
result, err := uuidToTextures(uuid, true)
|
||||||
ctx.Emit("mojang_textures:mojang_api_textures_provider:after_request", result, err)
|
ctx.Emit("mojang_textures:mojang_api_textures_provider:after_request", uuid, result, err)
|
||||||
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ func (suite *mojangApiTexturesProviderTestSuite) TestGetTextures() {
|
|||||||
).Once()
|
).Once()
|
||||||
suite.Emitter.On("Emit",
|
suite.Emitter.On("Emit",
|
||||||
"mojang_textures:mojang_api_textures_provider:after_request",
|
"mojang_textures:mojang_api_textures_provider:after_request",
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
expectedResult,
|
expectedResult,
|
||||||
nil,
|
nil,
|
||||||
).Once()
|
).Once()
|
||||||
@ -85,6 +86,7 @@ func (suite *mojangApiTexturesProviderTestSuite) TestGetTexturesWithError() {
|
|||||||
).Once()
|
).Once()
|
||||||
suite.Emitter.On("Emit",
|
suite.Emitter.On("Emit",
|
||||||
"mojang_textures:mojang_api_textures_provider:after_request",
|
"mojang_textures:mojang_api_textures_provider:after_request",
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
expectedResponse,
|
expectedResponse,
|
||||||
expectedError,
|
expectedError,
|
||||||
).Once()
|
).Once()
|
||||||
|
Loading…
Reference in New Issue
Block a user