@@ -136,7 +136,7 @@ void Countly::setUserDetails(const std::map<std::string, std::string> &value) {
136136
137137 std::map<std::string, std::string> data = {{" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}, {" user_details" , session_params[" user_details" ].dump ()}};
138138
139- sendHTTP ( " /i " , Countly::serializeForm (data));
139+ addToRequestQueue ( Countly::serializeForm (data));
140140 mutex.unlock ();
141141}
142142
@@ -152,7 +152,7 @@ void Countly::setCustomUserDetails(const std::map<std::string, std::string> &val
152152
153153 std::map<std::string, std::string> data = {{" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}, {" user_details" , session_params[" user_details" ].dump ()}};
154154
155- sendHTTP ( " /i " , Countly::serializeForm (data));
155+ addToRequestQueue ( Countly::serializeForm (data));
156156 mutex.unlock ();
157157}
158158
@@ -229,7 +229,7 @@ void Countly::_sendIndependantLocationRequest() {
229229 data[" app_key" ] = session_params[" app_key" ].get <std::string>();
230230 data[" device_id" ] = session_params[" device_id" ].get <std::string>();
231231 data[" timestamp" ] = std::to_string (timestamp.count ());
232- sendHTTP ( " /i " , Countly::serializeForm (data));
232+ addToRequestQueue ( Countly::serializeForm (data));
233233 }
234234
235235 mutex.unlock ();
@@ -285,7 +285,7 @@ void Countly::_changeDeviceIdWithMerge(const std::string &value) {
285285 {" old_device_id" , session_params[" old_device_id" ].get <std::string>()},
286286 {" timestamp" , std::to_string (timestamp.count ())},
287287 };
288- sendHTTP ( " /i " , Countly::serializeForm (data));
288+ addToRequestQueue ( Countly::serializeForm (data));
289289
290290 session_params.erase (" old_device_id" );
291291 mutex.unlock ();
@@ -313,6 +313,8 @@ void Countly::_changeDeviceIdWithoutMerge(const std::string &value) {
313313
314314void Countly::start (const std::string &app_key, const std::string &host, int port, bool start_thread) {
315315 mutex.lock ();
316+ enable_automatic_session = start_thread;
317+ start_thread = true ;
316318 log (Countly::LogLevel::INFO, " [Countly][start]" );
317319 this ->host = host;
318320 if (host.find (" http://" ) == 0 ) {
@@ -552,19 +554,15 @@ bool Countly::beginSession() {
552554 data[" metrics" ] = session_params[" metrics" ].dump ();
553555 }
554556
555- if ( sendHTTP ( " /i " , Countly::serializeForm (data)). success ) {
556- session_params.erase (" user_details" );
557- last_sent_session_request = Countly::getTimestamp ();
558- began_session = true ;
559- }
557+ addToRequestQueue ( Countly::serializeForm (data));
558+ session_params.erase (" user_details" );
559+ last_sent_session_request = Countly::getTimestamp ();
560+ began_session = true ;
561+ mutex. unlock ();
560562
561563 if (remote_config_enabled) {
562- mutex.unlock ();
563564 updateRemoteConfig ();
564- } else {
565- mutex.unlock ();
566565 }
567-
568566 return began_session;
569567}
570568
@@ -639,10 +637,7 @@ bool Countly::updateSession() {
639637 if (duration.count () >= _auto_session_update_interval) {
640638 log (Countly::LogLevel::DEBUG, " [Countly][updateSession] sending session update." );
641639 std::map<std::string, std::string> data = {{" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}, {" session_duration" , std::to_string (duration.count ())}};
642- if (!sendHTTP (" /i" , Countly::serializeForm (data)).success ) {
643- mutex.unlock ();
644- return false ;
645- }
640+ addToRequestQueue (Countly::serializeForm (data));
646641
647642 last_sent_session_request += duration;
648643 }
@@ -651,10 +646,7 @@ bool Countly::updateSession() {
651646 log (Countly::LogLevel::DEBUG, " [Countly][updateSession] sending event." );
652647 std::map<std::string, std::string> data = {{" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}, {" events" , events.dump ()}};
653648
654- if (!sendHTTP (" /i" , Countly::serializeForm (data)).success ) {
655- mutex.unlock ();
656- return false ;
657- }
649+ addToRequestQueue (Countly::serializeForm (data));
658650 }
659651
660652#ifndef COUNTLY_USE_SQLITE
@@ -697,15 +689,12 @@ bool Countly::endSession() {
697689 return false ;
698690 }
699691
700- if (sendHTTP (" /i" , Countly::serializeForm (data)).success ) {
701- last_sent_session_request = now;
702- began_session = false ;
703- mutex.unlock ();
704- return true ;
705- }
692+ addToRequestQueue (Countly::serializeForm (data));
706693
694+ last_sent_session_request = now;
695+ began_session = false ;
707696 mutex.unlock ();
708- return false ;
697+ return true ;
709698}
710699
711700std::chrono::system_clock::time_point Countly::getTimestamp () { return std::chrono::system_clock::now (); }
@@ -798,6 +787,32 @@ std::string Countly::calculateChecksum(const std::string &salt, const std::strin
798787#endif
799788}
800789
790+ void Countly::processRequestQueue () {
791+
792+ while (!request_queue.empty ()) {
793+ mutex.lock ();
794+ std::string data = request_queue.front ();
795+ HTTPResponse response = sendHTTP (" /i" , data);
796+
797+ if (!response.success ) {
798+ mutex.unlock ();
799+ break ;
800+ }
801+
802+ request_queue.pop_front ();
803+ mutex.unlock ();
804+ }
805+ }
806+
807+ void Countly::addToRequestQueue (std::string &data) {
808+ if (request_queue.size () >= 1000 ) {
809+ log (Countly::LogLevel::WARNING, " [Countly][addToRequestQueue] Request Queue is full. Dropping the oldest request." );
810+ request_queue.pop_front ();
811+ }
812+
813+ request_queue.push_back (data);
814+ }
815+
801816Countly::HTTPResponse Countly::sendHTTP (std::string path, std::string data) {
802817 bool use_post = always_use_post || (data.size () > COUNTLY_POST_THRESHOLD);
803818 log (Countly::LogLevel::DEBUG, " [Countly][sendHTTP] data: " + data);
@@ -996,7 +1011,11 @@ void Countly::updateLoop() {
9961011 size_t last_wait_milliseconds = wait_milliseconds;
9971012 mutex.unlock ();
9981013 std::this_thread::sleep_for (std::chrono::milliseconds (last_wait_milliseconds));
999- updateSession ();
1014+ if (enable_automatic_session) {
1015+ updateSession ();
1016+ }
1017+
1018+ processRequestQueue ();
10001019 }
10011020 mutex.lock ();
10021021 running = false ;
@@ -1009,20 +1028,29 @@ void Countly::enableRemoteConfig() {
10091028 mutex.unlock ();
10101029}
10111030
1031+ void Countly::_fetchRemoteConfig (std::map<std::string, std::string> &data) {
1032+ mutex.lock ();
1033+ HTTPResponse response = sendHTTP (" /o/sdk" , serializeForm (data));
1034+ if (response.success ) {
1035+ remote_config = response.data ;
1036+ }
1037+ mutex.unlock ();
1038+ }
1039+
10121040void Countly::updateRemoteConfig () {
1041+ mutex.lock ();
10131042 if (!session_params[" app_key" ].is_string () || !session_params[" device_id" ].is_string ()) {
10141043 log (Countly::LogLevel::ERROR, " Error updating remote config, app key or device id is missing" );
1044+ mutex.unlock ();
10151045 return ;
10161046 }
1017-
10181047 std::map<std::string, std::string> data = {{" method" , " fetch_remote_config" }, {" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}};
10191048
1020- HTTPResponse response = sendHTTP (" /o/sdk" , serializeForm (data));
1021- if (response.success ) {
1022- mutex.lock ();
1023- remote_config = response.data ;
1024- mutex.unlock ();
1025- }
1049+ mutex.unlock ();
1050+
1051+ // Fetch remote config asynchronously
1052+ std::thread _thread (&Countly::_fetchRemoteConfig, this , data);
1053+ _thread.detach ();
10261054}
10271055
10281056nlohmann::json Countly::getRemoteConfigValue (const std::string &key) {
@@ -1032,7 +1060,19 @@ nlohmann::json Countly::getRemoteConfigValue(const std::string &key) {
10321060 return value;
10331061}
10341062
1063+ void Countly::_updateRemoteConfigWithSpecificValues (std::map<std::string, std::string> &data) {
1064+ mutex.lock ();
1065+ HTTPResponse response = sendHTTP (" /o/sdk" , serializeForm (data));
1066+ if (response.success ) {
1067+ for (auto it = response.data .begin (); it != response.data .end (); ++it) {
1068+ remote_config[it.key ()] = it.value ();
1069+ }
1070+ }
1071+ mutex.unlock ();
1072+ }
1073+
10351074void Countly::updateRemoteConfigFor (std::string *keys, size_t key_count) {
1075+ mutex.lock ();
10361076 std::map<std::string, std::string> data = {{" method" , " fetch_remote_config" }, {" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}};
10371077
10381078 {
@@ -1042,18 +1082,15 @@ void Countly::updateRemoteConfigFor(std::string *keys, size_t key_count) {
10421082 }
10431083 data[" keys" ] = keys_json.dump ();
10441084 }
1085+ mutex.unlock ();
10451086
1046- HTTPResponse response = sendHTTP (" /o/sdk" , serializeForm (data));
1047- if (response.success ) {
1048- mutex.lock ();
1049- for (auto it = response.data .begin (); it != response.data .end (); ++it) {
1050- remote_config[it.key ()] = it.value ();
1051- }
1052- mutex.unlock ();
1053- }
1087+ // Fetch remote config asynchronously
1088+ std::thread _thread (&Countly::_updateRemoteConfigWithSpecificValues, this , data);
1089+ _thread.detach ();
10541090}
10551091
10561092void Countly::updateRemoteConfigExcept (std::string *keys, size_t key_count) {
1093+ mutex.lock ();
10571094 std::map<std::string, std::string> data = {{" method" , " fetch_remote_config" }, {" app_key" , session_params[" app_key" ].get <std::string>()}, {" device_id" , session_params[" device_id" ].get <std::string>()}};
10581095
10591096 {
@@ -1063,14 +1100,10 @@ void Countly::updateRemoteConfigExcept(std::string *keys, size_t key_count) {
10631100 }
10641101 data[" omit_keys" ] = keys_json.dump ();
10651102 }
1103+ mutex.unlock ();
10661104
1067- HTTPResponse response = sendHTTP (" /o/sdk" , serializeForm (data));
1068- if (response.success ) {
1069- mutex.lock ();
1070- for (auto it = response.data .begin (); it != response.data .end (); ++it) {
1071- remote_config[it.key ()] = it.value ();
1072- }
1073- mutex.unlock ();
1074- }
1105+ // Fetch remote config asynchronously
1106+ std::thread _thread (&Countly::_updateRemoteConfigWithSpecificValues, this , data);
1107+ _thread.detach ();
10751108}
10761109} // namespace cly
0 commit comments