@@ -310,8 +310,13 @@ class WebSocketSession : public std::enable_shared_from_this<WebSocketSession>
310310 DRCHandler drc_handler_;
311311
312312 // Write serialization: strand + queue ensures one async_write at a time
313+ struct PendingWrite
314+ {
315+ std::vector<unsigned char > frame;
316+ std::function<void ()> on_complete;
317+ };
313318 net::strand<net::any_io_executor> strand_;
314- std::deque<std::vector< unsigned char > > write_queue_;
319+ std::deque<PendingWrite > write_queue_;
315320 bool writing_ = false ;
316321
317322 // Background search index initialization
@@ -339,7 +344,8 @@ class WebSocketSession : public std::enable_shared_from_this<WebSocketSession>
339344 void on_accept (beast::error_code ec);
340345 void do_read ();
341346 void on_read (beast::error_code ec);
342- void queue_response (const WebSocketResponse& resp);
347+ void queue_response (const WebSocketResponse& resp,
348+ std::function<void ()> on_complete = {});
343349 void do_write ();
344350};
345351
@@ -435,15 +441,19 @@ void WebSocketSession::on_accept(beast::error_code ec)
435441 resp.payload .assign (json.begin (), json.end ());
436442 self->queue_response (resp);
437443 },
438- // PostFn — post an arbitrary callable onto this session's strand.
439- // Used by broadcastAndWait() to fence after the write is queued .
440- [weak_self](std::function<void ()> fn) {
444+ // SendAndWaitFn — queue a JSON push message and invoke the callback
445+ // after async_write completes .
446+ [weak_self](const std::string& json, std::function<void ()> fn) {
441447 auto self = weak_self.lock ();
442448 if (!self) {
443449 fn (); // session gone — signal fence immediately
444450 return ;
445451 }
446- net::post (self->strand_ , std::move (fn));
452+ WebSocketResponse resp;
453+ resp.id = 0 ;
454+ resp.type = 0 ; // JSON
455+ resp.payload .assign (json.begin (), json.end ());
456+ self->queue_response (resp, std::move (fn));
447457 });
448458
449459 // Flush any log output that accumulated before this client
@@ -789,18 +799,23 @@ void WebSocketSession::on_read(beast::error_code ec)
789799 do_read ();
790800}
791801
792- void WebSocketSession::queue_response (const WebSocketResponse& resp)
802+ void WebSocketSession::queue_response (const WebSocketResponse& resp,
803+ std::function<void ()> on_complete)
793804{
794805 std::vector<unsigned char > frame = serialize_response (resp);
795806
796807 // Post to the strand to serialize write queue access
797- net::post (strand_,
798- [self = shared_from_this (), frame = std::move (frame)]() mutable {
799- self->write_queue_ .push_back (std::move (frame));
800- if (!self->writing_ ) {
801- self->do_write ();
802- }
803- });
808+ net::post (
809+ strand_,
810+ [self = shared_from_this (),
811+ frame = std::move (frame),
812+ on_complete = std::move (on_complete)]() mutable {
813+ self->write_queue_ .push_back (PendingWrite{
814+ .frame = std::move (frame), .on_complete = std::move (on_complete)});
815+ if (!self->writing_ ) {
816+ self->do_write ();
817+ }
818+ });
804819}
805820
806821void WebSocketSession::do_write ()
@@ -812,19 +827,24 @@ void WebSocketSession::do_write()
812827 writing_ = true ;
813828 websocket_.binary (true );
814829 websocket_.async_write (
815- net::buffer (write_queue_.front ()),
830+ net::buffer (write_queue_.front (). frame ),
816831 [self = shared_from_this ()](beast::error_code ec, std::size_t ) {
817832 net::post (self->strand_ , [self, ec]() {
833+ auto on_complete = std::move (self->write_queue_ .front ().on_complete );
834+ self->write_queue_ .pop_front ();
835+ if (on_complete) {
836+ on_complete ();
837+ }
818838 if (ec) {
819839 debugPrint (self->logger_ ,
820840 utl::WEB ,
821841 " websocket" ,
822842 1 ,
823843 " websocket write error: {}" ,
824844 ec.message ());
845+ self->writing_ = false ;
825846 return ;
826847 }
827- self->write_queue_ .pop_front ();
828848 self->do_write ();
829849 });
830850 });
0 commit comments