@@ -131,13 +131,13 @@ struct UserThreadWebsocketCallbacks : public DataHandler, public WebsocketCallba
131131 ~UserThreadWebsocketCallbacks () override = default ;
132132
133133 // Process data in the user thread. Callbacks will be invoked in the user thread.
134- void processData ();
134+ void processData (uint32_t max_drain_count = 100 );
135135
136136private:
137137 bool checkMarketDataSequenceNumber (void *ws_client, int64_t seq_num) override {
138138 auto it = md_seq_nums_.find (ws_client);
139139 if (it == md_seq_nums_.end ()) [[unlikely]] {
140- it = md_seq_nums_.emplace (ws_client, - 1 ).first ;
140+ it = md_seq_nums_.emplace (ws_client, seq_num - 1 ).first ;
141141 }
142142 auto &seq_atomic = it->second ;
143143 auto last_seq = seq_atomic.load (std::memory_order_acquire);
@@ -153,7 +153,7 @@ struct UserThreadWebsocketCallbacks : public DataHandler, public WebsocketCallba
153153 bool checkUserDataSequenceNumber (void *ws_client, int64_t seq_num) override {
154154 auto it = user_seq_nums_.find (ws_client);
155155 if (it == user_seq_nums_.end ()) [[unlikely]] {
156- it = user_seq_nums_.emplace (ws_client, - 1 ).first ;
156+ it = user_seq_nums_.emplace (ws_client, seq_num - 1 ).first ;
157157 }
158158 auto &seq_atomic = it->second ;
159159 auto last_seq = seq_atomic.load (std::memory_order_acquire);
@@ -231,9 +231,13 @@ class WebSocketClient {
231231
232232
233233
234- inline void UserThreadWebsocketCallbacks::processData () {
235- auto [data_ptr, data_size] = data_queue_.read (read_cursor_);
236- if (data_ptr && data_size > 0 ) {
234+ inline void UserThreadWebsocketCallbacks::processData (uint32_t max_drain_count) {
235+ uint32_t i = 0 ;
236+ do {
237+ auto [data_ptr, data_size] = data_queue_.read (read_cursor_);
238+ if (!data_ptr || data_size == 0 ) {
239+ break ;
240+ }
237241 void * client = nullptr ;
238242 memcpy (&client, data_ptr, sizeof (void *));
239243 char channel = data_ptr[sizeof (void *)];
@@ -245,6 +249,7 @@ inline void UserThreadWebsocketCallbacks::processData() {
245249 processMarketData (client, data_ptr, data_size - sizeof (void *) - 1 );
246250 }
247251 }
252+ while (++i < max_drain_count);
248253}
249254
250255
@@ -417,8 +422,8 @@ inline void WebSocketClient::runDataLogger() {
417422 if (!data) {
418423 break ;
419424 }
420- ++data ; // skip channel identifier
421- data_log_.write (data, size - 1 );
425+ data += sizeof ( void *) + 1 ; // skip client and channel identifier
426+ data_log_.write (data, size - sizeof ( void *) - 1 );
422427 data_log_ << std::endl;
423428 }
424429}
@@ -450,7 +455,7 @@ inline void WebSocketClient::onUserData(const char* data, std::size_t size) {
450455 // If data_queue_ is not nullptr, data logger is enabled.
451456 // dispatch data for logging
452457 if (data_queue_) {
453- dispatchData (data, size, ' M ' );
458+ dispatchData (data, size, ' U ' );
454459 }
455460 }
456461}
@@ -517,7 +522,7 @@ inline bool DataHandler::processMarketData(void *ws_client, const char* data, st
517522 processHeartbeat (j);
518523 }
519524 else {
520- LOG_ERROR (" unknown channel: {}" , to_string ( channel));
525+ LOG_ERROR (" unknown channel: {}" , channel. is_string () ? channel. get <std::string_view>() : channel. dump ( ));
521526 }
522527 }
523528 catch (const std::exception &e) {
@@ -545,7 +550,7 @@ inline bool DataHandler::processUserData(void *ws_client, const char* data, std:
545550 else if (channel == " futures_balance_summary" ) {
546551 }
547552 else {
548- LOG_ERROR (" unknown channel: {}" , to_string ( channel));
553+ LOG_ERROR (" unknown channel: {}" , channel. is_string () ? channel. get <std::string_view>() : channel. dump ( ));
549554 }
550555 }
551556 catch (const std::exception &e) {
@@ -652,6 +657,10 @@ inline bool DataHandler::processHeartbeat([[maybe_unused]] const json& j) {
652657}
653658
654659inline bool DataHandler::checkMarketDataSequenceNumber ([[maybe_unused]] void * client, int64_t seq_num) {
660+ if (last_md_seq_num_ < 0 ) [[unlikely]] {
661+ last_md_seq_num_ = seq_num;
662+ return true ;
663+ }
655664 if (seq_num != last_md_seq_num_ + 1 ) {
656665 LOG_ERROR (" market data message lost. seq_num: {}, last_md_seq_num: {}" , seq_num, last_md_seq_num_);
657666 callbacks_->onMarketDataGap ();
@@ -662,6 +671,10 @@ inline bool DataHandler::checkMarketDataSequenceNumber([[maybe_unused]] void* cl
662671}
663672
664673inline bool DataHandler::checkUserDataSequenceNumber ([[maybe_unused]] void * client, int64_t seq_num) {
674+ if (last_user_seq_num_ < 0 ) [[unlikely]] {
675+ last_user_seq_num_ = seq_num;
676+ return true ;
677+ }
665678 if (seq_num != last_user_seq_num_ + 1 ) {
666679 LOG_ERROR (" user data message lost. seq_num: {}, last_user_seq_num: {}" , seq_num, last_user_seq_num_);
667680 callbacks_->onUserDataGap ();
0 commit comments