From 38aa2ee47c615774a2f1f0fe61daf506de2c400c Mon Sep 17 00:00:00 2001 From: James Hutchison <122519877+JamesHutchison@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:55:44 +0000 Subject: [PATCH 1/6] Fix for client not reconnecting on activity --- .../@reactpy/client/src/reactpy-client.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/js/packages/@reactpy/client/src/reactpy-client.ts b/src/js/packages/@reactpy/client/src/reactpy-client.ts index c69db96bc..cd2cc3553 100644 --- a/src/js/packages/@reactpy/client/src/reactpy-client.ts +++ b/src/js/packages/@reactpy/client/src/reactpy-client.ts @@ -163,7 +163,7 @@ export class SimpleReactPyClient private readonly urls: ServerUrls; private socket!: { current?: WebSocket }; private idleDisconnectTimeMillis: number; - private lastMessageTime: number; + private lastActivityTime: number; private reconnectOptions: ReconnectProps | undefined; private messageQueue: any[] = []; private socketLoopIntervalId?: number | null; @@ -190,7 +190,7 @@ export class SimpleReactPyClient ); this.idleDisconnectTimeMillis = (props.idleDisconnectTimeSeconds || 240) * 1000; this.connectionTimeout = props.connectionTimeout || 5000; - this.lastMessageTime = Date.now() + this.lastActivityTime = Date.now() this.reconnectOptions = props.reconnectOptions this.debugMessages = props.debugMessages || false; this.sleeping = false; @@ -213,14 +213,16 @@ export class SimpleReactPyClient this.reconnect() - const reconnectOnUserAction = (ev: any) => { + const handleUserAction = (ev: any) => { + this.lastActivityTime = Date.now(); if (!this.isReady && !this.isReconnecting) { + this.sleeping = false; this.reconnect(); } } - window.addEventListener('mousemove', reconnectOnUserAction); - window.addEventListener('scroll', reconnectOnUserAction); + window.addEventListener('mousemove', handleUserAction); + window.addEventListener('scroll', handleUserAction); } protected invokeLayoutUpdateHandlers(path: string, model: any) { @@ -324,6 +326,7 @@ export class SimpleReactPyClient if (this.debugMessages) { logger.log("Sending message", message); } + this.lastActivityTime = Date.now(); this.socket.current.send(JSON.stringify(message)); } } @@ -331,7 +334,7 @@ export class SimpleReactPyClient idleTimeoutCheck(): void { if (!this.socket) return; - if (Date.now() - this.lastMessageTime > this.idleDisconnectTimeMillis) { + if (Date.now() - this.lastActivityTime > this.idleDisconnectTimeMillis) { if (this.socket.current && this.socket.current.readyState === WebSocket.OPEN) { logger.warn("Closing socket connection due to idle activity"); this.sleeping = true; @@ -410,7 +413,7 @@ export class SimpleReactPyClient this.reconnect(onOpen, thisInterval, newRetriesRemaining, lastAttempt); } }, - onMessage: async ({ data }) => { this.lastMessageTime = Date.now(); this.handleIncoming(JSON.parse(data)) }, + onMessage: async ({ data }) => { this.lastActivityTime = Date.now(); this.handleIncoming(JSON.parse(data)) }, ...this.reconnectOptions, }); this.socketLoopIntervalId = window.setInterval(() => { this.socketLoop() }, 30); @@ -431,7 +434,7 @@ export class SimpleReactPyClient } else { this.messageQueue.push(message); } - this.lastMessageTime = Date.now() + this.lastActivityTime = Date.now() this.sleeping = false; this.ensureConnected(); } From 8c68c5bd661a05e011eb53a10b73f95bea40de15 Mon Sep 17 00:00:00 2001 From: James Hutchison <122519877+JamesHutchison@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:09:30 +0000 Subject: [PATCH 2/6] wip --- src/js/packages/@reactpy/client/src/reactpy-client.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/js/packages/@reactpy/client/src/reactpy-client.ts b/src/js/packages/@reactpy/client/src/reactpy-client.ts index cd2cc3553..be0021b3a 100644 --- a/src/js/packages/@reactpy/client/src/reactpy-client.ts +++ b/src/js/packages/@reactpy/client/src/reactpy-client.ts @@ -145,8 +145,8 @@ type ReconnectProps = { maxRetries?: number; backoffRate?: number; intervalJitter?: number; - reconnectingCallback?: Function; - reconnectedCallback?: Function; + reconnectingCallback?: () => void; + reconnectedCallback?: () => void; }; enum messageTypes { @@ -174,8 +174,8 @@ export class SimpleReactPyClient private salt: string; private shouldReconnect: boolean; private connectionTimeout: number; - private reconnectingCallback: Function; - private reconnectedCallback: Function; + private reconnectingCallback: () => void; + private reconnectedCallback: () => void; private didReconnectingCallback: boolean; constructor(props: SimpleReactPyClientProps) { @@ -338,6 +338,7 @@ export class SimpleReactPyClient if (this.socket.current && this.socket.current.readyState === WebSocket.OPEN) { logger.warn("Closing socket connection due to idle activity"); this.sleeping = true; + this.isReconnecting = false; this.socket.current.close(); } } From 063a65967a227cc36ad6c30c44c1ee99af92b09e Mon Sep 17 00:00:00 2001 From: James Hutchison <122519877+JamesHutchison@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:18:30 +0000 Subject: [PATCH 3/6] wip --- src/js/packages/@reactpy/client/src/reactpy-client.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/js/packages/@reactpy/client/src/reactpy-client.ts b/src/js/packages/@reactpy/client/src/reactpy-client.ts index be0021b3a..2333185ba 100644 --- a/src/js/packages/@reactpy/client/src/reactpy-client.ts +++ b/src/js/packages/@reactpy/client/src/reactpy-client.ts @@ -373,6 +373,8 @@ export class SimpleReactPyClient if (!this.didReconnectingCallback && this.reconnectingCallback && maxRetries != connectionAttemptsRemaining) { this.didReconnectingCallback = true; this.reconnectingCallback(); + } else if (!this.sleeping) { + this.isReconnecting = true; } if (maxRetries < connectionAttemptsRemaining) From 0bdafcfa3c3a4013e89f20173b2e476f321eb723 Mon Sep 17 00:00:00 2001 From: James Hutchison <122519877+JamesHutchison@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:22:22 +0000 Subject: [PATCH 4/6] wip --- src/js/packages/@reactpy/client/src/reactpy-client.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/js/packages/@reactpy/client/src/reactpy-client.ts b/src/js/packages/@reactpy/client/src/reactpy-client.ts index 2333185ba..4bdae6e34 100644 --- a/src/js/packages/@reactpy/client/src/reactpy-client.ts +++ b/src/js/packages/@reactpy/client/src/reactpy-client.ts @@ -373,8 +373,6 @@ export class SimpleReactPyClient if (!this.didReconnectingCallback && this.reconnectingCallback && maxRetries != connectionAttemptsRemaining) { this.didReconnectingCallback = true; this.reconnectingCallback(); - } else if (!this.sleeping) { - this.isReconnecting = true; } if (maxRetries < connectionAttemptsRemaining) @@ -398,10 +396,11 @@ export class SimpleReactPyClient if (Date.now() - lastAttempt > maxInterval * 2) { interval = 750; connectionAttemptsRemaining = maxRetries; + } else if (!this.sleeping) { + this.isReconnecting = true; } lastAttempt = Date.now() this.shouldReconnect = false; - this.isReconnecting = true; this.isReady = false; if (this.socketLoopIntervalId) clearInterval(this.socketLoopIntervalId); From e72dd75825e92656c271758150d2e0bff22b0660 Mon Sep 17 00:00:00 2001 From: James Hutchison <122519877+JamesHutchison@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:28:37 +0000 Subject: [PATCH 5/6] wip --- src/js/packages/@reactpy/client/src/reactpy-client.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/js/packages/@reactpy/client/src/reactpy-client.ts b/src/js/packages/@reactpy/client/src/reactpy-client.ts index 4bdae6e34..68e76fb98 100644 --- a/src/js/packages/@reactpy/client/src/reactpy-client.ts +++ b/src/js/packages/@reactpy/client/src/reactpy-client.ts @@ -177,6 +177,7 @@ export class SimpleReactPyClient private reconnectingCallback: () => void; private reconnectedCallback: () => void; private didReconnectingCallback: boolean; + private willReconnect: boolean; constructor(props: SimpleReactPyClientProps) { super(); @@ -195,6 +196,7 @@ export class SimpleReactPyClient this.debugMessages = props.debugMessages || false; this.sleeping = false; this.isReconnecting = false; + this.willReconnect = false; this.isReady = false this.salt = ""; this.shouldReconnect = false; @@ -292,7 +294,7 @@ export class SimpleReactPyClient } indicateReconnect(): void { - const isReconnecting = this.isReconnecting ? "yes" : "no"; + const isReconnecting = this.willReconnect ? "yes" : "no"; this.sendMessage({ "type": messageTypes.reconnectingCheck, "value": isReconnecting }, true) } @@ -388,11 +390,12 @@ export class SimpleReactPyClient this.reconnectedCallback(); this.didReconnectingCallback = false; } + this.willReconnect = true; if (onOpen) onOpen(); }, onClose: () => { - // reset retry interval + // reset retry interval on successful connection if (Date.now() - lastAttempt > maxInterval * 2) { interval = 750; connectionAttemptsRemaining = maxRetries; From 6099e1b333e79defaafbbdc04eb5b9d9365d0524 Mon Sep 17 00:00:00 2001 From: James Hutchison <122519877+JamesHutchison@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:31:31 +0000 Subject: [PATCH 6/6] wip --- src/js/packages/@reactpy/client/src/reactpy-client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/packages/@reactpy/client/src/reactpy-client.ts b/src/js/packages/@reactpy/client/src/reactpy-client.ts index 68e76fb98..005a11473 100644 --- a/src/js/packages/@reactpy/client/src/reactpy-client.ts +++ b/src/js/packages/@reactpy/client/src/reactpy-client.ts @@ -211,6 +211,7 @@ export class SimpleReactPyClient this.onMessage(messageTypes.layoutUpdate, (msg) => { this.updateClientState(msg.state_vars); this.invokeLayoutUpdateHandlers(msg.path, msg.model); + this.willReconnect = true; // don't indicate a reconnect until at least one successful layout update }) this.reconnect() @@ -390,7 +391,6 @@ export class SimpleReactPyClient this.reconnectedCallback(); this.didReconnectingCallback = false; } - this.willReconnect = true; if (onOpen) onOpen(); },