From 3a839d069765485d56f0d941adc6976ccff240ea Mon Sep 17 00:00:00 2001 From: Yordan Kinkov <yordan.kinkov@vereign.com> Date: Fri, 1 Apr 2022 13:37:34 +0300 Subject: [PATCH] #3 add cache set endpoint --- design/design.go | 24 ++++++++++++++++++++++++ design/types.go | 8 ++++++++ internal/clients/redis/client.go | 8 ++++++++ internal/service/cache/service.go | 23 ++++++++++++++++++++++- 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/design/design.go b/design/design.go index 0617832..597055d 100644 --- a/design/design.go +++ b/design/design.go @@ -62,6 +62,30 @@ var _ = Service("cache", func() { Response(StatusOK) }) }) + + Method("Set", func() { + Description("Set value in the cache. The HTTP request body is stored as value and the key is assembled from HTTP request headers.") + + Payload(CacheSetRequest) + Result(Empty) + + HTTP(func() { + POST("/v1/cache") + + Header("key:x-cache-key", String, "Cache entry key", func() { + Example("did:web:example.com") + }) + Header("namespace:x-cache-namespace", String, "Cache entry namespace", func() { + Example("Login") + }) + Header("scope:x-cache-scope", String, "Cache entry scope", func() { + Example("administration") + }) + Body("data") + + Response(StatusCreated) + }) + }) }) var _ = Service("openapi", func() { diff --git a/design/types.go b/design/types.go index 57789a4..19076b7 100644 --- a/design/types.go +++ b/design/types.go @@ -9,3 +9,11 @@ var CacheGetRequest = Type("CacheGetRequest", func() { Field(3, "scope", String) // Initial implementation with a single scope Required("key", "namespace", "scope") }) + +var CacheSetRequest = Type("CacheSetRequest", func() { + Field(1, "data", Bytes) + Field(2, "key", String) + Field(3, "namespace", String) + Field(4, "scope", String) // Initial implementation with a single scope + Required("data", "key", "namespace", "scope") +}) diff --git a/internal/clients/redis/client.go b/internal/clients/redis/client.go index 84d5106..0b1f1c9 100644 --- a/internal/clients/redis/client.go +++ b/internal/clients/redis/client.go @@ -41,3 +41,11 @@ func (c *Client) Get(ctx context.Context, key string) ([]byte, error) { } return []byte(result.Val()), nil } + +func (c *Client) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error { + if ttl == 0 { + ttl = c.defaultTTL + } + + return c.rdb.Set(ctx, key, value, ttl).Err() +} diff --git a/internal/service/cache/service.go b/internal/service/cache/service.go index 0e3153a..c2a3bc8 100644 --- a/internal/service/cache/service.go +++ b/internal/service/cache/service.go @@ -3,6 +3,7 @@ package cache import ( "context" "fmt" + "time" "go.uber.org/zap" @@ -12,6 +13,7 @@ import ( type Cache interface { Get(ctx context.Context, key string) ([]byte, error) + Set(ctx context.Context, key string, value []byte, ttl time.Duration) error } type Service struct { @@ -34,7 +36,7 @@ func (s *Service) Get(ctx context.Context, req *cache.CacheGetRequest) ([]byte, } // create key from the input fields - key := makeCacheKey(req.Key, req.Namespace, req.Scope) + key := makeCacheKey(req.Namespace, req.Scope, req.Key) data, err := s.cache.Get(ctx, key) if err != nil { s.logger.Error("error getting value from cache", zap.String("key", key), zap.Error(err)) @@ -47,6 +49,25 @@ func (s *Service) Get(ctx context.Context, req *cache.CacheGetRequest) ([]byte, return data, nil } +func (s *Service) Set(ctx context.Context, req *cache.CacheSetRequest) error { + var operation = zap.String("operation", "set") + if req.Key == "" || req.Namespace == "" || req.Scope == "" || len(req.Data) == 0 { + s.logger.Error("bad request: missing key or namespace or scope or data", operation) + return errors.New(errors.BadRequest, "bad request") + } + + // TODO(kinkov): issue #3 - evaluate key metadata (key, namespace and scope) and set TTL over a policy execution + + // create key from the input fields + key := makeCacheKey(req.Namespace, req.Scope, req.Key) + if err := s.cache.Set(ctx, key, req.Data, 0); err != nil { + s.logger.Error("error setting value in cache", zap.Error(err), operation) + return errors.New("error setting value in cache", err) + } + + return nil +} + func makeCacheKey(namespace, scope, key string) string { return fmt.Sprintf("%s,%s,%s", namespace, scope, key) } -- GitLab