From 086c32f980f53caec96424234443224a88c817f2 Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Tue, 5 Aug 2025 09:56:11 +0000 Subject: [PATCH] chore: health check improvements to avoid performance issues - only once per minute - concurrency 1 - use default timeout --- src/index.ts | 22 +++++++++++++++------- src/utils/env.test.ts | 7 +------ src/utils/env.ts | 2 -- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/index.ts b/src/index.ts index 1a886f0..acaa92f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import { ConfigureController, ManifestController, StreamController } from './con import { BlockedError, logErrorAndReturnNiceString } from './error'; import { createExtractors, ExtractorRegistry } from './extractor'; import { createSources } from './source'; -import { contextFromRequestAndResponse, envGet, envIsProd, Fetcher, isHaydukInstance, StreamResolver } from './utils'; +import { contextFromRequestAndResponse, envGet, envIsProd, Fetcher, StreamResolver } from './utils'; console.log = console.warn = console.error = console.info = console.debug = () => { /* disable in favor of logger */ }; @@ -62,6 +62,7 @@ addon.get('/', (_req: Request, res: Response) => { res.redirect('/configure'); }); +let lastHealthCheckRequestsTimestamp = 0; addon.get('/health', async (req: Request, res: Response) => { const ctx = contextFromRequestAndResponse(req, res); @@ -74,9 +75,9 @@ addon.get('/health', async (req: Request, res: Response) => { let blockedCount = 0; let errorCount = 0; - const fetchPromises = urls.map(async (url) => { + const fetchFactories = urls.map(url => async () => { try { - await fetcher.head(ctx, url, { noCache: true, timeout: 5000 }); + await fetcher.head(ctx, url, { queueLimit: 1, noCache: true }); } catch (error) { if (error instanceof BlockedError) { blockedCount++; @@ -87,11 +88,18 @@ addon.get('/health', async (req: Request, res: Response) => { logErrorAndReturnNiceString(ctx, logger, url.href, error); } }); - await Promise.all(fetchPromises); - if (isHaydukInstance(req) && blockedCount > 0) { - res.status(503).json({ status: 'blocked' }); - } else if (errorCount === urls.length) { + if (Date.now() - lastHealthCheckRequestsTimestamp > 60000) { // every minute + await Promise.all(fetchFactories.map(fn => fn())); + lastHealthCheckRequestsTimestamp = Date.now(); + } + + if (blockedCount > 0) { + // TODO: fail health check and try to get a clean IP if infra is ready + logger.warn('IP might be not clean and leading to blocking.', ctx); + } + + if (errorCount === urls.length) { res.status(503).json({ status: 'error' }); } else { res.json({ status: 'ok' }); diff --git a/src/utils/env.test.ts b/src/utils/env.test.ts index f2bb4ff..cf135b3 100644 --- a/src/utils/env.test.ts +++ b/src/utils/env.test.ts @@ -1,5 +1,5 @@ import { Request } from 'express'; -import { envGet, envGetAppId, envGetAppName, envIsProd, isElfHostedInstance, isHaydukInstance } from './env'; +import { envGet, envGetAppId, envGetAppName, envIsProd, isElfHostedInstance } from './env'; describe('env', () => { test('envGet', () => { @@ -35,9 +35,4 @@ describe('env', () => { expect(isElfHostedInstance({ host: 'someuser.elfhosted.com' } as Request)).toBeTruthy(); expect(isElfHostedInstance({ host: 'webstreamr.hayd.uk' } as Request)).toBeFalsy(); }); - - test('isHaydukInstance', () => { - expect(isHaydukInstance({ host: 'webstreamr.hayd.uk' } as Request)).toBeTruthy(); - expect(isHaydukInstance({ host: 'someuser.elfhosted.com' } as Request)).toBeFalsy(); - }); }); diff --git a/src/utils/env.ts b/src/utils/env.ts index 854cd08..6251334 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -9,5 +9,3 @@ export const envGetAppName = (): string => process.env['MANIFEST_NAME'] || 'WebS export const envIsProd = (): boolean => process.env['NODE_ENV'] === 'production'; export const isElfHostedInstance = (req: Request): boolean => req.host.endsWith('elfhosted.com'); - -export const isHaydukInstance = (req: Request): boolean => req.host.endsWith('hayd.uk');