-
Notifications
You must be signed in to change notification settings - Fork 3
feat: Add the ability to persist and restore flag configuration. #93
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
|
This pull request has been linked to Shortcut Story #202753: Ability to persist and restore flags.. |
| using launchdarkly::client_side::PersistenceBuilder; | ||
| using launchdarkly::config::shared::builders::LoggingBuilder; | ||
|
|
||
| class FilePersistence : public IPersistence { |
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.
Simple persistence implementation for demonstration purposes.
apps/hello-cpp/main.cpp
Outdated
| .Logging(LoggingBuilder::BasicLogging().Level(LogLevel::kDebug)) | ||
| .Events(launchdarkly::client_side::EventsBuilder().FlushInterval( | ||
| std::chrono::seconds(5))) | ||
| .Persistence( |
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.
Configure persistence with the custom implementation.
| .value(), | ||
| ContextBuilder().kind("user", "ryan").build()); | ||
|
|
||
| auto before_init = client.BoolVariationDetail("my-boolean-flag", false); |
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.
Read a flag before init is complete. Result can be different if the value was persisted.
| } | ||
|
|
||
| DataSourceEventHandler::DataSourceEventHandler( | ||
| Context const& context, |
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.
Context flows through data source updates now. Allowing correlation between context and data. The dotnet client does this as well.
| @@ -1,47 +1,36 @@ | |||
| #include <tl/expected.hpp> | |||
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 was the FlagManager is now the FlagStore. The FlagManager coordinates the store, updater, and persistence.
| char const** read_value, | ||
| void* user_data); | ||
|
|
||
| typedef void (*FreeFn)(char const* value, void* user_data); |
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.
So, when we read a value someone has to allocate that value. I figured I let the implementer allocate it. Which means that the implementer needs to know when to free it.
Alternatively I could do some buffer scheme, where I see if the read fits, grow the buffer, or do partial reads. This seemed simpler.
| } | ||
|
|
||
| ContextIndex FlagPersistence::GetIndex() { | ||
| if (persistence_) { |
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.
nit: could early out.
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.
I am doing the other one, but this one it makes it so multiple different paths need to create a ContextIndex, so the nesting is more consice.
| Logger& logger_; | ||
| std::size_t max_cached_contexts_; | ||
|
|
||
| IDataSourceUpdateSink* sink_; |
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.
Why are we passing the sink as a raw pointer again - What's the ownership model?
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.
There is 1 in the client and it is passed around. Currently it isn't consistently used. I think a pointer is better than a reference for this use case.
But, if we change either use case, we should probably just make them all shared pointers.
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.
I can make it a reference for now.
No description provided.