-
Notifications
You must be signed in to change notification settings - Fork 3
feat: update event processor to handle context key deduplication #150
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
Merged
cwaldren-ld
merged 6 commits into
server-side
from
cw/sc-206551/event-processor-changes
Jun 14, 2023
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
e2a5581
add context key cache for events
cwaldren-ld 29874cb
add some unit tests
cwaldren-ld f6bc272
allow event processor to emit index events in server-side SDKs
cwaldren-ld efd3c78
identify event -> index event
cwaldren-ld 529f282
ContextKeyCache -> LRUCache renaming
cwaldren-ld b50bcec
rename context_key_cache.cpp and test file to lru_cache
cwaldren-ld File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #pragma once | ||
| #include <list> | ||
| #include <string> | ||
| #include <unordered_map> | ||
| namespace launchdarkly::events { | ||
|
|
||
| class LRUCache { | ||
| public: | ||
| /** | ||
| * Constructs a new cache with a given capacity. When capacity is exceeded, | ||
| * entries are evicted from the cache in LRU order. | ||
| * @param capacity | ||
| */ | ||
| explicit LRUCache(std::size_t capacity); | ||
|
|
||
| /** | ||
| * Adds a value to the cache; returns true if it was already there. | ||
| * @param value Value to add. | ||
| * @return True if the value was already in the cache. | ||
| */ | ||
| bool Notice(std::string const& value); | ||
|
|
||
| /** | ||
| * Returns the current size of the cache. | ||
| * @return Number of unique entries in cache. | ||
| */ | ||
| std::size_t Size() const; | ||
|
|
||
| /** | ||
| * Clears all cache entries. | ||
| */ | ||
| void Clear(); | ||
|
|
||
| private: | ||
| using KeyList = std::list<std::string>; | ||
| std::size_t capacity_; | ||
| std::unordered_map<std::string, KeyList::reference> map_; | ||
| KeyList list_; | ||
| }; | ||
|
|
||
| } // namespace launchdarkly::events |
12 changes: 12 additions & 0 deletions
12
libs/internal/include/launchdarkly/events/server_events.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #pragma once | ||
|
|
||
| #include "common_events.hpp" | ||
|
|
||
| namespace launchdarkly::events::server { | ||
|
|
||
| struct IndexEvent { | ||
| Date creation_date; | ||
| EventContext context; | ||
| }; | ||
|
|
||
| } // namespace launchdarkly::events::server |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,8 @@ | |
| #include <launchdarkly/network/asio_requester.hpp> | ||
| #include <launchdarkly/serialization/events/json_events.hpp> | ||
|
|
||
| #include <launchdarkly/events/server_events.hpp> | ||
|
|
||
| namespace http = boost::beast::http; | ||
| namespace launchdarkly::events { | ||
|
|
||
|
|
@@ -53,6 +55,7 @@ AsioEventProcessor<SDK>::AsioEventProcessor( | |
| last_known_past_time_(std::nullopt), | ||
| filter_(events_config.AllAttributesPrivate(), | ||
| events_config.PrivateAttributes()), | ||
| context_key_cache_(events_config.ContextKeysCacheCapacity().value_or(0)), | ||
| logger_(logger) { | ||
| ScheduleFlush(); | ||
| } | ||
|
|
@@ -212,47 +215,63 @@ std::vector<OutputEvent> AsioEventProcessor<SDK>::Process( | |
| InputEvent input_event) { | ||
| std::vector<OutputEvent> out; | ||
| std::visit( | ||
| overloaded{[&](client::FeatureEventParams&& event) { | ||
| summarizer_.Update(event); | ||
|
|
||
| client::FeatureEventBase base{event}; | ||
|
|
||
| auto debug_until_date = event.debug_events_until_date; | ||
|
|
||
| // To be conservative, use as the current time the | ||
| // maximum of the actual current time and the server's | ||
| // time. This way if the local host is running behind, we | ||
| // won't accidentally keep emitting events. | ||
|
|
||
| auto conservative_now = std::max( | ||
| std::chrono::system_clock::now(), | ||
| last_known_past_time_.value_or( | ||
| std::chrono::system_clock::from_time_t(0))); | ||
|
|
||
| bool emit_debug_event = | ||
| debug_until_date && | ||
| conservative_now < debug_until_date->t; | ||
|
|
||
| if (emit_debug_event) { | ||
| out.emplace_back(client::DebugEvent{ | ||
| base, filter_.filter(event.context)}); | ||
| } | ||
|
|
||
| if (event.require_full_event) { | ||
| out.emplace_back(client::FeatureEvent{ | ||
| std::move(base), event.context.KindsToKeys()}); | ||
| } | ||
| }, | ||
| [&](client::IdentifyEventParams&& event) { | ||
| // Contexts should already have been checked for | ||
| // validity by this point. | ||
| assert(event.context.Valid()); | ||
| out.emplace_back(client::IdentifyEvent{ | ||
| event.creation_date, filter_.filter(event.context)}); | ||
| }, | ||
| [&](TrackEventParams&& event) { | ||
| out.emplace_back(std::move(event)); | ||
| }}, | ||
| overloaded{ | ||
| [&](client::FeatureEventParams&& event) { | ||
| summarizer_.Update(event); | ||
|
|
||
| if constexpr (std::is_same<SDK, | ||
| config::shared::ServerSDK>::value) { | ||
| if (!context_key_cache_.Notice( | ||
| event.context.CanonicalKey())) { | ||
| out.emplace_back( | ||
| server::IndexEvent{event.creation_date, | ||
| filter_.filter(event.context)}); | ||
| } | ||
| } | ||
|
|
||
| client::FeatureEventBase base{event}; | ||
|
|
||
| auto debug_until_date = event.debug_events_until_date; | ||
|
|
||
| // To be conservative, use as the current time the | ||
| // maximum of the actual current time and the server's | ||
| // time. This way if the local host is running behind, we | ||
| // won't accidentally keep emitting events. | ||
|
|
||
| auto conservative_now = | ||
| std::max(std::chrono::system_clock::now(), | ||
| last_known_past_time_.value_or( | ||
| std::chrono::system_clock::from_time_t(0))); | ||
|
|
||
| bool emit_debug_event = | ||
| debug_until_date && conservative_now < debug_until_date->t; | ||
|
|
||
| if (emit_debug_event) { | ||
| out.emplace_back(client::DebugEvent{ | ||
| base, filter_.filter(event.context)}); | ||
| } | ||
|
|
||
| if (event.require_full_event) { | ||
| out.emplace_back(client::FeatureEvent{ | ||
| std::move(base), event.context.KindsToKeys()}); | ||
| } | ||
| }, | ||
| [&](client::IdentifyEventParams&& event) { | ||
| // Contexts should already have been checked for | ||
| // validity by this point. | ||
| assert(event.context.Valid()); | ||
|
|
||
| if constexpr (std::is_same<SDK, | ||
| config::shared::ServerSDK>::value) { | ||
| context_key_cache_.Notice(event.context.CanonicalKey()); | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Other change (2/2). |
||
|
|
||
| out.emplace_back(client::IdentifyEvent{ | ||
| event.creation_date, filter_.filter(event.context)}); | ||
| }, | ||
| [&](TrackEventParams&& event) { | ||
| out.emplace_back(std::move(event)); | ||
| }}, | ||
| std::move(input_event)); | ||
|
|
||
| return out; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #include <launchdarkly/events/lru_cache.hpp> | ||
|
|
||
| namespace launchdarkly::events { | ||
| LRUCache::LRUCache(std::size_t capacity) | ||
| : capacity_(capacity), map_(), list_() {} | ||
|
|
||
| bool LRUCache::Notice(std::string const& value) { | ||
| auto it = map_.find(value); | ||
| if (it != map_.end()) { | ||
| list_.remove(value); | ||
| list_.push_front(value); | ||
| return true; | ||
| } | ||
| while (map_.size() >= capacity_) { | ||
| map_.erase(list_.back()); | ||
| list_.pop_back(); | ||
| } | ||
| list_.push_front(value); | ||
| map_.emplace(value, list_.front()); | ||
| return false; | ||
| } | ||
|
|
||
| void LRUCache::Clear() { | ||
| map_.clear(); | ||
| list_.clear(); | ||
| } | ||
|
|
||
| std::size_t LRUCache::Size() const { | ||
| return list_.size(); | ||
| } | ||
|
|
||
| } // namespace launchdarkly::events |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 is the actual change (1/2), not sure why the diff chunk is so large.