1
0
Эх сурвалжийг харах

fix: http-based session message inorder in slow network

wangweimin 2 жил өмнө
parent
commit
3a3355b7ac

+ 14 - 1
pywebio/platform/adaptor/http.py

@@ -113,6 +113,7 @@ class HttpHandler:
     """
     # type: Dict[str, Session]
     _webio_sessions = {}  # WebIOSessionID -> WebIOSession()
+    _webio_last_commands = {}  # WebIOSessionID -> (last commands, commands sequence id)
     _webio_expire = LRUDict()  # WebIOSessionID -> last active timestamp. In increasing order of last active time
     _webio_expire_lock = threading.Lock()
 
@@ -149,6 +150,17 @@ class HttpHandler:
         cls._webio_sessions.pop(sid, None)
         cls._webio_expire.pop(sid, None)
 
+    @classmethod
+    def get_response(cls, sid, ack=0):
+        commands, seq = cls._webio_last_commands.get(sid, ([], 0))
+        if ack == seq:
+            webio_session = cls._webio_sessions[sid]
+            commands = webio_session.get_task_commands()
+            seq += 1
+            cls._webio_last_commands[sid] = (commands, seq)
+
+        return {'commands': commands, 'seq': seq}
+
     def _process_cors(self, context: HttpContext):
         """Handling cross-domain requests: check the source of the request and set headers"""
         origin = context.request_headers().get('Origin', '')
@@ -272,7 +284,8 @@ class HttpHandler:
 
         self.interval_cleaning()
 
-        context.set_content(webio_session.get_task_commands(), json_type=True)
+        ack = int(context.request_url_parameter('ack', 0))
+        context.set_content(type(self).get_response(webio_session_id, ack=ack), json_type=True)
 
         if webio_session.closed():
             self._remove_webio_session(webio_session_id)

+ 12 - 6
webiojs/src/session.ts

@@ -181,6 +181,7 @@ export class HttpSession implements Session {
     webio_session_id: string = 'NEW';
     debug = false;
 
+    private _executed_command_msg_id = 0;
     private _closed = false;
     private _session_create_callbacks: (() => void)[] = [];
     private _session_close_callbacks: (() => void)[] = [];
@@ -218,11 +219,11 @@ export class HttpSession implements Session {
         let that = this;
         $.ajax({
             type: "GET",
-            url: this.api_url,
+            url: `${this.api_url}&ack=${this._executed_command_msg_id}`,
             contentType: "application/json; charset=utf-8",
             dataType: "json",
             headers: {"webio-session-id": this.webio_session_id},
-            success: function (data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
+            success: function (data: { commands: Command[], seq: number }, textStatus: string, jqXHR: JQuery.jqXHR) {
                 safe_poprun_callbacks(that._session_create_callbacks, 'session_create_callback');
                 that._on_request_success(data, textStatus, jqXHR);
             },
@@ -232,11 +233,16 @@ export class HttpSession implements Session {
         })
     }
 
-    private _on_request_success(data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
+    private _on_request_success(data: { commands: Command[], seq: number }, textStatus: string, jqXHR: JQuery.jqXHR) {
+        if (data.seq == this._executed_command_msg_id)
+            return;
+        this._executed_command_msg_id = data.seq;
+
         let sid = jqXHR.getResponseHeader('webio-session-id');
-        if (sid) this.webio_session_id = sid;
+        if (sid)
+            this.webio_session_id = sid;
 
-        for (let msg of data) {
+        for (let msg of data.commands) {
             if (this.debug) console.info('>>>', msg);
             this._on_server_message(msg);
         }
@@ -267,7 +273,7 @@ export class HttpSession implements Session {
         $.ajax({
             ...options,
             type: "POST",
-            url: this.api_url,
+            url: `${this.api_url}&ack=${this._executed_command_msg_id}`,
             dataType: "json",
             headers: {"webio-session-id": this.webio_session_id},
             success: this._on_request_success.bind(this),