From 90fc94a83ba697909d3935aacff33c1789f19456 Mon Sep 17 00:00:00 2001 From: Yudhi Armyndharis Date: Tue, 23 Jun 2026 16:13:43 +0700 Subject: [PATCH] fix(gsheets-logger): clamp flush interval/batch size to safe positives (v0.2.2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A non-numeric or zero/negative flushIntervalSec coerced to NaN, and setInterval(NaN) fires at ~1ms — a flush hot-loop that burns CPU and Sheets API quota. A NaN batch size silently disabled the size trigger. Both are now validated in parseConfig and fall back to the documented defaults (5s / 20 rows). --- README.md | 2 +- gsheets-logger/CHANGELOG.md | 9 +++++++++ gsheets-logger/README.md | 2 +- gsheets-logger/index.test.ts | 13 +++++++++++++ gsheets-logger/index.ts | 8 ++++++-- gsheets-logger/manifest.json | 2 +- plugins.json | 4 ++-- 7 files changed, 33 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 43be3fa..4435160 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ This repository provides: | [`chat-flow`](./chat-flow) | Interactive, stateful auto-reply: a trigger word starts a greeting + numbered menu, replies traverse a configurable menu tree, and per-chat state expires after 15 minutes. | 1.0.2 | stable | | [`faq-bot`](./faq-bot) | Auto-replies to inbound WhatsApp messages from configurable FAQ keyword/regex rules. | 0.1.1 | stable | | [`group-translate`](./group-translate) | Auto-translates group messages between participants' languages via a LibreTranslate backend. Configure in-chat with /tr commands. Admin-gated; disabled until enabled. | 1.0.2 | stable | -| [`gsheets-logger`](./gsheets-logger) | Logs WhatsApp message events to a Google Sheet via a service account. | 0.2.1 | stable | +| [`gsheets-logger`](./gsheets-logger) | Logs WhatsApp message events to a Google Sheet via a service account. | 0.2.2 | stable | The table above is generated from each plugin's `manifest.json` + `CHANGELOG.md` by `npm run catalog` diff --git a/gsheets-logger/CHANGELOG.md b/gsheets-logger/CHANGELOG.md index ff242a8..eab0c98 100644 --- a/gsheets-logger/CHANGELOG.md +++ b/gsheets-logger/CHANGELOG.md @@ -8,6 +8,15 @@ The version here always matches `manifest.json`'s `version`. ## [Unreleased] +## [0.2.2] — 2026-06-23 + +### Fixed + +- `flushIntervalSec` and `flushBatchSize` are now clamped to safe positive values. A non-numeric or + zero/negative interval previously coerced to `NaN`, which made the flush timer fire roughly every + millisecond (a hot-loop that burns CPU and Google Sheets API quota). Invalid values now fall back to + the documented defaults (5s / 20 rows). + ## [0.2.1] — 2026-06-23 ### Added diff --git a/gsheets-logger/README.md b/gsheets-logger/README.md index fc51c36..e4c4ff6 100644 --- a/gsheets-logger/README.md +++ b/gsheets-logger/README.md @@ -13,7 +13,7 @@ | Field | Value | | ----- | ----- | | **Identifier** | `gsheets-logger` | -| **Version** | 0.2.1 | +| **Version** | 0.2.2 | | **Released** | 2026-06-23 | | **Status** | stable | | **Author** | Yudhi Armyndharis | diff --git a/gsheets-logger/index.test.ts b/gsheets-logger/index.test.ts index 4f860c8..4b34b5a 100644 --- a/gsheets-logger/index.test.ts +++ b/gsheets-logger/index.test.ts @@ -23,6 +23,19 @@ test('parseConfig applies defaults', () => { assert.equal(config.flushBatchSize, 20); }); +test('parseConfig clamps non-numeric/non-positive flush interval and batch size to safe defaults', () => { + const base = { spreadsheetId: 'sid', serviceAccountJson: validSa }; + // Non-numeric / zero / negative interval must not coerce to NaN (which makes setInterval hot-loop at ~1ms). + assert.equal(parseConfig({ ...base, flushIntervalSec: 'abc' }).config.flushIntervalSec, 5); + assert.equal(parseConfig({ ...base, flushIntervalSec: 0 }).config.flushIntervalSec, 5); + assert.equal(parseConfig({ ...base, flushIntervalSec: -3 }).config.flushIntervalSec, 5); + assert.equal(parseConfig({ ...base, flushBatchSize: 'xyz' }).config.flushBatchSize, 20); + assert.equal(parseConfig({ ...base, flushBatchSize: 0 }).config.flushBatchSize, 20); + // Valid values pass through unchanged. + assert.equal(parseConfig({ ...base, flushIntervalSec: 10 }).config.flushIntervalSec, 10); + assert.equal(parseConfig({ ...base, flushBatchSize: 50 }).config.flushBatchSize, 50); +}); + test('flushBuffer clears the buffer on success', async () => { const buffer = [['a'], ['b']]; await flushBuffer(buffer, async () => {}); diff --git a/gsheets-logger/index.ts b/gsheets-logger/index.ts index 648240d..9b80489 100644 --- a/gsheets-logger/index.ts +++ b/gsheets-logger/index.ts @@ -35,13 +35,17 @@ export function parseConfig(raw: Record): { config: LoggerConfi throw new Error('gsheets-logger: serviceAccountJson missing client_email/private_key'); } + // Clamp to safe positives: a non-numeric interval coerces to NaN, and setInterval(NaN) fires at ~1ms + // (a flush hot-loop / Sheets-quota burn). A NaN batch size silently disables the size trigger. + const flushIntervalSec = Number(raw.flushIntervalSec ?? 5); + const flushBatchSize = Number(raw.flushBatchSize ?? 20); return { config: { serviceAccountJson, spreadsheetId, sheetTab: String(raw.sheetTab ?? 'Logs'), - flushIntervalSec: Number(raw.flushIntervalSec ?? 5), - flushBatchSize: Number(raw.flushBatchSize ?? 20), + flushIntervalSec: Number.isFinite(flushIntervalSec) && flushIntervalSec > 0 ? flushIntervalSec : 5, + flushBatchSize: Number.isFinite(flushBatchSize) && flushBatchSize >= 1 ? flushBatchSize : 20, }, sa, }; diff --git a/gsheets-logger/manifest.json b/gsheets-logger/manifest.json index 08cc6d0..aeaf9e2 100644 --- a/gsheets-logger/manifest.json +++ b/gsheets-logger/manifest.json @@ -1,7 +1,7 @@ { "id": "gsheets-logger", "name": "Google Sheets Logger", - "version": "0.2.1", + "version": "0.2.2", "type": "extension", "main": "dist/index.js", "description": "Logs WhatsApp message events to a Google Sheet via a service account.", diff --git a/plugins.json b/plugins.json index 7ab18fd..73619d5 100644 --- a/plugins.json +++ b/plugins.json @@ -783,7 +783,7 @@ { "id": "gsheets-logger", "name": "Google Sheets Logger", - "version": "0.2.1", + "version": "0.2.2", "type": "extension", "status": "stable", "description": "Logs WhatsApp message events to a Google Sheet via a service account.", @@ -803,7 +803,7 @@ "repoPath": "gsheets-logger", "repoUrl": "https://github.com/rmyndharis/OpenWA-plugins", "homepage": "https://github.com/rmyndharis/OpenWA-plugins/tree/main/gsheets-logger", - "download": "https://github.com/rmyndharis/OpenWA-plugins/releases/download/gsheets-logger-v0.2.1/gsheets-logger.zip", + "download": "https://github.com/rmyndharis/OpenWA-plugins/releases/download/gsheets-logger-v0.2.2/gsheets-logger.zip", "i18n": { "es": { "name": "Registrador en Google Sheets",