diff --git a/CHANGELOG.md b/CHANGELOG.md index 53b5f9b..66ae8da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Bumped Go version to 1.21. +### Removed +- StatsD metrics: + - Gauges: + - `ely.skinsystem.{hostname}.app.redis.pool.available` + ## [4.6.0] - 2021-03-04 ### Added - `/profile/{username}` endpoint, which returns a profile and its textures, equivalent of the Mojang's diff --git a/db/redis/redis.go b/db/redis/redis.go index f76fa9f..235e84f 100644 --- a/db/redis/redis.go +++ b/db/redis/redis.go @@ -3,6 +3,7 @@ package redis import ( "bytes" "compress/zlib" + "context" "encoding/json" "fmt" "io" @@ -10,23 +11,22 @@ import ( "strings" "time" - "github.com/mediocregopher/radix.v2/pool" - "github.com/mediocregopher/radix.v2/redis" - "github.com/mediocregopher/radix.v2/util" + "github.com/mediocregopher/radix/v4" "github.com/elyby/chrly/model" ) var now = time.Now -func New(addr string, poolSize int) (*Redis, error) { - conn, err := pool.New("tcp", addr, poolSize) +func New(ctx context.Context, addr string, poolSize int) (*Redis, error) { + client, err := (radix.PoolConfig{Size: poolSize}).New(ctx, "tcp", addr) if err != nil { return nil, err } return &Redis{ - pool: conn, + client: client, + context: ctx, }, nil } @@ -34,27 +34,34 @@ const accountIdToUsernameKey = "hash:username-to-account-id" // TODO: this shoul const mojangUsernameToUuidKey = "hash:mojang-username-to-uuid" type Redis struct { - pool *pool.Pool + client radix.Client + context context.Context } func (db *Redis) FindSkinByUsername(username string) (*model.Skin, error) { - conn, err := db.pool.Get() + var skin *model.Skin + err := db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + var err error + skin, err = findByUsername(ctx, conn, username) + + return err + })) + + return skin, err +} + +func findByUsername(ctx context.Context, conn radix.Conn, username string) (*model.Skin, error) { + redisKey := buildUsernameKey(username) + var encodedResult []byte + err := conn.Do(ctx, radix.Cmd(&encodedResult, "GET", redisKey)) if err != nil { return nil, err } - defer db.pool.Put(conn) - return findByUsername(username, conn) -} - -func findByUsername(username string, conn util.Cmder) (*model.Skin, error) { - redisKey := buildUsernameKey(username) - response := conn.Cmd("GET", redisKey) - if response.IsType(redis.Nil) { + if len(encodedResult) == 0 { return nil, nil } - encodedResult, _ := response.Bytes() result, err := zlibDecode(encodedResult) if err != nil { return nil, err @@ -72,56 +79,66 @@ func findByUsername(username string, conn util.Cmder) (*model.Skin, error) { } func (db *Redis) FindSkinByUserId(id int) (*model.Skin, error) { - conn, err := db.pool.Get() + var skin *model.Skin + err := db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + var err error + skin, err = findByUserId(ctx, conn, id) + + return err + })) + + return skin, err +} + +func findByUserId(ctx context.Context, conn radix.Conn, id int) (*model.Skin, error) { + var username string + err := conn.Do(ctx, radix.FlatCmd(&username, "HGET", accountIdToUsernameKey, id)) if err != nil { return nil, err } - defer db.pool.Put(conn) - return findByUserId(id, conn) -} - -func findByUserId(id int, conn util.Cmder) (*model.Skin, error) { - response := conn.Cmd("HGET", accountIdToUsernameKey, id) - if response.IsType(redis.Nil) { + if username == "" { return nil, nil } - username, err := response.Str() - if err != nil { - return nil, err - } - - return findByUsername(username, conn) + return findByUsername(ctx, conn, username) } func (db *Redis) SaveSkin(skin *model.Skin) error { - conn, err := db.pool.Get() + return db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + return save(ctx, conn, skin) + })) +} + +func save(ctx context.Context, conn radix.Conn, skin *model.Skin) error { + err := conn.Do(ctx, radix.Cmd(nil, "MULTI")) if err != nil { return err } - defer db.pool.Put(conn) - - return save(skin, conn) -} - -func save(skin *model.Skin, conn util.Cmder) error { - conn.Cmd("MULTI") // If user has changed username, then we must delete his old username record if skin.OldUsername != "" && skin.OldUsername != skin.Username { - conn.Cmd("DEL", buildUsernameKey(skin.OldUsername)) + err = conn.Do(ctx, radix.Cmd(nil, "DEL", buildUsernameKey(skin.OldUsername))) + if err != nil { + return err + } } // If this is a new record or if the user has changed username, we set the value in the hash table if skin.OldUsername != "" || skin.OldUsername != skin.Username { - conn.Cmd("HSET", accountIdToUsernameKey, skin.UserId, skin.Username) + err = conn.Do(ctx, radix.FlatCmd(nil, "HSET", accountIdToUsernameKey, skin.UserId, skin.Username)) } str, _ := json.Marshal(skin) - conn.Cmd("SET", buildUsernameKey(skin.Username), zlibEncode(str)) + err = conn.Do(ctx, radix.FlatCmd(nil, "SET", buildUsernameKey(skin.Username), zlibEncode(str))) + if err != nil { + return err + } - conn.Cmd("EXEC") + err = conn.Do(ctx, radix.Cmd(nil, "EXEC")) + if err != nil { + return err + } skin.OldUsername = skin.Username @@ -129,45 +146,45 @@ func save(skin *model.Skin, conn util.Cmder) error { } func (db *Redis) RemoveSkinByUserId(id int) error { - conn, err := db.pool.Get() - if err != nil { - return err - } - defer db.pool.Put(conn) - - return removeByUserId(id, conn) + return db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + return removeByUserId(ctx, conn, id) + })) } -func removeByUserId(id int, conn util.Cmder) error { - record, err := findByUserId(id, conn) +func removeByUserId(ctx context.Context, conn radix.Conn, id int) error { + record, err := findByUserId(ctx, conn, id) if err != nil { return err } - conn.Cmd("MULTI") - - conn.Cmd("HDEL", accountIdToUsernameKey, id) - if record != nil { - conn.Cmd("DEL", buildUsernameKey(record.Username)) + err = conn.Do(ctx, radix.Cmd(nil, "MULTI")) + if err != nil { + return err } - conn.Cmd("EXEC") + err = conn.Do(ctx, radix.FlatCmd(nil, "HDEL", accountIdToUsernameKey, id)) + if err != nil { + return err + } - return nil + if record != nil { + err = conn.Do(ctx, radix.Cmd(nil, "DEL", buildUsernameKey(record.Username))) + if err != nil { + return err + } + } + + return conn.Do(ctx, radix.Cmd(nil, "EXEC")) } func (db *Redis) RemoveSkinByUsername(username string) error { - conn, err := db.pool.Get() - if err != nil { - return err - } - defer db.pool.Put(conn) - - return removeByUsername(username, conn) + return db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + return removeByUsername(ctx, conn, username) + })) } -func removeByUsername(username string, conn util.Cmder) error { - record, err := findByUsername(username, conn) +func removeByUsername(ctx context.Context, conn radix.Conn, username string) error { + record, err := findByUsername(ctx, conn, username) if err != nil { return err } @@ -176,45 +193,68 @@ func removeByUsername(username string, conn util.Cmder) error { return nil } - conn.Cmd("MULTI") + err = conn.Do(ctx, radix.Cmd(nil, "MULTI")) + if err != nil { + return err + } - conn.Cmd("DEL", buildUsernameKey(record.Username)) - conn.Cmd("HDEL", accountIdToUsernameKey, record.UserId) + err = conn.Do(ctx, radix.Cmd(nil, "DEL", buildUsernameKey(record.Username))) + if err != nil { + return err + } - conn.Cmd("EXEC") + err = conn.Do(ctx, radix.FlatCmd(nil, "HDEL", accountIdToUsernameKey, record.UserId)) + if err != nil { + return err + } - return nil + return conn.Do(ctx, radix.Cmd(nil, "EXEC")) } func (db *Redis) GetUuid(username string) (string, bool, error) { - conn, err := db.pool.Get() + var uuid string + var found bool + err := db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + var err error + uuid, found, err = findMojangUuidByUsername(ctx, conn, username) + + return err + })) + + return uuid, found, err +} + +func findMojangUuidByUsername(ctx context.Context, conn radix.Conn, username string) (string, bool, error) { + key := strings.ToLower(username) + var result string + err := conn.Do(ctx, radix.Cmd(&result, "HGET", mojangUsernameToUuidKey, key)) if err != nil { return "", false, err } - defer db.pool.Put(conn) - return findMojangUuidByUsername(username, conn) -} - -func findMojangUuidByUsername(username string, conn util.Cmder) (string, bool, error) { - key := strings.ToLower(username) - response := conn.Cmd("HGET", mojangUsernameToUuidKey, key) - if response.IsType(redis.Nil) { + if result == "" { return "", false, nil } - data, _ := response.Str() - parts := strings.Split(data, ":") + parts := strings.Split(result, ":") // https://github.com/elyby/chrly/issues/28 if len(parts) < 2 { - conn.Cmd("HDEL", mojangUsernameToUuidKey, key) - return "", false, fmt.Errorf("Got unexpected response from the mojangUsernameToUuid hash: \"%s\"", data) + err = conn.Do(ctx, radix.Cmd(nil, "HDEL", mojangUsernameToUuidKey, key)) + if err != nil { + return "", false, err + } + + return "", false, fmt.Errorf("got unexpected response from the mojangUsernameToUuid hash: \"%s\"", result) } timestamp, _ := strconv.ParseInt(parts[1], 10, 64) storedAt := time.Unix(timestamp, 0) if storedAt.Add(time.Hour * 24 * 30).Before(now()) { - conn.Cmd("HDEL", mojangUsernameToUuidKey, key) + err = conn.Do(ctx, radix.Cmd(nil, "HDEL", mojangUsernameToUuidKey, key)) + if err != nil { + return "", false, err + } + return "", false, nil } @@ -222,36 +262,23 @@ func findMojangUuidByUsername(username string, conn util.Cmder) (string, bool, e } func (db *Redis) StoreUuid(username string, uuid string) error { - conn, err := db.pool.Get() - if err != nil { - return err - } - defer db.pool.Put(conn) - - return storeMojangUuid(username, uuid, conn) + return db.client.Do(db.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error { + return storeMojangUuid(ctx, conn, username, uuid) + })) } -func storeMojangUuid(username string, uuid string, conn util.Cmder) error { +func storeMojangUuid(ctx context.Context, conn radix.Conn, username string, uuid string) error { value := uuid + ":" + strconv.FormatInt(now().Unix(), 10) - res := conn.Cmd("HSET", mojangUsernameToUuidKey, strings.ToLower(username), value) - if res.IsType(redis.Err) { - return res.Err + err := conn.Do(ctx, radix.Cmd(nil, "HSET", mojangUsernameToUuidKey, strings.ToLower(username), value)) + if err != nil { + return err } return nil } func (db *Redis) Ping() error { - r := db.pool.Cmd("PING") - if r.Err != nil { - return r.Err - } - - return nil -} - -func (db *Redis) Avail() int { - return db.pool.Avail() + return db.client.Do(db.context, radix.Cmd(nil, "PING")) } func buildUsernameKey(username string) string { diff --git a/db/redis/redis_integration_test.go b/db/redis/redis_integration_test.go index 5224ab5..43e4749 100644 --- a/db/redis/redis_integration_test.go +++ b/db/redis/redis_integration_test.go @@ -1,17 +1,16 @@ //go:build redis -// +build redis package redis import ( + "context" "fmt" "os" - "reflect" "strconv" "testing" "time" - "github.com/mediocregopher/radix.v2/redis" + "github.com/mediocregopher/radix/v4" assert "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -36,15 +35,13 @@ func init() { func TestNew(t *testing.T) { t.Run("should connect", func(t *testing.T) { - conn, err := New(redisAddr, 12) + conn, err := New(context.Background(), redisAddr, 12) assert.Nil(t, err) assert.NotNil(t, conn) - internalPool := reflect.ValueOf(conn.pool).Elem().FieldByName("pool") - assert.Equal(t, 12, internalPool.Cap()) }) t.Run("should return error", func(t *testing.T) { - conn, err := New("localhost:12345", 12) // Use localhost to avoid DNS resolution + conn, err := New(context.Background(), "localhost:12345", 12) // Use localhost to avoid DNS resolution assert.Error(t, err) assert.Nil(t, conn) }) @@ -55,21 +52,30 @@ type redisTestSuite struct { Redis *Redis - cmd func(cmd string, args ...interface{}) *redis.Resp + cmd func(cmd string, args ...interface{}) string } func (suite *redisTestSuite) SetupSuite() { - conn, err := New(redisAddr, 10) + ctx := context.Background() + conn, err := New(ctx, redisAddr, 10) if err != nil { panic(fmt.Errorf("cannot establish connection to redis: %w", err)) } suite.Redis = conn - suite.cmd = conn.pool.Cmd + suite.cmd = func(cmd string, args ...interface{}) string { + var result string + err := suite.Redis.client.Do(ctx, radix.FlatCmd(&result, cmd, args...)) + if err != nil { + panic(err) + } + + return result + } } func (suite *redisTestSuite) SetupTest() { - // Cleanup database before the each test + // Cleanup database before each test suite.cmd("FLUSHALL") } @@ -101,7 +107,7 @@ func TestRedis(t *testing.T) { * mojangSignature: "mock-mojang-signature" * } */ -var skinRecord = []byte{ +var skinRecord = string([]byte{ 0x78, 0x9c, 0x5c, 0xce, 0x4b, 0x4a, 0x4, 0x41, 0xc, 0xc6, 0xf1, 0xbb, 0x7c, 0xeb, 0x1a, 0xdb, 0xd6, 0xb2, 0x9c, 0xc9, 0xd, 0x5c, 0x88, 0x8b, 0xd1, 0xb5, 0x84, 0x4e, 0xa6, 0xa7, 0xec, 0x7a, 0xc, 0xf5, 0x0, 0x41, 0xbc, 0xbb, 0xb4, 0xd2, 0xa, 0x2e, 0xf3, 0xe3, 0x9f, 0x90, 0xf, 0xf4, 0xaa, 0xe5, 0x41, 0x40, 0xa3, 0x41, @@ -112,7 +118,7 @@ var skinRecord = []byte{ 0xa0, 0x13, 0x87, 0xaa, 0x6, 0x31, 0xbf, 0x71, 0x9a, 0x9f, 0xf5, 0xbd, 0xf5, 0xa2, 0x15, 0x84, 0x98, 0xa7, 0x65, 0xf7, 0xa3, 0xbb, 0xb6, 0xf1, 0xd6, 0x1d, 0xfd, 0x9c, 0x78, 0xa5, 0x7f, 0x61, 0xfd, 0x75, 0x83, 0xa7, 0x20, 0x2f, 0x7f, 0xff, 0xe2, 0xf3, 0x2b, 0x0, 0x0, 0xff, 0xff, 0x6f, 0xdd, 0x51, 0x71, -} +}) func (suite *redisTestSuite) TestFindSkinByUsername() { suite.RunSubTest("exists record", func() { @@ -198,14 +204,11 @@ func (suite *redisTestSuite) TestSaveSkin() { suite.Require().Nil(err) usernameResp := suite.cmd("GET", "username:mock") - suite.Require().False(usernameResp.IsType(redis.Nil)) - bytes, _ := usernameResp.Bytes() - suite.Require().Equal(skinRecord, bytes) + suite.Require().NotEmpty(usernameResp) + suite.Require().Equal(skinRecord, usernameResp) idResp := suite.cmd("HGET", "hash:username-to-account-id", 1) - suite.Require().False(usernameResp.IsType(redis.Nil)) - str, _ := idResp.Str() - suite.Require().Equal("Mock", str) + suite.Require().Equal("Mock", idResp) }) suite.RunSubTest("save exists record with changed username", func() { @@ -227,9 +230,8 @@ func (suite *redisTestSuite) TestSaveSkin() { suite.Require().Nil(err) usernameResp := suite.cmd("GET", "username:newmock") - suite.Require().False(usernameResp.IsType(redis.Nil)) - bytes, _ := usernameResp.Bytes() - suite.Require().Equal([]byte{ + suite.Require().NotEmpty(usernameResp) + suite.Require().Equal(string([]byte{ 0x78, 0x9c, 0x5c, 0x8e, 0xcb, 0x4e, 0xc3, 0x40, 0xc, 0x45, 0xff, 0xe5, 0xae, 0xa7, 0x84, 0x40, 0x18, 0x5a, 0xff, 0x1, 0xb, 0x60, 0x51, 0x58, 0x23, 0x2b, 0x76, 0xd3, 0x21, 0xf3, 0xa8, 0xe6, 0x21, 0x90, 0x10, 0xff, 0x8e, 0x52, 0x14, 0x90, 0xba, 0xf4, 0xd1, 0xf1, 0xd5, 0xf9, 0x42, 0x2b, 0x9a, 0x1f, 0x4, 0xd4, 0x1b, 0xb4, @@ -241,15 +243,14 @@ func (suite *redisTestSuite) TestSaveSkin() { 0x42, 0x1a, 0xe7, 0xcd, 0x2f, 0xdd, 0xd4, 0x15, 0xaf, 0xde, 0xde, 0x4d, 0x91, 0x17, 0x74, 0x21, 0x96, 0x3f, 0x6e, 0xf0, 0xec, 0xe5, 0xf5, 0x3f, 0xf9, 0xdc, 0xfb, 0xfd, 0x13, 0x0, 0x0, 0xff, 0xff, 0xca, 0xc3, 0x54, 0x25, - }, bytes) + }), usernameResp) oldUsernameResp := suite.cmd("GET", "username:mock") - suite.Require().True(oldUsernameResp.IsType(redis.Nil)) + suite.Require().Empty(oldUsernameResp) idResp := suite.cmd("HGET", "hash:username-to-account-id", 1) - suite.Require().False(usernameResp.IsType(redis.Nil)) - str, _ := idResp.Str() - suite.Require().Equal("NewMock", str) + suite.Require().NotEmpty(usernameResp) + suite.Require().Equal("NewMock", idResp) }) } @@ -262,10 +263,10 @@ func (suite *redisTestSuite) TestRemoveSkinByUserId() { suite.Require().Nil(err) usernameResp := suite.cmd("GET", "username:mock") - suite.Require().True(usernameResp.IsType(redis.Nil)) + suite.Require().Empty(usernameResp) idResp := suite.cmd("HGET", "hash:username-to-account-id", 1) - suite.Require().True(idResp.IsType(redis.Nil)) + suite.Require().Empty(idResp) }) suite.RunSubTest("exists only id", func() { @@ -275,7 +276,7 @@ func (suite *redisTestSuite) TestRemoveSkinByUserId() { suite.Require().Nil(err) idResp := suite.cmd("HGET", "hash:username-to-account-id", 1) - suite.Require().True(idResp.IsType(redis.Nil)) + suite.Require().Empty(idResp) }) suite.RunSubTest("error when querying skin record", func() { @@ -296,10 +297,10 @@ func (suite *redisTestSuite) TestRemoveSkinByUsername() { suite.Require().Nil(err) usernameResp := suite.cmd("GET", "username:mock") - suite.Require().True(usernameResp.IsType(redis.Nil)) + suite.Require().Empty(usernameResp) idResp := suite.cmd("HGET", "hash:username-to-account-id", 1) - suite.Require().True(idResp.IsType(redis.Nil)) + suite.Require().Empty(idResp) }) suite.RunSubTest("exists only username", func() { @@ -309,7 +310,7 @@ func (suite *redisTestSuite) TestRemoveSkinByUsername() { suite.Require().Nil(err) usernameResp := suite.cmd("GET", "username:mock") - suite.Require().True(usernameResp.IsType(redis.Nil)) + suite.Require().Empty(usernameResp) }) suite.RunSubTest("no records", func() { @@ -372,7 +373,7 @@ func (suite *redisTestSuite) TestGetUuid() { suite.Require().Nil(err) resp := suite.cmd("HGET", "hash:mojang-username-to-uuid", "mock") - suite.Require().True(resp.IsType(redis.Nil), "should cleanup expired records") + suite.Require().Empty(resp, "should cleanup expired records") }) suite.RunSubTest("exists, but corrupted record", func() { @@ -388,7 +389,7 @@ func (suite *redisTestSuite) TestGetUuid() { suite.Require().Error(err, "Got unexpected response from the mojangUsernameToUuid hash: \"corrupted value\"") resp := suite.cmd("HGET", "hash:mojang-username-to-uuid", "mock") - suite.Require().True(resp.IsType(redis.Nil), "should cleanup expired records") + suite.Require().Empty(resp, "should cleanup expired records") }) } @@ -402,9 +403,7 @@ func (suite *redisTestSuite) TestStoreUuid() { suite.Require().Nil(err) resp := suite.cmd("HGET", "hash:mojang-username-to-uuid", "mock") - suite.Require().False(resp.IsType(redis.Nil)) - str, _ := resp.Str() - suite.Require().Equal(str, "d3ca513eb3e14946b58047f2bd3530fd:1587435016") + suite.Require().Equal(resp, "d3ca513eb3e14946b58047f2bd3530fd:1587435016") }) suite.RunSubTest("store empty uuid", func() { @@ -416,9 +415,7 @@ func (suite *redisTestSuite) TestStoreUuid() { suite.Require().Nil(err) resp := suite.cmd("HGET", "hash:mojang-username-to-uuid", "mock") - suite.Require().False(resp.IsType(redis.Nil)) - str, _ := resp.Str() - suite.Require().Equal(str, ":1587435016") + suite.Require().Equal(resp, ":1587435016") }) } @@ -426,8 +423,3 @@ func (suite *redisTestSuite) TestPing() { err := suite.Redis.Ping() suite.Require().Nil(err) } - -func (suite *redisTestSuite) TestAvail() { - avail := suite.Redis.Avail() - suite.Require().True(avail > 0) -} diff --git a/di/db.go b/di/db.go index 0fea76e..1147b60 100644 --- a/di/db.go +++ b/di/db.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "path" - "time" "github.com/defval/di" "github.com/spf13/viper" @@ -38,6 +37,7 @@ func newRedis(container *di.Container, config *viper.Viper) (*redis.Redis, error config.SetDefault("storage.redis.poolSize", 10) conn, err := redis.New( + context.Background(), fmt.Sprintf("%s:%d", config.GetString("storage.redis.host"), config.GetInt("storage.redis.port")), config.GetInt("storage.redis.poolSize"), ) @@ -45,12 +45,6 @@ func newRedis(container *di.Container, config *viper.Viper) (*redis.Redis, error return nil, err } - if err := container.Provide(func() es.ReporterFunc { - return es.AvailableRedisPoolSizeReporter(conn, time.Second, context.Background()) - }, di.As(new(es.Reporter))); err != nil { - return nil, err - } - if err := container.Provide(func() *namedHealthChecker { return &namedHealthChecker{ Name: "redis", diff --git a/eventsubscribers/stats_reporter.go b/eventsubscribers/stats_reporter.go index 9158838..c925f92 100644 --- a/eventsubscribers/stats_reporter.go +++ b/eventsubscribers/stats_reporter.go @@ -1,7 +1,6 @@ package eventsubscribers import ( - "context" "net/http" "strings" "sync" @@ -30,7 +29,7 @@ func (f ReporterFunc) Enable(reporter slf.StatsReporter) { f(reporter) } -// TODO: rework all reporters in the same style as AvailableRedisPoolSizeReporter +// TODO: rework all reporters in the same style as it was there: https://github.com/elyby/chrly/blob/1543e98b/di/db.go#L48-L52 func (s *StatsReporter) ConfigureWithDispatcher(d Subscriber) { s.timersMap = make(map[string]time.Time) @@ -189,24 +188,3 @@ func (s *StatsReporter) finalizeTimeRecording(timeKey string, statName string) { s.RecordTimer(statName, time.Since(startedAt)) } - -type RedisPoolCheckable interface { - Avail() int -} - -func AvailableRedisPoolSizeReporter(pool RedisPoolCheckable, d time.Duration, stop context.Context) ReporterFunc { - return func(reporter slf.StatsReporter) { - go func() { - ticker := time.NewTicker(d) - for { - select { - case <-stop.Done(): - ticker.Stop() - return - case <-ticker.C: - reporter.UpdateGauge("redis.pool.available", int64(pool.Avail())) - } - } - }() - } -} diff --git a/eventsubscribers/stats_reporter_test.go b/eventsubscribers/stats_reporter_test.go index 0923039..f70a03e 100644 --- a/eventsubscribers/stats_reporter_test.go +++ b/eventsubscribers/stats_reporter_test.go @@ -1,7 +1,6 @@ package eventsubscribers import ( - "context" "errors" "net/http/httptest" "testing" @@ -401,30 +400,3 @@ func TestStatsReporter(t *testing.T) { }) } } - -type redisPoolCheckableMock struct { - mock.Mock -} - -func (r *redisPoolCheckableMock) Avail() int { - return r.Called().Int(0) -} - -func TestAvailableRedisPoolSizeReporter(t *testing.T) { - poolMock := &redisPoolCheckableMock{} - poolMock.On("Avail").Return(5).Times(3) - reporterMock := &StatsReporterMock{} - reporterMock.On("UpdateGauge", "redis.pool.available", int64(5)).Times(3) - - ctx, cancel := context.WithCancel(context.Background()) - - creator := AvailableRedisPoolSizeReporter(poolMock, 10*time.Millisecond, ctx) - creator(reporterMock) - - time.Sleep(35 * time.Millisecond) - - cancel() - - poolMock.AssertExpectations(t) - reporterMock.AssertExpectations(t) -} diff --git a/go.mod b/go.mod index 4736f63..a0f1152 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/etherlabsio/healthcheck/v2 v2.0.0 github.com/getsentry/raven-go v0.2.1-0.20190419175539-919484f041ea github.com/gorilla/mux v1.8.1 - github.com/mediocregopher/radix.v2 v0.0.0-20181115013041-b67df6e626f9 + github.com/mediocregopher/radix/v4 v4.1.4 github.com/mono83/slf v0.0.0-20170919161409-79153e9636db github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.1 @@ -32,11 +32,9 @@ require ( github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/levenlabs/golib v0.0.0-20180911183212-0f8974794783 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mono83/udpwriter v1.0.2 // indirect - github.com/oschwald/geoip2-golang v1.9.0 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -47,6 +45,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/tilinna/clock v1.0.2 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/sys v0.15.0 // indirect diff --git a/go.sum b/go.sum index f0af79c..88f8b5d 100644 --- a/go.sum +++ b/go.sum @@ -35,12 +35,10 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/levenlabs/golib v0.0.0-20180911183212-0f8974794783 h1:ErBsqZpyadTBr2zGsgMau0JdyghyLdwRRHAKJukexrQ= -github.com/levenlabs/golib v0.0.0-20180911183212-0f8974794783/go.mod h1:zw8z7nRRkGDZHexz1aMbZGtwxli5so0CBVZeIa3G+RE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mediocregopher/radix.v2 v0.0.0-20181115013041-b67df6e626f9 h1:ViNuGS149jgnttqhc6XQNPwdupEMBXqCx9wtlW7P3sA= -github.com/mediocregopher/radix.v2 v0.0.0-20181115013041-b67df6e626f9/go.mod h1:fLRUbhbSd5Px2yKUaGYYPltlyxi1guJz1vCmo1RQL50= +github.com/mediocregopher/radix/v4 v4.1.4 h1:Uze6DEbEAvL+VHXUEu/EDBTkUk5CLct5h3nVSGpc6Ts= +github.com/mediocregopher/radix/v4 v4.1.4/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mono83/slf v0.0.0-20170919161409-79153e9636db h1:tlz4fTklh5mttoq5M+0yEc5Lap8W/02A2HCXCJn5iz0= @@ -49,10 +47,6 @@ github.com/mono83/udpwriter v1.0.2 h1:JiQ/N646oZoJA1G0FOMvn2teMt6SdL1KwNH2mszOlQ github.com/mono83/udpwriter v1.0.2/go.mod h1:mTDiyLtA0tXoxckkV9T4NUkJTgSQIuO8pAUKx/dSRkQ= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= -github.com/oschwald/geoip2-golang v1.9.0 h1:uvD3O6fXAXs+usU+UGExshpdP13GAqp4GBrzN7IgKZc= -github.com/oschwald/geoip2-golang v1.9.0/go.mod h1:BHK6TvDyATVQhKNbQBdrj9eAvuwOMi2zSFXizL3K81Y= -github.com/oschwald/maxminddb-golang v1.11.0 h1:aSXMqYR/EPNjGE8epgqwDay+P30hCBZIveY0WZbAWh0= -github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfglAFj3PuCmui13+P9zDg= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -81,6 +75,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -90,6 +85,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/thedevsaddam/govalidator v1.9.10 h1:m3dLRbSZ5Hts3VUWYe+vxLMG+FdyQuWOjzTeQRiMCvU= github.com/thedevsaddam/govalidator v1.9.10/go.mod h1:Ilx8u7cg5g3LXbSS943cx5kczyNuUn7LH/cK5MYuE90= +github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= +github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=