From 9be9d05dbebbad4dc7231fe0d0cccc6b5626fac1 Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Sep 2022 23:43:14 -0400 Subject: [PATCH 1/3] add redis process time and add timeout clause --- src/routes/getStatus.ts | 27 +++++++++++++++++++++------ test/cases/getStatus.ts | 12 ++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/routes/getStatus.ts b/src/routes/getStatus.ts index 7f764f5..a3dd206 100644 --- a/src/routes/getStatus.ts +++ b/src/routes/getStatus.ts @@ -3,25 +3,40 @@ import { Logger } from "../utils/logger"; import { Request, Response } from "express"; import os from "os"; import redis from "../utils/redis"; +import { setTimeout } from "timers/promises"; export async function getStatus(req: Request, res: Response): Promise { const startTime = Date.now(); let value = req.params.value as string[] | string; value = Array.isArray(value) ? value[0] : value; + let processTime, redisProcessTime = -1; + const timeoutPromise = async (): Promise => { + await setTimeout(5000); + return "timeout"; + }; try { - const dbVersion = (await db.prepare("get", "SELECT key, value FROM config where key = ?", ["version"])).value; + const dbVersion = await Promise.race([db.prepare("get", "SELECT key, value FROM config where key = ?", ["version"]), timeoutPromise()]) + .then(e => { + if (e === "timeout") return e; + processTime = Date.now() - startTime; + return e.value; + }); let statusRequests: unknown = 0; - try { - const numberRequests = await redis.increment("statusRequest"); - statusRequests = numberRequests?.[0]; - } catch (error) { } // eslint-disable-line no-empty + const numberRequests = await Promise.race([redis.increment("statusRequest"), timeoutPromise()]) + .then(e => { + if (e === "timeout") return [-1]; + redisProcessTime = Date.now() - startTime; + return e; + }); + statusRequests = numberRequests?.[0]; const statusValues: Record = { uptime: process.uptime(), commit: (global as any).HEADCOMMIT || "unknown", db: Number(dbVersion), startTime, - processTime: Date.now() - startTime, + processTime, + redisProcessTime, loadavg: os.loadavg().slice(1), // only return 5 & 15 minute load average statusRequests, hostname: os.hostname() diff --git a/test/cases/getStatus.ts b/test/cases/getStatus.ts index abf22b3..7f4ffaf 100644 --- a/test/cases/getStatus.ts +++ b/test/cases/getStatus.ts @@ -110,4 +110,16 @@ describe("getStatus", () => { }) .catch(err => done(err)); }); + + it("Should be able to get redis latency", function (done) { + if (!config.redis?.enabled) this.skip(); + client.get(endpoint) + .then(res => { + assert.strictEqual(res.status, 200); + const data = res.data; + assert.ok(data.redisProcessTime >= 0); + done(); + }) + .catch(err => done(err)); + }); }); From 00dae6d6a18a7f5bc29f948501f27746d5c63683 Mon Sep 17 00:00:00 2001 From: Michael C Date: Thu, 8 Sep 2022 16:34:39 -0400 Subject: [PATCH 2/3] switch to reused promiseOrTimeout --- src/routes/getStatus.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/routes/getStatus.ts b/src/routes/getStatus.ts index a3dd206..1295790 100644 --- a/src/routes/getStatus.ts +++ b/src/routes/getStatus.ts @@ -3,30 +3,30 @@ import { Logger } from "../utils/logger"; import { Request, Response } from "express"; import os from "os"; import redis from "../utils/redis"; -import { setTimeout } from "timers/promises"; +import { promiseOrTimeout } from "../utils/promise"; export async function getStatus(req: Request, res: Response): Promise { const startTime = Date.now(); let value = req.params.value as string[] | string; value = Array.isArray(value) ? value[0] : value; let processTime, redisProcessTime = -1; - const timeoutPromise = async (): Promise => { - await setTimeout(5000); - return "timeout"; - }; try { - const dbVersion = await Promise.race([db.prepare("get", "SELECT key, value FROM config where key = ?", ["version"]), timeoutPromise()]) + const dbVersion = await promiseOrTimeout(db.prepare("get", "SELECT key, value FROM config where key = ?", ["version"]), 5000) .then(e => { - if (e === "timeout") return e; processTime = Date.now() - startTime; return e.value; + }) + .catch(e => { + Logger.error(`status: SQL query timed out: ${e}`); }); let statusRequests: unknown = 0; - const numberRequests = await Promise.race([redis.increment("statusRequest"), timeoutPromise()]) + const numberRequests = await promiseOrTimeout(redis.increment("statusRequest"), 5000) .then(e => { - if (e === "timeout") return [-1]; redisProcessTime = Date.now() - startTime; return e; + }).catch(e => { + Logger.error(`status: redis increment timed out ${e}`); + return [-1]; }); statusRequests = numberRequests?.[0]; From 0e3eeece0167b5a99f0649c53da31d732c7dbfff Mon Sep 17 00:00:00 2001 From: Michael C Date: Thu, 8 Sep 2022 16:38:05 -0400 Subject: [PATCH 3/3] return -1 for unknown dbVersion --- src/routes/getStatus.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/getStatus.ts b/src/routes/getStatus.ts index 1295790..b817450 100644 --- a/src/routes/getStatus.ts +++ b/src/routes/getStatus.ts @@ -18,6 +18,7 @@ export async function getStatus(req: Request, res: Response): Promise }) .catch(e => { Logger.error(`status: SQL query timed out: ${e}`); + return -1; }); let statusRequests: unknown = 0; const numberRequests = await promiseOrTimeout(redis.increment("statusRequest"), 5000)