Skip to content

Commit 2545a44

Browse files
authored
Merge pull request #227 from online-go/background-pinging
Better background-ping support
2 parents 72b3141 + 8801b99 commit 2545a44

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

src/engine/GobanSocket.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@ export interface GobanSocketOptions {
4545
/** Don't automatically send pings */
4646
dont_ping?: boolean;
4747

48+
/**
49+
* When true, pings are still sent (letting the browser throttle
50+
* naturally) but no timeout timers are armed and pong responses
51+
* are silently ignored (no latency/drift updates, no timeout
52+
* signals). Used when the tab is in the background so we keep the
53+
* connection alive through intermediaries without reacting to
54+
* unreliable timing measurements.
55+
*/
56+
background_pinging?: boolean;
57+
58+
/**
59+
* Timestamp (ms since epoch). Pong responses whose originating
60+
* ping was sent before this time are silently discarded. Set to
61+
* Date.now() when transitioning from background to foreground so
62+
* that stale in-flight pongs from the background period don't
63+
* pollute latency measurements.
64+
*/
65+
ignore_pongs_before?: number;
66+
4867
// Note: you can't turn off ping by setting ping interval to zero or undefined.
4968
ping_interval?: number; // milliseconds, applied if non-zero.
5069
timeout_delay?: number;
@@ -154,6 +173,20 @@ export class GobanSocket<
154173
this.socket = this.connect();
155174

156175
this.on("net/pong", ({ client, server }: { client: number; server: number }) => {
176+
// Ignore pongs from background pings: either we're still in
177+
// background mode, or this is a stale pong that arrived after
178+
// returning to the foreground.
179+
if (
180+
this.options.background_pinging ||
181+
(this.options.ignore_pongs_before && client < this.options.ignore_pongs_before)
182+
) {
183+
if (this.timeout_timer) {
184+
clearTimeout(this.timeout_timer);
185+
this.timeout_timer = undefined;
186+
}
187+
return;
188+
}
189+
157190
const now = Date.now();
158191
const latency = now - client;
159192
const drift = now - latency / 2 - server;
@@ -162,8 +195,8 @@ export class GobanSocket<
162195
this.emit("latency", latency, drift);
163196
if (this.timeout_timer) {
164197
clearTimeout(this.timeout_timer);
198+
this.timeout_timer = undefined;
165199
}
166-
///console.log("Pong:", this.url);
167200
});
168201
}
169202

@@ -183,6 +216,11 @@ export class GobanSocket<
183216
}
184217

185218
signalTimeout = () => {
219+
// A timeout timer from the last foreground ping may fire after
220+
// we've transitioned to background mode -- ignore it.
221+
if (this.options.background_pinging) {
222+
return;
223+
}
186224
this.emit("timeout");
187225
};
188226

@@ -198,7 +236,7 @@ export class GobanSocket<
198236
latency: this.latency,
199237
} as DataArgument<SendProtocol["net/ping"]>);
200238

201-
if (this.options.timeout_delay) {
239+
if (this.options.timeout_delay && !this.options.background_pinging) {
202240
this.timeout_timer = setTimeout(this.signalTimeout, this.options.timeout_delay);
203241
}
204242

0 commit comments

Comments
 (0)