diff --git a/cmd/worker.go b/cmd/worker.go index 9bec0ca..119ca4d 100644 --- a/cmd/worker.go +++ b/cmd/worker.go @@ -56,9 +56,16 @@ var workerCmd = &cobra.Command{ handler.Handle("/healthcheck", healthcheck.Handler( healthcheck.WithChecker( "mojang-batch-uuids-provider-response", - eventsubscribers.MojangBatchUuidsProviderChecker( + eventsubscribers.MojangBatchUuidsProviderResponseChecker( dispatcher, - viper.GetDuration("healthcheck.mojang_batch_uuids_provider_cool_down"), + viper.GetDuration("healthcheck.mojang_batch_uuids_provider_cool_down_duration"), + ), + ), + healthcheck.WithChecker( + "mojang-batch-uuids-provider-queue-length", + eventsubscribers.MojangBatchUuidsProviderQueueLengthChecker( + dispatcher, + viper.GetInt("healthcheck.mojang_batch_uuids_provider_queue_length_limit"), ), ), )).Methods("GET") @@ -84,5 +91,6 @@ var workerCmd = &cobra.Command{ func init() { RootCmd.AddCommand(workerCmd) - viper.SetDefault("healthcheck.mojang_batch_uuids_provider_cool_down", time.Minute) + viper.SetDefault("healthcheck.mojang_batch_uuids_provider_cool_down_duration", time.Minute) + viper.SetDefault("healthcheck.mojang_batch_uuids_provider_queue_length_limit", 50) } diff --git a/eventsubscribers/health_checkers.go b/eventsubscribers/health_checkers.go index e002514..9c33db4 100644 --- a/eventsubscribers/health_checkers.go +++ b/eventsubscribers/health_checkers.go @@ -2,6 +2,7 @@ package eventsubscribers import ( "context" + "errors" "sync" "time" @@ -10,7 +11,7 @@ import ( "github.com/elyby/chrly/api/mojang" ) -func MojangBatchUuidsProviderChecker(dispatcher Subscriber, resetDuration time.Duration) healthcheck.CheckerFunc { +func MojangBatchUuidsProviderResponseChecker(dispatcher Subscriber, resetDuration time.Duration) healthcheck.CheckerFunc { var mutex sync.Mutex var lastCallErr error var expireTimer *time.Timer @@ -40,3 +41,24 @@ func MojangBatchUuidsProviderChecker(dispatcher Subscriber, resetDuration time.D return lastCallErr } } + +func MojangBatchUuidsProviderQueueLengthChecker(dispatcher Subscriber, maxLength int) healthcheck.CheckerFunc { + var mutex sync.Mutex + queueLength := 0 + dispatcher.Subscribe("mojang_textures:batch_uuids_provider:round", func(usernames []string, tasksInQueue int) { + mutex.Lock() + queueLength = tasksInQueue + mutex.Unlock() + }) + + return func(ctx context.Context) error { + mutex.Lock() + defer mutex.Unlock() + + if queueLength < maxLength { + return nil + } + + return errors.New("the maximum number of tasks in the queue has been exceeded") + } +} diff --git a/eventsubscribers/health_checkers_test.go b/eventsubscribers/health_checkers_test.go index 4d437e0..d2df137 100644 --- a/eventsubscribers/health_checkers_test.go +++ b/eventsubscribers/health_checkers_test.go @@ -15,20 +15,20 @@ import ( func TestMojangBatchUuidsProviderChecker(t *testing.T) { t.Run("empty state", func(t *testing.T) { dispatcher := bootstrap.CreateEventDispatcher() - checker := MojangBatchUuidsProviderChecker(dispatcher, time.Millisecond) + checker := MojangBatchUuidsProviderResponseChecker(dispatcher, time.Millisecond) assert.Nil(t, checker(context.Background())) }) t.Run("when no error occurred", func(t *testing.T) { dispatcher := bootstrap.CreateEventDispatcher() - checker := MojangBatchUuidsProviderChecker(dispatcher, time.Millisecond) + checker := MojangBatchUuidsProviderResponseChecker(dispatcher, time.Millisecond) dispatcher.Emit("mojang_textures:batch_uuids_provider:result", []string{"username"}, []*mojang.ProfileInfo{}, nil) assert.Nil(t, checker(context.Background())) }) t.Run("when error occurred", func(t *testing.T) { dispatcher := bootstrap.CreateEventDispatcher() - checker := MojangBatchUuidsProviderChecker(dispatcher, time.Millisecond) + checker := MojangBatchUuidsProviderResponseChecker(dispatcher, time.Millisecond) err := errors.New("some error occurred") dispatcher.Emit("mojang_textures:batch_uuids_provider:result", []string{"username"}, nil, err) assert.Equal(t, err, checker(context.Background())) @@ -36,7 +36,7 @@ func TestMojangBatchUuidsProviderChecker(t *testing.T) { t.Run("should reset value after passed duration", func(t *testing.T) { dispatcher := bootstrap.CreateEventDispatcher() - checker := MojangBatchUuidsProviderChecker(dispatcher, 20*time.Millisecond) + checker := MojangBatchUuidsProviderResponseChecker(dispatcher, 20*time.Millisecond) err := errors.New("some error occurred") dispatcher.Emit("mojang_textures:batch_uuids_provider:result", []string{"username"}, nil, err) assert.Equal(t, err, checker(context.Background())) @@ -44,3 +44,28 @@ func TestMojangBatchUuidsProviderChecker(t *testing.T) { assert.Nil(t, checker(context.Background())) }) } + +func TestMojangBatchUuidsProviderQueueLengthChecker(t *testing.T) { + t.Run("empty state", func(t *testing.T) { + dispatcher := bootstrap.CreateEventDispatcher() + checker := MojangBatchUuidsProviderQueueLengthChecker(dispatcher, 10) + assert.Nil(t, checker(context.Background())) + }) + + t.Run("less than allowed limit", func(t *testing.T) { + dispatcher := bootstrap.CreateEventDispatcher() + checker := MojangBatchUuidsProviderQueueLengthChecker(dispatcher, 10) + dispatcher.Emit("mojang_textures:batch_uuids_provider:round", []string{"username"}, 9) + assert.Nil(t, checker(context.Background())) + }) + + t.Run("greater than allowed limit", func(t *testing.T) { + dispatcher := bootstrap.CreateEventDispatcher() + checker := MojangBatchUuidsProviderQueueLengthChecker(dispatcher, 10) + dispatcher.Emit("mojang_textures:batch_uuids_provider:round", []string{"username"}, 10) + checkResult := checker(context.Background()) + if assert.Error(t, checkResult) { + assert.Equal(t, "the maximum number of tasks in the queue has been exceeded", checkResult.Error()) + } + }) +}