Skip to content
Snippets Groups Projects
Commit 409d30ae authored by Yordan Kinkov's avatar Yordan Kinkov
Browse files

Merge branch '1-add-TTL-parameter-on-cache-set' into 'main'

Add TTL optional parameter when setting entry to cache

Closes #1

See merge request gaia-x/data-infrastructure-federation-services/tsa/cache!1
parents 0e8653f8 7f2466d3
Branches
Tags
No related merge requests found
Pipeline #54041 passed
...@@ -83,6 +83,9 @@ var _ = Service("cache", func() { ...@@ -83,6 +83,9 @@ var _ = Service("cache", func() {
Header("scope:x-cache-scope", String, "Cache entry scope", func() { Header("scope:x-cache-scope", String, "Cache entry scope", func() {
Example("administration") Example("administration")
}) })
Header("ttl:x-cache-ttl", Int, "Cache entry TTL in seconds", func() {
Example(60)
})
Body("data") Body("data")
Response(StatusCreated) Response(StatusCreated)
...@@ -107,6 +110,9 @@ var _ = Service("cache", func() { ...@@ -107,6 +110,9 @@ var _ = Service("cache", func() {
Header("scope:x-cache-scope", String, "Cache entry scope", func() { Header("scope:x-cache-scope", String, "Cache entry scope", func() {
Example("administration") Example("administration")
}) })
Header("ttl:x-cache-ttl", Int, "Cache entry TTL in seconds", func() {
Example(60)
})
Body("data") Body("data")
Response(StatusOK) Response(StatusOK)
......
...@@ -15,5 +15,6 @@ var CacheSetRequest = Type("CacheSetRequest", func() { ...@@ -15,5 +15,6 @@ var CacheSetRequest = Type("CacheSetRequest", func() {
Field(2, "key", String) Field(2, "key", String)
Field(3, "namespace", String) Field(3, "namespace", String)
Field(4, "scope", String) // Initial implementation with a single scope Field(4, "scope", String) // Initial implementation with a single scope
Field(5, "ttl", Int)
Required("data", "key") Required("data", "key")
}) })
...@@ -45,4 +45,5 @@ type CacheSetRequest struct { ...@@ -45,4 +45,5 @@ type CacheSetRequest struct {
Key string Key string
Namespace *string Namespace *string
Scope *string Scope *string
TTL *int
} }
...@@ -11,6 +11,7 @@ package client ...@@ -11,6 +11,7 @@ package client
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strconv"
cache "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/cache/gen/cache" cache "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/cache/gen/cache"
) )
...@@ -42,13 +43,13 @@ func BuildGetPayload(cacheGetKey string, cacheGetNamespace string, cacheGetScope ...@@ -42,13 +43,13 @@ func BuildGetPayload(cacheGetKey string, cacheGetNamespace string, cacheGetScope
} }
// BuildSetPayload builds the payload for the cache Set endpoint from CLI flags. // BuildSetPayload builds the payload for the cache Set endpoint from CLI flags.
func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace string, cacheSetScope string) (*cache.CacheSetRequest, error) { func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace string, cacheSetScope string, cacheSetTTL string) (*cache.CacheSetRequest, error) {
var err error var err error
var body interface{} var body interface{}
{ {
err = json.Unmarshal([]byte(cacheSetBody), &body) err = json.Unmarshal([]byte(cacheSetBody), &body)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "\"Quasi ut.\"") return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "\"Corporis omnis itaque earum quasi.\"")
} }
} }
var key string var key string
...@@ -67,6 +68,18 @@ func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace ...@@ -67,6 +68,18 @@ func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace
scope = &cacheSetScope scope = &cacheSetScope
} }
} }
var ttl *int
{
if cacheSetTTL != "" {
var v int64
v, err = strconv.ParseInt(cacheSetTTL, 10, strconv.IntSize)
val := int(v)
ttl = &val
if err != nil {
return nil, fmt.Errorf("invalid value for ttl, must be INT")
}
}
}
v := body v := body
res := &cache.CacheSetRequest{ res := &cache.CacheSetRequest{
Data: v, Data: v,
...@@ -74,13 +87,14 @@ func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace ...@@ -74,13 +87,14 @@ func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace
res.Key = key res.Key = key
res.Namespace = namespace res.Namespace = namespace
res.Scope = scope res.Scope = scope
res.TTL = ttl
return res, nil return res, nil
} }
// BuildSetExternalPayload builds the payload for the cache SetExternal // BuildSetExternalPayload builds the payload for the cache SetExternal
// endpoint from CLI flags. // endpoint from CLI flags.
func BuildSetExternalPayload(cacheSetExternalBody string, cacheSetExternalKey string, cacheSetExternalNamespace string, cacheSetExternalScope string) (*cache.CacheSetRequest, error) { func BuildSetExternalPayload(cacheSetExternalBody string, cacheSetExternalKey string, cacheSetExternalNamespace string, cacheSetExternalScope string, cacheSetExternalTTL string) (*cache.CacheSetRequest, error) {
var err error var err error
var body interface{} var body interface{}
{ {
...@@ -105,6 +119,18 @@ func BuildSetExternalPayload(cacheSetExternalBody string, cacheSetExternalKey st ...@@ -105,6 +119,18 @@ func BuildSetExternalPayload(cacheSetExternalBody string, cacheSetExternalKey st
scope = &cacheSetExternalScope scope = &cacheSetExternalScope
} }
} }
var ttl *int
{
if cacheSetExternalTTL != "" {
var v int64
v, err = strconv.ParseInt(cacheSetExternalTTL, 10, strconv.IntSize)
val := int(v)
ttl = &val
if err != nil {
return nil, fmt.Errorf("invalid value for ttl, must be INT")
}
}
}
v := body v := body
res := &cache.CacheSetRequest{ res := &cache.CacheSetRequest{
Data: v, Data: v,
...@@ -112,6 +138,7 @@ func BuildSetExternalPayload(cacheSetExternalBody string, cacheSetExternalKey st ...@@ -112,6 +138,7 @@ func BuildSetExternalPayload(cacheSetExternalBody string, cacheSetExternalKey st
res.Key = key res.Key = key
res.Namespace = namespace res.Namespace = namespace
res.Scope = scope res.Scope = scope
res.TTL = ttl
return res, nil return res, nil
} }
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
cache "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/cache/gen/cache" cache "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/cache/gen/cache"
goahttp "goa.design/goa/v3/http" goahttp "goa.design/goa/v3/http"
...@@ -128,6 +129,11 @@ func EncodeSetRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Re ...@@ -128,6 +129,11 @@ func EncodeSetRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Re
head := *p.Scope head := *p.Scope
req.Header.Set("x-cache-scope", head) req.Header.Set("x-cache-scope", head)
} }
if p.TTL != nil {
head := *p.TTL
headStr := strconv.Itoa(head)
req.Header.Set("x-cache-ttl", headStr)
}
body := p.Data body := p.Data
if err := encoder(req).Encode(&body); err != nil { if err := encoder(req).Encode(&body); err != nil {
return goahttp.ErrEncodingError("cache", "Set", err) return goahttp.ErrEncodingError("cache", "Set", err)
...@@ -198,6 +204,11 @@ func EncodeSetExternalRequest(encoder func(*http.Request) goahttp.Encoder) func( ...@@ -198,6 +204,11 @@ func EncodeSetExternalRequest(encoder func(*http.Request) goahttp.Encoder) func(
head := *p.Scope head := *p.Scope
req.Header.Set("x-cache-scope", head) req.Header.Set("x-cache-scope", head)
} }
if p.TTL != nil {
head := *p.TTL
headStr := strconv.Itoa(head)
req.Header.Set("x-cache-ttl", headStr)
}
body := p.Data body := p.Data
if err := encoder(req).Encode(&body); err != nil { if err := encoder(req).Encode(&body); err != nil {
return goahttp.ErrEncodingError("cache", "SetExternal", err) return goahttp.ErrEncodingError("cache", "SetExternal", err)
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"context" "context"
"io" "io"
"net/http" "net/http"
"strconv"
goahttp "goa.design/goa/v3/http" goahttp "goa.design/goa/v3/http"
goa "goa.design/goa/v3/pkg" goa "goa.design/goa/v3/pkg"
...@@ -90,6 +91,7 @@ func DecodeSetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Dec ...@@ -90,6 +91,7 @@ func DecodeSetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Dec
key string key string
namespace *string namespace *string
scope *string scope *string
ttl *int
) )
key = r.Header.Get("x-cache-key") key = r.Header.Get("x-cache-key")
if key == "" { if key == "" {
...@@ -103,10 +105,21 @@ func DecodeSetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Dec ...@@ -103,10 +105,21 @@ func DecodeSetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Dec
if scopeRaw != "" { if scopeRaw != "" {
scope = &scopeRaw scope = &scopeRaw
} }
{
ttlRaw := r.Header.Get("x-cache-ttl")
if ttlRaw != "" {
v, err2 := strconv.ParseInt(ttlRaw, 10, strconv.IntSize)
if err2 != nil {
err = goa.MergeErrors(err, goa.InvalidFieldTypeError("ttl", ttlRaw, "integer"))
}
pv := int(v)
ttl = &pv
}
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
payload := NewSetCacheSetRequest(body, key, namespace, scope) payload := NewSetCacheSetRequest(body, key, namespace, scope, ttl)
return payload, nil return payload, nil
} }
...@@ -141,6 +154,7 @@ func DecodeSetExternalRequest(mux goahttp.Muxer, decoder func(*http.Request) goa ...@@ -141,6 +154,7 @@ func DecodeSetExternalRequest(mux goahttp.Muxer, decoder func(*http.Request) goa
key string key string
namespace *string namespace *string
scope *string scope *string
ttl *int
) )
key = r.Header.Get("x-cache-key") key = r.Header.Get("x-cache-key")
if key == "" { if key == "" {
...@@ -154,10 +168,21 @@ func DecodeSetExternalRequest(mux goahttp.Muxer, decoder func(*http.Request) goa ...@@ -154,10 +168,21 @@ func DecodeSetExternalRequest(mux goahttp.Muxer, decoder func(*http.Request) goa
if scopeRaw != "" { if scopeRaw != "" {
scope = &scopeRaw scope = &scopeRaw
} }
{
ttlRaw := r.Header.Get("x-cache-ttl")
if ttlRaw != "" {
v, err2 := strconv.ParseInt(ttlRaw, 10, strconv.IntSize)
if err2 != nil {
err = goa.MergeErrors(err, goa.InvalidFieldTypeError("ttl", ttlRaw, "integer"))
}
pv := int(v)
ttl = &pv
}
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
payload := NewSetExternalCacheSetRequest(body, key, namespace, scope) payload := NewSetExternalCacheSetRequest(body, key, namespace, scope, ttl)
return payload, nil return payload, nil
} }
......
...@@ -23,7 +23,7 @@ func NewGetCacheGetRequest(key string, namespace *string, scope *string) *cache. ...@@ -23,7 +23,7 @@ func NewGetCacheGetRequest(key string, namespace *string, scope *string) *cache.
} }
// NewSetCacheSetRequest builds a cache service Set endpoint payload. // NewSetCacheSetRequest builds a cache service Set endpoint payload.
func NewSetCacheSetRequest(body interface{}, key string, namespace *string, scope *string) *cache.CacheSetRequest { func NewSetCacheSetRequest(body interface{}, key string, namespace *string, scope *string, ttl *int) *cache.CacheSetRequest {
v := body v := body
res := &cache.CacheSetRequest{ res := &cache.CacheSetRequest{
Data: v, Data: v,
...@@ -31,13 +31,14 @@ func NewSetCacheSetRequest(body interface{}, key string, namespace *string, scop ...@@ -31,13 +31,14 @@ func NewSetCacheSetRequest(body interface{}, key string, namespace *string, scop
res.Key = key res.Key = key
res.Namespace = namespace res.Namespace = namespace
res.Scope = scope res.Scope = scope
res.TTL = ttl
return res return res
} }
// NewSetExternalCacheSetRequest builds a cache service SetExternal endpoint // NewSetExternalCacheSetRequest builds a cache service SetExternal endpoint
// payload. // payload.
func NewSetExternalCacheSetRequest(body interface{}, key string, namespace *string, scope *string) *cache.CacheSetRequest { func NewSetExternalCacheSetRequest(body interface{}, key string, namespace *string, scope *string, ttl *int) *cache.CacheSetRequest {
v := body v := body
res := &cache.CacheSetRequest{ res := &cache.CacheSetRequest{
Data: v, Data: v,
...@@ -45,6 +46,7 @@ func NewSetExternalCacheSetRequest(body interface{}, key string, namespace *stri ...@@ -45,6 +46,7 @@ func NewSetExternalCacheSetRequest(body interface{}, key string, namespace *stri
res.Key = key res.Key = key
res.Namespace = namespace res.Namespace = namespace
res.Scope = scope res.Scope = scope
res.TTL = ttl
return res return res
} }
...@@ -32,7 +32,7 @@ cache (get|set|set-external) ...@@ -32,7 +32,7 @@ cache (get|set|set-external)
// UsageExamples produces an example of a valid invocation of the CLI tool. // UsageExamples produces an example of a valid invocation of the CLI tool.
func UsageExamples() string { func UsageExamples() string {
return os.Args[0] + ` health liveness` + "\n" + return os.Args[0] + ` health liveness` + "\n" +
os.Args[0] + ` cache get --key "Suscipit sed consequatur rerum occaecati in veritatis." --namespace "Repudiandae eos consequatur sint dolorum occaecati." --scope "Voluptatum modi tenetur tempore quia est ratione."` + "\n" + os.Args[0] + ` cache get --key "Sed consequatur rerum occaecati." --namespace "Veritatis exercitationem repudiandae eos." --scope "Sint dolorum occaecati."` + "\n" +
"" ""
} }
...@@ -64,12 +64,14 @@ func ParseEndpoint( ...@@ -64,12 +64,14 @@ func ParseEndpoint(
cacheSetKeyFlag = cacheSetFlags.String("key", "REQUIRED", "") cacheSetKeyFlag = cacheSetFlags.String("key", "REQUIRED", "")
cacheSetNamespaceFlag = cacheSetFlags.String("namespace", "", "") cacheSetNamespaceFlag = cacheSetFlags.String("namespace", "", "")
cacheSetScopeFlag = cacheSetFlags.String("scope", "", "") cacheSetScopeFlag = cacheSetFlags.String("scope", "", "")
cacheSetTTLFlag = cacheSetFlags.String("ttl", "", "")
cacheSetExternalFlags = flag.NewFlagSet("set-external", flag.ExitOnError) cacheSetExternalFlags = flag.NewFlagSet("set-external", flag.ExitOnError)
cacheSetExternalBodyFlag = cacheSetExternalFlags.String("body", "REQUIRED", "") cacheSetExternalBodyFlag = cacheSetExternalFlags.String("body", "REQUIRED", "")
cacheSetExternalKeyFlag = cacheSetExternalFlags.String("key", "REQUIRED", "") cacheSetExternalKeyFlag = cacheSetExternalFlags.String("key", "REQUIRED", "")
cacheSetExternalNamespaceFlag = cacheSetExternalFlags.String("namespace", "", "") cacheSetExternalNamespaceFlag = cacheSetExternalFlags.String("namespace", "", "")
cacheSetExternalScopeFlag = cacheSetExternalFlags.String("scope", "", "") cacheSetExternalScopeFlag = cacheSetExternalFlags.String("scope", "", "")
cacheSetExternalTTLFlag = cacheSetExternalFlags.String("ttl", "", "")
) )
healthFlags.Usage = healthUsage healthFlags.Usage = healthUsage
healthLivenessFlags.Usage = healthLivenessUsage healthLivenessFlags.Usage = healthLivenessUsage
...@@ -175,10 +177,10 @@ func ParseEndpoint( ...@@ -175,10 +177,10 @@ func ParseEndpoint(
data, err = cachec.BuildGetPayload(*cacheGetKeyFlag, *cacheGetNamespaceFlag, *cacheGetScopeFlag) data, err = cachec.BuildGetPayload(*cacheGetKeyFlag, *cacheGetNamespaceFlag, *cacheGetScopeFlag)
case "set": case "set":
endpoint = c.Set() endpoint = c.Set()
data, err = cachec.BuildSetPayload(*cacheSetBodyFlag, *cacheSetKeyFlag, *cacheSetNamespaceFlag, *cacheSetScopeFlag) data, err = cachec.BuildSetPayload(*cacheSetBodyFlag, *cacheSetKeyFlag, *cacheSetNamespaceFlag, *cacheSetScopeFlag, *cacheSetTTLFlag)
case "set-external": case "set-external":
endpoint = c.SetExternal() endpoint = c.SetExternal()
data, err = cachec.BuildSetExternalPayload(*cacheSetExternalBodyFlag, *cacheSetExternalKeyFlag, *cacheSetExternalNamespaceFlag, *cacheSetExternalScopeFlag) data, err = cachec.BuildSetExternalPayload(*cacheSetExternalBodyFlag, *cacheSetExternalKeyFlag, *cacheSetExternalNamespaceFlag, *cacheSetExternalScopeFlag, *cacheSetExternalTTLFlag)
} }
} }
} }
...@@ -247,34 +249,36 @@ Get JSON value from the cache. ...@@ -247,34 +249,36 @@ Get JSON value from the cache.
-scope STRING: -scope STRING:
Example: Example:
%[1]s cache get --key "Suscipit sed consequatur rerum occaecati in veritatis." --namespace "Repudiandae eos consequatur sint dolorum occaecati." --scope "Voluptatum modi tenetur tempore quia est ratione." %[1]s cache get --key "Sed consequatur rerum occaecati." --namespace "Veritatis exercitationem repudiandae eos." --scope "Sint dolorum occaecati."
`, os.Args[0]) `, os.Args[0])
} }
func cacheSetUsage() { func cacheSetUsage() {
fmt.Fprintf(os.Stderr, `%[1]s [flags] cache set -body JSON -key STRING -namespace STRING -scope STRING fmt.Fprintf(os.Stderr, `%[1]s [flags] cache set -body JSON -key STRING -namespace STRING -scope STRING -ttl INT
Set a JSON value in the cache. Set a JSON value in the cache.
-body JSON: -body JSON:
-key STRING: -key STRING:
-namespace STRING: -namespace STRING:
-scope STRING: -scope STRING:
-ttl INT:
Example: Example:
%[1]s cache set --body "Quasi ut." --key "Quasi perspiciatis." --namespace "Accusantium animi non alias." --scope "Esse inventore ullam placeat aut." %[1]s cache set --body "Corporis omnis itaque earum quasi." --key "Et eligendi nihil optio natus assumenda." --namespace "Quasi perspiciatis." --scope "Accusantium animi non alias." --ttl 3495630911155968941
`, os.Args[0]) `, os.Args[0])
} }
func cacheSetExternalUsage() { func cacheSetExternalUsage() {
fmt.Fprintf(os.Stderr, `%[1]s [flags] cache set-external -body JSON -key STRING -namespace STRING -scope STRING fmt.Fprintf(os.Stderr, `%[1]s [flags] cache set-external -body JSON -key STRING -namespace STRING -scope STRING -ttl INT
Set an external JSON value in the cache and provide an event for the input. Set an external JSON value in the cache and provide an event for the input.
-body JSON: -body JSON:
-key STRING: -key STRING:
-namespace STRING: -namespace STRING:
-scope STRING: -scope STRING:
-ttl INT:
Example: Example:
%[1]s cache set-external --body "Enim vel." --key "Quisquam ab dolores distinctio quis." --namespace "Optio aliquam error nam." --scope "Recusandae illo." %[1]s cache set-external --body "Enim vel." --key "Ut in." --namespace "Ab dolores distinctio quis." --scope "Optio aliquam error nam." --ttl 2227603043401673122
`, os.Args[0]) `, os.Args[0])
} }
{"swagger":"2.0","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":""},"host":"localhost:8083","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get JSON value from the cache.","operationId":"cache#Get","produces":["application/json"],"parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":false,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":false,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]},"post":{"tags":["cache"],"summary":"Set cache","description":"Set a JSON value in the cache.","operationId":"cache#Set","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":false,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":false,"type":"string"},{"name":"any","in":"body","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"201":{"description":"Created response."}},"schemes":["http"]}},"/v1/external/cache":{"post":{"tags":["cache"],"summary":"SetExternal cache","description":"Set an external JSON value in the cache and provide an event for the input.","operationId":"cache#SetExternal","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":false,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":false,"type":"string"},{"name":"any","in":"body","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response."}},"schemes":["http"]}}}} {"swagger":"2.0","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":""},"host":"localhost:8083","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get JSON value from the cache.","operationId":"cache#Get","produces":["application/json"],"parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":false,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":false,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]},"post":{"tags":["cache"],"summary":"Set cache","description":"Set a JSON value in the cache.","operationId":"cache#Set","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":false,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Cache entry TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"201":{"description":"Created response."}},"schemes":["http"]}},"/v1/external/cache":{"post":{"tags":["cache"],"summary":"SetExternal cache","description":"Set an external JSON value in the cache and provide an event for the input.","operationId":"cache#SetExternal","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":false,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Cache entry TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response."}},"schemes":["http"]}}}}
\ No newline at end of file \ No newline at end of file
...@@ -90,6 +90,11 @@ paths: ...@@ -90,6 +90,11 @@ paths:
description: Cache entry scope description: Cache entry scope
required: false required: false
type: string type: string
- name: x-cache-ttl
in: header
description: Cache entry TTL in seconds
required: false
type: integer
- name: any - name: any
in: body in: body
required: true required: true
...@@ -124,6 +129,11 @@ paths: ...@@ -124,6 +129,11 @@ paths:
description: Cache entry scope description: Cache entry scope
required: false required: false
type: string type: string
- name: x-cache-ttl
in: header
description: Cache entry TTL in seconds
required: false
type: integer
- name: any - name: any
in: body in: body
required: true required: true
......
{"openapi":"3.0.3","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":"1.0"},"servers":[{"url":"http://localhost:8083","description":"Cache Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get JSON value from the cache.","operationId":"cache#Get","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Delectus quaerat molestiae placeat nemo.","format":"binary"},"example":"Quia dolores rem."}}}}},"post":{"tags":["cache"],"summary":"Set cache","description":"Set a JSON value in the cache.","operationId":"cache#Set","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"string","example":"Quis rerum velit sunt rerum dignissimos at.","format":"binary"},"example":"Est illum."}}},"responses":{"201":{"description":"Created response."}}}},"/v1/external/cache":{"post":{"tags":["cache"],"summary":"SetExternal cache","description":"Set an external JSON value in the cache and provide an event for the input.","operationId":"cache#SetExternal","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"string","example":"Molestiae minima.","format":"binary"},"example":"Repellendus quo."}}},"responses":{"200":{"description":"OK response."}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"cache","description":"Cache service allows storing and retrieving data from distributed cache."}]} {"openapi":"3.0.3","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":"1.0"},"servers":[{"url":"http://localhost:8083","description":"Cache Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get JSON value from the cache.","operationId":"cache#Get","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Delectus quaerat molestiae placeat nemo.","format":"binary"},"example":"Quia dolores rem."}}}}},"post":{"tags":["cache"],"summary":"Set cache","description":"Set a JSON value in the cache.","operationId":"cache#Set","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"},{"name":"x-cache-ttl","in":"header","description":"Cache entry TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Cache entry TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"string","example":"Quis rerum velit sunt rerum dignissimos at.","format":"binary"},"example":"Est illum."}}},"responses":{"201":{"description":"Created response."}}}},"/v1/external/cache":{"post":{"tags":["cache"],"summary":"SetExternal cache","description":"Set an external JSON value in the cache and provide an event for the input.","operationId":"cache#SetExternal","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"},{"name":"x-cache-ttl","in":"header","description":"Cache entry TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Cache entry TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"string","example":"Molestiae minima.","format":"binary"},"example":"Repellendus quo."}}},"responses":{"200":{"description":"OK response."}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"cache","description":"Cache service allows storing and retrieving data from distributed cache."}]}
\ No newline at end of file \ No newline at end of file
...@@ -106,6 +106,16 @@ paths: ...@@ -106,6 +106,16 @@ paths:
description: Cache entry scope description: Cache entry scope
example: administration example: administration
example: administration example: administration
- name: x-cache-ttl
in: header
description: Cache entry TTL in seconds
allowEmptyValue: true
schema:
type: integer
description: Cache entry TTL in seconds
example: 60
format: int64
example: 60
requestBody: requestBody:
required: true required: true
content: content:
...@@ -154,6 +164,16 @@ paths: ...@@ -154,6 +164,16 @@ paths:
description: Cache entry scope description: Cache entry scope
example: administration example: administration
example: administration example: administration
- name: x-cache-ttl
in: header
description: Cache entry TTL in seconds
allowEmptyValue: true
schema:
type: integer
description: Cache entry TTL in seconds
example: 60
format: int64
example: 60
requestBody: requestBody:
required: true required: true
content: content:
......
...@@ -73,8 +73,6 @@ func (s *Service) Set(ctx context.Context, req *cache.CacheSetRequest) error { ...@@ -73,8 +73,6 @@ func (s *Service) Set(ctx context.Context, req *cache.CacheSetRequest) error {
return errors.New(errors.BadRequest, "missing key") return errors.New(errors.BadRequest, "missing key")
} }
// TODO(kinkov): issue #3 - evaluate key metadata (key, namespace and scope) and set TTL over a policy execution
// create key from the input fields // create key from the input fields
key := makeCacheKey(req.Key, req.Namespace, req.Scope) key := makeCacheKey(req.Key, req.Namespace, req.Scope)
// encode payload to json bytes for storing in cache // encode payload to json bytes for storing in cache
...@@ -84,7 +82,13 @@ func (s *Service) Set(ctx context.Context, req *cache.CacheSetRequest) error { ...@@ -84,7 +82,13 @@ func (s *Service) Set(ctx context.Context, req *cache.CacheSetRequest) error {
return errors.New(errors.BadRequest, "cannot encode payload to json", err) return errors.New(errors.BadRequest, "cannot encode payload to json", err)
} }
if err := s.cache.Set(ctx, key, value, 0); err != nil { // set cache ttl if provided in request
var ttl time.Duration
if req.TTL != nil {
ttl = time.Duration(*req.TTL) * time.Second
}
if err := s.cache.Set(ctx, key, value, ttl); err != nil {
logger.Error("error storing value in cache", zap.Error(err)) logger.Error("error storing value in cache", zap.Error(err))
return errors.New("error storing value in cache", err) return errors.New("error storing value in cache", err)
} }
......
...@@ -165,6 +165,22 @@ func TestService_Set(t *testing.T) { ...@@ -165,6 +165,22 @@ func TestService_Set(t *testing.T) {
}, },
errtext: "", errtext: "",
}, },
{
name: "successfully set value in cache with TTL provided in request",
req: &goacache.CacheSetRequest{
Key: "key",
Namespace: ptr.String("namespace"),
Scope: ptr.String("scope"),
Data: map[string]interface{}{"test": "value"},
TTL: ptr.Int(60),
},
cache: &cachefakes.FakeCache{
SetStub: func(ctx context.Context, key string, value []byte, ttl time.Duration) error {
return nil
},
},
errtext: "",
},
} }
for _, test := range tests { for _, test := range tests {
...@@ -248,6 +264,25 @@ func TestService_SetExternal(t *testing.T) { ...@@ -248,6 +264,25 @@ func TestService_SetExternal(t *testing.T) {
}}, }},
errtext: "", errtext: "",
}, },
{
name: "successfully set value in cache with TTL provided in request and send an event to events",
req: &goacache.CacheSetRequest{
Key: "key",
Namespace: ptr.String("namespace"),
Scope: ptr.String("scope"),
Data: map[string]interface{}{"test": "value"},
TTL: ptr.Int(60),
},
cache: &cachefakes.FakeCache{
SetStub: func(ctx context.Context, key string, value []byte, ttl time.Duration) error {
return nil
},
},
events: &cachefakes.FakeEvents{SendStub: func(ctx context.Context, s string) error {
return nil
}},
errtext: "",
},
} }
for _, test := range tests { for _, test := range tests {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment