-
Notifications
You must be signed in to change notification settings - Fork 27
[FSSDK-8838] feat(odp-cache): Adds support for odp cache. #365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* Adds support for odp options in config.yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Some suggestions to reuse go-sdk cache. Let's discuss options.
config/config.go
Outdated
EventsRequestTimeout time.Duration `json:"eventsRequestTimeout"` | ||
EventsFlushInterval time.Duration `json:"eventsFlushInterval"` | ||
Disable bool `json:"disable"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EventsRequestTimeout time.Duration `json:"eventsRequestTimeout"` | |
EventsFlushInterval time.Duration `json:"eventsFlushInterval"` | |
Disable bool `json:"disable"` | |
Disable bool `json:"disable"` | |
EventsRequestTimeout time.Duration `json:"eventsRequestTimeout"` | |
EventsFlushInterval time.Duration `json:"eventsFlushInterval"` |
plugins/odpcache/README.md
Outdated
@@ -0,0 +1,64 @@ | |||
# ODP Cache | |||
Use a ODP Cache to persist segments and ensure they are sticky. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a ODP Cache to persist segments and ensure they are sticky. | |
Use a ODP Cache to cache user segments fetched from the ODP server. |
) | ||
|
||
// InMemoryCache represents the in-memory implementation of Cache interface | ||
type InMemoryCache struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not clear about the value of providing an option to use this in-memory cache. It looks like instantiating the same URLCache implemented in go-sdk. Can't we use the default one already in go-sdk?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are now using this as default odp cache with both timeout
and size
as arguments. Following is the default configuration:
odp:
## Disable odp
disable: false
## Timeout in seconds after which event requests will timeout.
eventsRequestTimeout: 10s
## Flush interval in seconds for odp events
eventsFlushInterval: 1s
## Timeout in seconds after which segment requests will timeout.
segmentsRequestTimeout: 10s
## This will override all other settings
segmentsCache:
default: "in-memory"
services:
in-memory:
size: 10000
timeout: 600 # seconds
# redis:
# host: "localhost:6379"
# password: ""
# database: 0
# timeout: 0 # seconds
} | ||
|
||
// Check if JSON string was set using OPTIMIZELY_CLIENT_ODP_SEGMENTSCACHE environment variable | ||
if odpSegmentsCache := v.GetStringMap("client.odp.segmentsCache"); odpSegmentsCache != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering why we need this support for odpCache only? What about other odp config like "client.odp"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No specific reason, its just something that we did for ups
aswell.
config.yaml
Outdated
segmentsCacheTimeout: 600s | ||
## Timeout in seconds after which segment requests will timeout. | ||
segmentsRequestTimeout: 10s | ||
## This will override all other settings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we be more specific about overriding? CacheSize and CacheTimeout will be overriden. Others like "disable" etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted this comment as segmentsCacheTimeout
and segmentsCacheSize
no longer exist outside of the scope of in-memory
cache.
config.yaml
Outdated
segmentsRequestTimeout: 10s | ||
## This will override all other settings | ||
segmentsCache: | ||
default: "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this empty default imply? Will agent use go-sdk native URLCache with segmentCacheSize
and segmentsCacheTimeout
? Or is it cache disabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as per the new implementation, empty default simply means that go-sdk will use its default LRU cache with default timeout and size
config.yaml
Outdated
# in-memory: | ||
# size: 0 | ||
# timeout: 0 # seconds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this in-memory
cache the same as one in go-sdk (implemented and active by default)?
If so, we can use size
and timeout
for its config (segmentsCacheSize
and segmentsCacheTimeout
above can be removed).
What about "in-memory" as default for "default: in-memory"? So, they'll use go-sdk cache unless override with redis
etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this default config make sense?
disable: false
eventsRequestTimeout: 10s
eventsFlushInterval: 1s
segmentsRequestTimeout: 10s
segmentsCache:
default: "in-memory"
services:
in-memory:
size: 10000
timeout: 600s
# redis:
# host:
#
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the suggestion, went with the same approach.
# size: 0 | ||
# timeout: 0 # seconds | ||
# redis: | ||
# host: "localhost:6379" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to control redis timeout as well? We can reuse segmentsCacheTimeout
but it may be confusing since we do not use segmentsCacheSize
for redis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added timeout to redis aswell.
func init() { | ||
redisCacheCreator := func() cache.Cache { | ||
return &RedisCache{ | ||
Expiration: 0 * time.Second, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need timeout control for redis cache. Can't we add timeout
to config?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All changes look good! A few small fixes suggested.
cmd/optimizely/testdata/default.yaml
Outdated
redis: | ||
host: "localhost:6379" | ||
password: "" | ||
timeout: 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5s ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5s
was possible if the key was at the root and viper was unmarshalling it. In this case we are unmarshalling it at runtime using native json
library which does not support converting 5s
to time duration.
config.yaml
Outdated
# timeout: 0 # seconds | ||
in-memory: | ||
size: 10000 | ||
timeout: 600 # seconds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
600s ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above.
config.yaml
Outdated
# host: "localhost:6379" | ||
# password: "" | ||
# database: 0 | ||
# timeout: 0 # seconds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
600s default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above.
config.yaml
Outdated
segmentsCacheTimeout: 600s | ||
## Timeout in seconds after which segment requests will timeout. | ||
segmentsRequestTimeout: 10s | ||
## This will override all other settings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No overriding any more. This line should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! A few minor fixes suggested.
plugins/odpcache/README.md
Outdated
in-memory: | ||
## 0 means cache will be disabled | ||
size: 0 | ||
## timeout after which least recently used records will be deleted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## timeout after which least recently used records will be deleted | |
## timeout after which the cached item will become invalid. |
## configure optional ODP Cache | ||
odp: | ||
segmentsCache: | ||
default: "in-memory" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be better if default "default" is clarified. If no segmentsCache
is defined (or no default is defined), we will use the default in-memory with default size and timeout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement is true, if none provided then sdk uses its own in-memory
with default values: https://github.com/optimizely/go-sdk/blob/master/pkg/odp/segment/segment_manager.go#L87
|
||
switch value := unmarshalledJSON.(type) { | ||
case float64: | ||
duration.Duration = time.Duration(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we accept number without unit? What is the default unit for this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes we do, default unit is nanosecond by golang.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Summary
in-memory
andredis
.in-memory
will use the builtin LRU cache with user providedsize
andtimeout
.size
andtimeout
.Out of Box ODP Cache Usage
ODPCache
, update theconfig.yaml
as shown below:ODPCache
, update theconfig.yaml
as shown below:Custom ODPCache Implementation
To implement a custom odp cache, followings steps need to be taken:
cache.Cache
interface inplugins/odpcache/services
.init
method inside your ODPCache file as shown below:config.yaml
file with yourODPCache
config as shown below:If a user has created multiple
ODPCache
services and wants to override thedefault
ODPCache
for a specificsdkKey
, they can do so by providing theODPCache
name in the request HeaderX-Optimizely-ODP-Cache-Name
.Whenever a request is made with a unique
sdkKey
, The agent node handling that request creates and caches a newODPCache
. To keep theODPCache
type consistent among all nodes in a cluster, it is recommended to send the request HeaderX-Optimizely-ODP-Cache-Name
in every request made.Tests
Ticket
FSSDK-8838