diff options
-rw-r--r-- | store/local_cache_supplier_roles.go | 2 | ||||
-rw-r--r-- | store/redis_supplier.go | 67 | ||||
-rw-r--r-- | store/redis_supplier_reactions.go | 57 | ||||
-rw-r--r-- | store/redis_supplier_roles.go | 89 |
4 files changed, 148 insertions, 67 deletions
diff --git a/store/local_cache_supplier_roles.go b/store/local_cache_supplier_roles.go index a9cbda017..8cbde0a23 100644 --- a/store/local_cache_supplier_roles.go +++ b/store/local_cache_supplier_roles.go @@ -25,6 +25,8 @@ func (s *LocalCacheSupplier) RoleSave(ctx context.Context, role *model.Role, hin } func (s *LocalCacheSupplier) RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + // Roles are cached by name, as that is most commonly how they are looked up. + // This means that no caching is supported on roles being looked up by ID. return s.Next().RoleGet(ctx, roleId, hints...) } diff --git a/store/redis_supplier.go b/store/redis_supplier.go index b8ec794cf..751227be9 100644 --- a/store/redis_supplier.go +++ b/store/redis_supplier.go @@ -5,14 +5,12 @@ package store import ( "bytes" - "context" "encoding/gob" "time" l4g "github.com/alecthomas/log4go" "github.com/go-redis/redis" - "github.com/mattermost/mattermost-server/model" ) const REDIS_EXPIRY_TIME = 30 * time.Minute @@ -87,68 +85,3 @@ func (s *RedisSupplier) SetChainNext(next LayeredStoreSupplier) { func (s *RedisSupplier) Next() LayeredStoreSupplier { return s.next } - -func (s *RedisSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - if err := s.client.Del("reactions:" + reaction.PostId).Err(); err != nil { - l4g.Error("Redis failed to remove key reactions:" + reaction.PostId + " Error: " + err.Error()) - } - return s.Next().ReactionSave(ctx, reaction, hints...) -} - -func (s *RedisSupplier) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - if err := s.client.Del("reactions:" + reaction.PostId).Err(); err != nil { - l4g.Error("Redis failed to remove key reactions:" + reaction.PostId + " Error: " + err.Error()) - } - return s.Next().ReactionDelete(ctx, reaction, hints...) -} - -func (s *RedisSupplier) ReactionGetForPost(ctx context.Context, postId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - var resultdata []*model.Reaction - found, err := s.load("reactions:"+postId, &resultdata) - if found { - result := NewSupplierResult() - result.Data = resultdata - return result - } - if err != nil { - l4g.Error("Redis encountered an error on read: " + err.Error()) - } - - result := s.Next().ReactionGetForPost(ctx, postId, hints...) - - if err := s.save("reactions:"+postId, result.Data, REDIS_EXPIRY_TIME); err != nil { - l4g.Error("Redis encountered and error on write: " + err.Error()) - } - - return result -} - -func (s *RedisSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - // Ignoring this. It's probably OK to have the emoji slowly expire from Redis. - return s.Next().ReactionDeleteAllWithEmojiName(ctx, emojiName, hints...) -} - -func (s *RedisSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - // Ignoring this. It's probably OK to have the emoji slowly expire from Redis. - return s.Next().ReactionPermanentDeleteBatch(ctx, endTime, limit, hints...) -} - -func (s *RedisSupplier) RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - // TODO: Redis Caching. - return s.Next().RoleSave(ctx, role, hints...) -} - -func (s *RedisSupplier) RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - // TODO: Redis Caching. - return s.Next().RoleGet(ctx, roleId, hints...) -} - -func (s *RedisSupplier) RoleGetByName(ctx context.Context, name string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - // TODO: Redis Caching. - return s.Next().RoleGetByName(ctx, name, hints...) -} - -func (s *RedisSupplier) RoleGetByNames(ctx context.Context, roleNames []string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { - // TODO: Redis Caching. - return s.Next().RoleGetByNames(ctx, roleNames, hints...) -} diff --git a/store/redis_supplier_reactions.go b/store/redis_supplier_reactions.go new file mode 100644 index 000000000..cece8113d --- /dev/null +++ b/store/redis_supplier_reactions.go @@ -0,0 +1,57 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package store + +import ( + "context" + + l4g "github.com/alecthomas/log4go" + + "github.com/mattermost/mattermost-server/model" +) + +func (s *RedisSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + if err := s.client.Del("reactions:" + reaction.PostId).Err(); err != nil { + l4g.Error("Redis failed to remove key reactions:" + reaction.PostId + " Error: " + err.Error()) + } + return s.Next().ReactionSave(ctx, reaction, hints...) +} + +func (s *RedisSupplier) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + if err := s.client.Del("reactions:" + reaction.PostId).Err(); err != nil { + l4g.Error("Redis failed to remove key reactions:" + reaction.PostId + " Error: " + err.Error()) + } + return s.Next().ReactionDelete(ctx, reaction, hints...) +} + +func (s *RedisSupplier) ReactionGetForPost(ctx context.Context, postId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + var resultdata []*model.Reaction + found, err := s.load("reactions:"+postId, &resultdata) + if found { + result := NewSupplierResult() + result.Data = resultdata + return result + } + if err != nil { + l4g.Error("Redis encountered an error on read: " + err.Error()) + } + + result := s.Next().ReactionGetForPost(ctx, postId, hints...) + + if err := s.save("reactions:"+postId, result.Data, REDIS_EXPIRY_TIME); err != nil { + l4g.Error("Redis encountered and error on write: " + err.Error()) + } + + return result +} + +func (s *RedisSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + // Ignoring this. It's probably OK to have the emoji slowly expire from Redis. + return s.Next().ReactionDeleteAllWithEmojiName(ctx, emojiName, hints...) +} + +func (s *RedisSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + // Ignoring this. It's probably OK to have the emoji slowly expire from Redis. + return s.Next().ReactionPermanentDeleteBatch(ctx, endTime, limit, hints...) +} diff --git a/store/redis_supplier_roles.go b/store/redis_supplier_roles.go new file mode 100644 index 000000000..170420f1f --- /dev/null +++ b/store/redis_supplier_roles.go @@ -0,0 +1,89 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package store + +import ( + "context" + "fmt" + + l4g "github.com/alecthomas/log4go" + + "github.com/mattermost/mattermost-server/model" +) + +func (s *RedisSupplier) RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + key := buildRedisKeyForRoleName(role.Name) + + if err := s.client.Del(key).Err(); err != nil { + l4g.Error("Redis failed to remove key " + key + " Error: " + err.Error()) + } + + return s.Next().RoleSave(ctx, role, hints...) +} + +func (s *RedisSupplier) RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + // Roles are cached by name, as that is most commonly how they are looked up. + // This means that no caching is supported on roles being looked up by ID. + return s.Next().RoleGet(ctx, roleId, hints...) +} + +func (s *RedisSupplier) RoleGetByName(ctx context.Context, name string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + key := buildRedisKeyForRoleName(name) + + var role *model.Role + found, err := s.load(key, &role) + if err != nil { + l4g.Error("Redis encountered an error on read: " + err.Error()) + } else if found { + result := NewSupplierResult() + result.Data = role + return result + } + + result := s.Next().RoleGetByName(ctx, name, hints...) + + if result.Err == nil { + if err := s.save(key, result.Data, REDIS_EXPIRY_TIME); err != nil { + l4g.Error("Redis encountered and error on write: " + err.Error()) + } + } + + return result +} + +func (s *RedisSupplier) RoleGetByNames(ctx context.Context, roleNames []string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { + var foundRoles []*model.Role + var rolesToQuery []string + + for _, roleName := range roleNames { + var role *model.Role + found, err := s.load(buildRedisKeyForRoleName(roleName), &role) + if err == nil && found { + foundRoles = append(foundRoles, role) + } else { + rolesToQuery = append(rolesToQuery, roleName) + if err != nil { + l4g.Error("Redis encountered an error on read: " + err.Error()) + } + } + } + + result := s.Next().RoleGetByNames(ctx, rolesToQuery, hints...) + + if result.Err == nil { + rolesFound := result.Data.([]*model.Role) + for _, role := range rolesFound { + if err := s.save(buildRedisKeyForRoleName(role.Name), role, REDIS_EXPIRY_TIME); err != nil { + l4g.Error("Redis encountered and error on write: " + err.Error()) + } + } + result.Data = append(foundRoles, result.Data.([]*model.Role)...) + } + + return result +} + +func buildRedisKeyForRoleName(roleName string) string { + return fmt.Sprintf("roles:%s", roleName) +} |