summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
authorGeorge Goldberg <george@gberg.me>2018-02-07 18:15:07 +0000
committerGitHub <noreply@github.com>2018-02-07 18:15:07 +0000
commita735725d116c3e8dca2b4d1cad3425bcd473311c (patch)
tree7253153de1bbdc8ede107c7c93e90c3ce2b2afe9 /store
parenta04b02081a77497ecfc7a5ae9ffb0ca28404dd0e (diff)
downloadchat-a735725d116c3e8dca2b4d1cad3425bcd473311c.tar.gz
chat-a735725d116c3e8dca2b4d1cad3425bcd473311c.tar.bz2
chat-a735725d116c3e8dca2b4d1cad3425bcd473311c.zip
XYZ-59: Implement redis caching layer for Role store. (#8207)
* XYZ-59: Implement redis caching layer for Role store. * Use variable for key where used more than once.
Diffstat (limited to 'store')
-rw-r--r--store/local_cache_supplier_roles.go2
-rw-r--r--store/redis_supplier.go67
-rw-r--r--store/redis_supplier_reactions.go57
-rw-r--r--store/redis_supplier_roles.go89
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)
+}