diff --git a/packages/phone-number-privacy/signer/.env b/packages/phone-number-privacy/signer/.env index 1e91f1b99a4..17849657cdd 100644 --- a/packages/phone-number-privacy/signer/.env +++ b/packages/phone-number-privacy/signer/.env @@ -32,7 +32,7 @@ ALFAJORES_ODIS_BLOCKCHAIN_PROVIDER=https://alfajores-forno.celo-testnet.org MAINNET_ODIS_BLOCKCHAIN_PROVIDER=https://forno.celo.org ODIS_DOMAINS_TEST_KEY_VERSION=1 ODIS_PNP_TEST_KEY_VERSION=1 -DEPLOYED_SIGNER_SERVICE_VERSION=3.0.0 +DEPLOYED_SIGNER_SERVICE_VERSION=3.0.1 # PUBKEYS STAGING_DOMAINS_PUBKEY=7FsWGsFnmVvRfMDpzz95Np76wf/1sPaK0Og9yiB+P8QbjiC8FV67NBans9hzZEkBaQMhiapzgMR6CkZIZPvgwQboAxl65JWRZecGe5V3XO4sdKeNemdAZ2TzQuWkuZoA ALFAJORES_DOMAINS_PUBKEY=+ZrxyPvLChWUX/DyPw6TuGwQH0glDJEbSrSxUARyP5PuqYyP/U4WZTV1e0bAUioBZ6QCJMiLpDwTaFvy8VnmM5RBbLQUMrMg5p4+CBCqj6HhsMfcyUj8V0LyuNdStlCB diff --git a/packages/phone-number-privacy/signer/package.json b/packages/phone-number-privacy/signer/package.json index f7d4806b8a5..c7f9e5b59fe 100644 --- a/packages/phone-number-privacy/signer/package.json +++ b/packages/phone-number-privacy/signer/package.json @@ -1,6 +1,6 @@ { "name": "@celo/phone-number-privacy-signer", - "version": "3.0.1-dev", + "version": "3.0.2-dev", "description": "Signing participator of ODIS", "author": "Celo", "license": "Apache-2.0", diff --git a/packages/phone-number-privacy/signer/src/common/handler.ts b/packages/phone-number-privacy/signer/src/common/handler.ts index 23ed6252116..4efad1e381b 100644 --- a/packages/phone-number-privacy/signer/src/common/handler.ts +++ b/packages/phone-number-privacy/signer/src/common/handler.ts @@ -95,7 +95,7 @@ export function meteringHandler( histogram: client.Histogram, handler: PromiseHandler ): PromiseHandler { - return (req, res) => newMeter(histogram, req.url)(() => handler(req, res)) + return (req, res) => newMeter(histogram, req.url)(async () => handler(req, res)) } export function timeoutHandler( @@ -103,17 +103,33 @@ export function timeoutHandler( handler: PromiseHandler ): PromiseHandler { return async (req, res) => { - const timeoutSignal = (AbortSignal as any).timeout(timeoutMs) - timeoutSignal.addEventListener( - 'abort', - () => { - if (!res.headersSent) { - Counters.timeouts.inc() - sendFailure(ErrorMessage.TIMEOUT_FROM_SIGNER, 500, res, req.url) - } - }, - { once: true } - ) + const timeoutId = setTimeout(() => { + if (!res.headersSent) { + Counters.timeouts.inc() + sendFailure(ErrorMessage.TIMEOUT_FROM_SIGNER, 500, res, req.url) + } + }, timeoutMs) + + try { + await handler(req, res) + } finally { + // Clears the timeout if it answers first + clearTimeout(timeoutId) + } + } +} + +export function connectionClosedHandler( + handler: PromiseHandler +): PromiseHandler { + return async (req, res) => { + req.on('close', () => { + if (res.socket?.destroyed) { + res.locals.logger.info('connection closed') + Counters.connectionClosed.inc() + res.end() + } + }) await handler(req, res) } @@ -141,8 +157,11 @@ export function resultHandler( ): PromiseHandler { return async (req, res) => { const result = await resHandler(req, res) - send(res, result.body, result.status, res.locals.logger) - Counters.responses.labels(req.url, result.status.toString()).inc() + // Check if the response was ended + if (!res.writableEnded) { + send(res, result.body, result.status, res.locals.logger) + Counters.responses.labels(req.url, result.status.toString()).inc() + } } } @@ -170,16 +189,19 @@ function sendFailure( endpoint: string, body?: Record // TODO remove any ) { - send( - response, - { - success: false, - version: getSignerVersion(), - error, - ...body, - }, - status, - response.locals.logger - ) - Counters.responses.labels(endpoint, status.toString()).inc() + // Check if the response was ended + if (!response.writableEnded) { + send( + response, + { + success: false, + version: getSignerVersion(), + error, + ...body, + }, + status, + response.locals.logger + ) + Counters.responses.labels(endpoint, status.toString()).inc() + } } diff --git a/packages/phone-number-privacy/signer/src/common/metrics.ts b/packages/phone-number-privacy/signer/src/common/metrics.ts index 2c009cabab3..311509ede6e 100644 --- a/packages/phone-number-privacy/signer/src/common/metrics.ts +++ b/packages/phone-number-privacy/signer/src/common/metrics.ts @@ -60,6 +60,10 @@ export const Counters = { name: 'errors_thrown_after_response_sent', help: 'Counter for the number of errors thrown after a response was already sent', }), + connectionClosed: new Counter({ + name: 'connection_closed', + help: 'Counter for the number of closed connections caught in Signer', + }), } const buckets = [ 0.001, 0.01, 0.1, 0.2, 0.3, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.3, 2.6, 2.9, 3.5, diff --git a/packages/phone-number-privacy/signer/src/server.ts b/packages/phone-number-privacy/signer/src/server.ts index 56978ac66ca..2933cf7c229 100644 --- a/packages/phone-number-privacy/signer/src/server.ts +++ b/packages/phone-number-privacy/signer/src/server.ts @@ -14,6 +14,7 @@ import { IncomingMessage, ServerResponse } from 'node:http' import * as PromClient from 'prom-client' import { catchErrorHandler, + connectionClosedHandler, disabledHandler, Locals, meteringHandler, @@ -144,7 +145,10 @@ function createHandler( tracingHandler( meteringHandler( Histograms.responseLatency, - timeoutHandler(timeoutMs, enabled ? resultHandler(action) : disabledHandler) + timeoutHandler( + timeoutMs, + enabled ? connectionClosedHandler(resultHandler(action)) : disabledHandler + ) ) ) )