diff --git a/include/analytics_manager.h b/include/analytics_manager.h index f58e1c6a..b806af76 100644 --- a/include/analytics_manager.h +++ b/include/analytics_manager.h @@ -47,15 +47,15 @@ struct ClickEvent { }; struct event_cache_t { - uint64_t creation_time; + uint64_t last_update_time; uint64_t count; bool operator == (const event_cache_t& res) const { - return creation_time == res.creation_time; + return last_update_time == res.last_update_time; } bool operator != (const event_cache_t& res) const { - return creation_time != res.creation_time; + return last_update_time != res.last_update_time; } }; @@ -154,4 +154,6 @@ public: Option get_click_events(); Option write_click_event_to_store(nlohmann::json& click_event_json); + + void resetRateLimit(); }; diff --git a/src/analytics_manager.cpp b/src/analytics_manager.cpp index 5587d445..842d89af 100644 --- a/src/analytics_manager.cpp +++ b/src/analytics_manager.cpp @@ -8,7 +8,7 @@ LRU::Cache events_cache; #define CLICK_EVENTS_RATE_LIMIT_SEC 60 -#define CLICK_EVENTS_RATE_LIMIT_COUNT 100 +#define CLICK_EVENTS_RATE_LIMIT_COUNT 5 Option AnalyticsManager::create_rule(nlohmann::json& payload, bool upsert, bool write_to_disk) { /* @@ -234,13 +234,14 @@ Option AnalyticsManager::add_click_event(const std::string &query_collecti if(events_cache_it != events_cache.end()) { //event found in events cache - if ((now_ts_seconds - events_cache_it->second.creation_time) < CLICK_EVENTS_RATE_LIMIT_SEC) { + if ((now_ts_seconds - events_cache_it->second.last_update_time) < CLICK_EVENTS_RATE_LIMIT_SEC) { if (events_cache_it->second.count >= CLICK_EVENTS_RATE_LIMIT_COUNT) { return Option(500, "click event rate limit reached."); } else { events_cache_it->second.count++; } } else { + events_cache_it->second.last_update_time = now_ts_seconds; events_cache_it->second.count = 1; } } else { @@ -459,4 +460,8 @@ Option AnalyticsManager::write_click_event_to_store(nlohmann::json &click_ } } return Option(true); +} + +void AnalyticsManager::resetRateLimit() { + events_cache.clear(); } \ No newline at end of file diff --git a/test/analytics_manager_test.cpp b/test/analytics_manager_test.cpp index 8cf6abb8..973e098f 100644 --- a/test/analytics_manager_test.cpp +++ b/test/analytics_manager_test.cpp @@ -348,4 +348,41 @@ TEST_F(AnalyticsManagerTest, ClickEventsStoreRetrieveal) { ASSERT_EQ("21", result[1]["data"]["doc_id"]); ASSERT_EQ(4, result[1]["data"]["position"]); ASSERT_EQ("technology", result[1]["data"]["q"]); +} + +TEST_F(AnalyticsManagerTest, ClickEventsRateLimitTest) { + nlohmann::json titles_schema = R"({ + "name": "titles", + "fields": [ + {"name": "title", "type": "string"} + ] + })"_json; + + Collection* titles_coll = collectionManager.create_collection(titles_schema).get(); + + std::shared_ptr req = std::make_shared(); + std::shared_ptr res = std::make_shared(nullptr); + + nlohmann::json event = R"({ + "type": "query_click", + "data": { + "q": "technology", + "collection": "titles", + "doc_id": "21", + "position": 2, + "user_id": "13" + } + })"_json; + + //reset the LRU cache to test the rate limit + analyticsManager.resetRateLimit(); + + req->body = event.dump(); + for(auto i = 0; i < 5; ++i) { + ASSERT_TRUE(post_create_event(req, res)); + } + + //as rate limit is 5, adding one more event above that should trigger rate limit + ASSERT_FALSE(post_create_event(req, res)); + ASSERT_EQ("{\"message\": \"click event rate limit reached.\"}", res->body); } \ No newline at end of file