mirror of
https://github.com/elyby/chrly.git
synced 2024-12-23 05:30:06 +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 params: `MOJANG_API_BASE_URL` and `MOJANG_SESSION_SERVER_BASE_URL`, that allow you to spoof
|
||||
Mojang API base addresses.
|
||||
- New health checker, that ensures that response for textures provider from Mojang's API is valid.
|
||||
|
||||
### Fixed
|
||||
- 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(
|
||||
container *di.Container,
|
||||
config *viper.Viper,
|
||||
emitter mojangtextures.Emitter,
|
||||
) (*mojangtextures.RemoteApiUuidsProvider, error) {
|
||||
@ -197,6 +198,20 @@ func newMojangTexturesRemoteUUIDsProvider(
|
||||
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{
|
||||
Emitter: emitter,
|
||||
Url: *remoteUrl,
|
||||
|
@ -32,33 +32,16 @@ func DatabaseChecker(connection Pingable) healthcheck.CheckerFunc {
|
||||
}
|
||||
|
||||
func MojangBatchUuidsProviderResponseChecker(dispatcher Subscriber, resetDuration time.Duration) healthcheck.CheckerFunc {
|
||||
var mutex sync.Mutex
|
||||
var lastCallErr error
|
||||
var expireTimer *time.Timer
|
||||
errHolder := &expiringErrHolder{D: resetDuration}
|
||||
dispatcher.Subscribe(
|
||||
"mojang_textures:batch_uuids_provider:result",
|
||||
func(usernames []string, profiles []*mojang.ProfileInfo, err error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
lastCallErr = err
|
||||
if expireTimer != nil {
|
||||
expireTimer.Stop()
|
||||
}
|
||||
|
||||
expireTimer = time.AfterFunc(resetDuration, func() {
|
||||
mutex.Lock()
|
||||
lastCallErr = nil
|
||||
mutex.Unlock()
|
||||
})
|
||||
errHolder.Set(err)
|
||||
},
|
||||
)
|
||||
|
||||
return func(ctx context.Context) error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
return lastCallErr
|
||||
return errHolder.Get()
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,3 +65,47 @@ func MojangBatchUuidsProviderQueueLengthChecker(dispatcher Subscriber, maxLength
|
||||
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)
|
||||
assert.Nil(t, checker(context.Background()))
|
||||
})
|
||||
//
|
||||
|
||||
t.Run("when no error occurred", func(t *testing.T) {
|
||||
d := dispatcher.New()
|
||||
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)
|
||||
})
|
||||
|
||||
_ = 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
|
||||
<-done
|
||||
select {
|
||||
case <-r:
|
||||
// fail
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
ctx.Emit("mojang_textures:mojang_api_textures_provider:before_request", uuid)
|
||||
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
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ func (suite *mojangApiTexturesProviderTestSuite) TestGetTextures() {
|
||||
).Once()
|
||||
suite.Emitter.On("Emit",
|
||||
"mojang_textures:mojang_api_textures_provider:after_request",
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
expectedResult,
|
||||
nil,
|
||||
).Once()
|
||||
@ -85,6 +86,7 @@ func (suite *mojangApiTexturesProviderTestSuite) TestGetTexturesWithError() {
|
||||
).Once()
|
||||
suite.Emitter.On("Emit",
|
||||
"mojang_textures:mojang_api_textures_provider:after_request",
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
expectedResponse,
|
||||
expectedError,
|
||||
).Once()
|
||||
|
Loading…
Reference in New Issue
Block a user