Skip to content

Commit ddeb1dc

Browse files
committed
Improve ping pong connection duration
1 parent 221cfa3 commit ddeb1dc

3 files changed

Lines changed: 25 additions & 12 deletions

File tree

backend/api/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ gcloud projects add-iam-policy-binding compass-130ba \
5454
--member="serviceAccount:253367029065-compute@developer.gserviceaccount.com" \
5555
--role="roles/secretmanager.secretAccessor"
5656
gcloud run services list
57+
gcloud compute backend-services update api-backend \
58+
--global \
59+
--timeout=600s
5760
```
5861

5962
Set up the saved search notifications job:

backend/shared/src/monitoring/metric-writer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class MetricWriter {
104104
for (const entry of freshEntries) {
105105
entry.fresh = false
106106
}
107-
if (!IS_GOOGLE_CLOUD) {
107+
if (IS_GOOGLE_CLOUD) {
108108
log.debug('Writing GCP metrics.', {entries: freshEntries})
109109
if (this.instance == null) {
110110
this.instance = await getInstanceInfo()

backend/shared/src/websockets/server.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ import {
1212
import {IS_LOCAL} from "common/envs/constants";
1313
import {getWebsocketUrl} from "common/api/utils";
1414

15+
// Extend the type definition locally
16+
interface HeartbeatWebSocket extends WebSocket {
17+
isAlive?: boolean
18+
}
19+
1520
const SWITCHBOARD = new Switchboard()
1621

1722
// if a connection doesn't ping for this long, we assume the other side is toast
18-
const CONNECTION_TIMEOUT_MS = 60 * 1000
23+
// const CONNECTION_TIMEOUT_MS = 60 * 1000
1924

2025
export class MessageParseError extends Error {
2126
details?: unknown
@@ -52,7 +57,7 @@ function parseMessage(data: RawData): ClientMessage {
5257
}
5358
}
5459

55-
function processMessage(ws: WebSocket, data: RawData): ServerMessage<'ack'> {
60+
function processMessage(ws: HeartbeatWebSocket, data: RawData): ServerMessage<'ack'> {
5661
try {
5762
const msg = parseMessage(data)
5863
const { type, txid } = msg
@@ -129,21 +134,26 @@ export function listen(server: HttpServer, path: string) {
129134
let deadConnectionCleaner: NodeJS.Timeout | undefined
130135
wss.on('listening', () => {
131136
log.info(`Web socket server listening on ${path}. ${getWebsocketUrl()}`)
132-
deadConnectionCleaner = setInterval(function ping() {
133-
const now = Date.now()
134-
for (const ws of wss.clients) {
135-
const lastSeen = SWITCHBOARD.getClient(ws).lastSeen
136-
if (lastSeen < now - CONNECTION_TIMEOUT_MS) {
137-
ws.terminate()
137+
deadConnectionCleaner = setInterval(() => {
138+
for (const ws of wss.clients as Set<HeartbeatWebSocket>) {
139+
if (ws.isAlive === false) {
140+
log.debug('Terminating dead connection');
141+
ws.terminate();
142+
continue;
138143
}
144+
ws.isAlive = false;
145+
log.debug('Sending ping to client');
146+
ws.ping();
139147
}
140-
}, CONNECTION_TIMEOUT_MS)
148+
}, 25000);
141149
})
142150
wss.on('error', (err) => {
143151
log.error('Error on websocket server.', { error: err })
144152
})
145-
wss.on('connection', (ws) => {
146-
// todo: should likely kill connections that haven't sent any ping for a long time
153+
wss.on('connection', (ws: HeartbeatWebSocket) => {
154+
ws.isAlive = true;
155+
log.debug('Received pong from client');
156+
ws.on('pong', () => (ws.isAlive = true));
147157
metrics.inc('ws/connections_established')
148158
metrics.set('ws/open_connections', wss.clients.size)
149159
log.debug('WS client connected.')

0 commit comments

Comments
 (0)