From bf4d538651ac4486c885833b86c0c2f698f0f29e Mon Sep 17 00:00:00 2001 From: liquidev Date: Mon, 2 Sep 2024 23:17:00 +0200 Subject: [PATCH] add ping/pong between client and server the purpose of this is to hopefully prevent nginx from reaping the connection, since there's data flowing through it every so often --- crates/rkgk/src/api/wall.rs | 4 ++++ crates/rkgk/src/api/wall/schema.rs | 4 ++++ static/session.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/crates/rkgk/src/api/wall.rs b/crates/rkgk/src/api/wall.rs index 18ababf..f5a8110 100644 --- a/crates/rkgk/src/api/wall.rs +++ b/crates/rkgk/src/api/wall.rs @@ -300,6 +300,10 @@ impl SessionLoop { async fn process_request(&mut self, ws: &mut WebSocket, request: Request) -> eyre::Result<()> { match request { + Request::Ping => { + ws.send(to_message(&Notify::Pong)).await?; + } + Request::Wall { wall_event } => { match &wall_event { // This match only concerns itself with drawing-related events to offload diff --git a/crates/rkgk/src/api/wall/schema.rs b/crates/rkgk/src/api/wall/schema.rs index 7467b38..30b41fc 100644 --- a/crates/rkgk/src/api/wall/schema.rs +++ b/crates/rkgk/src/api/wall/schema.rs @@ -69,6 +69,8 @@ pub enum LoginResponse { rename_all_fields = "camelCase" )] pub enum Request { + Ping, + Wall { wall_event: wall::EventKind, }, @@ -95,6 +97,8 @@ pub struct ChunkInfo { rename_all_fields = "camelCase" )] pub enum Notify { + Pong, + Wall { wall_event: wall::Event, }, diff --git a/static/session.js b/static/session.js index c917fb7..36bec0c 100644 --- a/static/session.js +++ b/static/session.js @@ -75,6 +75,8 @@ export async function registerUser(nickname) { } class Session extends EventTarget { + #sentPing = false; + constructor(userId, secret) { super(); this.userId = userId; @@ -193,6 +195,8 @@ class Session extends EventTarget { } async eventLoop() { + this.#pingLoop(); + try { while (true) { let event = await listen([this.ws, "message"]); @@ -207,7 +211,21 @@ class Session extends EventTarget { } } + #pingLoop() { + // Send small ping packets every 30 seconds to prevent reverse proxies from reaping the + // connection if the tab is in the background. + // (Browsers don't seem to send standard WebSocket pings if the tab is unfocused.) + // We don't actually use this packet for anything else, like establishing whether + // we still have a connection to the server, because the browser can handle that for us. + setInterval(() => this.sendPing(), 30000); + } + async #processNotify(notify) { + if (notify.notify == "pong") { + console.debug("pong received"); + this.#sentPing = false; + } + if (notify.notify == "wall") { this.dispatchEvent( Object.assign(new Event("wallEvent"), { @@ -229,6 +247,16 @@ class Session extends EventTarget { } } + sendPing() { + if (!this.#sentPing) { + console.debug("ping sent; waiting for pong"); + this.#sendJson({ + request: "ping", + }); + this.#sentPing = true; + } + } + sendCursor(x, y) { this.#sendJson({ request: "wall",