feat: cross-replica, OFREP bulk evaluation caching#1858
feat: cross-replica, OFREP bulk evaluation caching#1858
Conversation
✅ Deploy Preview for polite-licorice-3db33c ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Summary of ChangesHello @toddbaert, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant performance enhancement for flagd's OFREP bulk evaluation endpoint by implementing a sophisticated caching mechanism. It leverages HTTP ETags, generated per flag selector, to allow clients to avoid re-evaluation when the underlying flag configuration has not changed. The system ensures ETag consistency across distributed instances and intelligently invalidates cached entries when relevant flag configurations are updated, optimizing network traffic and server load. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
a5c7c8d to
c1fefab
Compare
There was a problem hiding this comment.
Code Review
This PR introduces an ETag-based caching mechanism for OFREP bulk evaluations, which is a great feature for performance. The implementation is well-structured, with a new SelectorVersionTracker to manage ETags per selector. The caching is aware of flag configuration changes through a watch mechanism on the store. The changes are accompanied by good documentation and comprehensive tests.
I've found a potential race condition in the cache eviction logic that could lead to the cache growing beyond its configured capacity. I've also included a couple of suggestions to improve logging. Overall, this is a solid contribution.
flagd/pkg/service/flag-evaluation/ofrep/selector_version_tracker.go
Outdated
Show resolved
Hide resolved
flagd/pkg/service/flag-evaluation/ofrep/selector_version_tracker.go
Outdated
Show resolved
Hide resolved
c1fefab to
90dd25f
Compare
| return flags, queryMeta, nil | ||
| } | ||
|
|
||
| // watchSelector returns a channel that will be closed when the flags matching the given selector are modified. |
There was a problem hiding this comment.
Here, we "hook in" to memdb's listener for the selector, and use it to invalidate the cache.
| } | ||
|
|
||
| // SelectorVersionTracker tracks content hashes for selectors to enable ETag-based caching. | ||
| type SelectorVersionTracker struct { |
There was a problem hiding this comment.
This object handles the caching, and hooks into the store for invalidation whenever a selector it's tracking is updated (the same way we fire messages to listening providers over gRPC when selectors change).
ea65da0 to
28ee86e
Compare
0c3d99e to
7414115
Compare
- sends per-selector ETag for caching - ensures that ETags will be consistent across replicas - skips evaluation entirely if ETag matches Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
7414115 to
95aec74
Compare
|
erka
left a comment
There was a problem hiding this comment.
This approach feels a bit hacky. While it may be fine for internal company use, it could cause issues in an open-source context. Users may run into problems, particularly if they rely on bulk evaluation with their custom clients (someone really likes to generate their own) that don’t match flagd’s/OpenFeature assumptions. It could also make migration between OFREP providers and flagd unnecessarily painful, and custom logic in the web JS provider may cause issues for other OFREP providers.
I think the evaluation context needs to be hashed as part of the ETag to make this implementation safe. It should still be faster than the other PR.
I suppose that if we hash the context and add that as a factor in the ETag, we don't need to worry about this at all - basically we will be able to enforce that opinion in flagd itself, instead of pushing it into the OFREP provider generally. I think that's a good point @erka . |
|
Could you share more context of the motivation here?
|
|
Thanks for the explanation. Could you help me understand why single flag caching is not an interest of OFREP? We're exploring to adopt OFREP soon. |



This PR implements an OFREP bulk-evaluation caching mechanism compliant with https://openfeature.dev/docs/reference/other-technologies/ofrep/openapi/, that entirely avoids re-evaluation. The cache is invalidated based on the flag configuration, not on the context of the request (ie, it tells the client to keep it's current cache if no configuration has changed).
This is an alternative implementation to #1854. The main difference here is evaluation is avoided entirely if the ETag matches. This implementation:
One challenge and part of the complexity here is that I wanted the invalidation of ETags to be "Selector aware" so that clients interested in one set of flags didn't have their ETag invalidated if a sync update didn't impact them.