From 891cb26b2cc647333893aed32c72a897dd184459 Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour <42529354+KooshaPari@users.noreply.github.com> Date: Fri, 4 Sep 2026 22:33:16 -0700 Subject: [PATCH] fix(db): back-fill last_ping_at + last_pinged_reset_key on provider_connections (#12470) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged. Clean, surgical fix with its own regression guard. `ensureProviderConnectionsColumns()` reconciles the base columns that later data migrations assume, but `last_ping_at` / `last_pinged_reset_key` were only ever created by `123_quota_auto_ping` — so a lineage that skipped it kept a table that the quota auto-ping writes cannot target. Adding them to the reconciliation list is exactly the right place. Validated on `release/v3.8.51`: `tests/unit/db-schema-columns-split.test.ts` 10/10, including your new `back-fills last_ping columns on a pre-123 lineage` case and the idempotency re-run. `typecheck:core` clean, `check-file-size` OK. The `changelog.d/fixes/` fragment was already correct. Thank you — this is the shape a fix should have: root cause named, minimal diff, test that fails without it. --- .../fixes/12470-last-ping-at-backfill.md | 1 + src/lib/db/schemaColumns.ts | 2 ++ tests/unit/db-schema-columns-split.test.ts | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 changelog.d/fixes/12470-last-ping-at-backfill.md diff --git a/changelog.d/fixes/12470-last-ping-at-backfill.md b/changelog.d/fixes/12470-last-ping-at-backfill.md new file mode 100644 index 0000000000..09d45f4acd --- /dev/null +++ b/changelog.d/fixes/12470-last-ping-at-backfill.md @@ -0,0 +1 @@ +- **fix(db):** back-fill `last_ping_at` and `last_pinged_reset_key` on `provider_connections` during schema reconciliation so divergent lineages that skipped `123_quota_auto_ping` still accept quota auto-ping writes ([#12470](https://github.com/diegosouzapw/OmniRoute/pull/12470) — thanks @KooshaPari) diff --git a/src/lib/db/schemaColumns.ts b/src/lib/db/schemaColumns.ts index 2b58470948..068c140c69 100644 --- a/src/lib/db/schemaColumns.ts +++ b/src/lib/db/schemaColumns.ts @@ -27,6 +27,8 @@ export function ensureProviderConnectionsColumns(db: SqliteDatabase) { ["rate_limit_protection", "INTEGER DEFAULT 0"], ["last_used_at", "TEXT"], ["default_model", "TEXT"], // legacy-schema hole; later data migrations read it + ["last_ping_at", "TEXT"], // added by 123_quota_auto_ping; back-filled here for divergent lineages + ["last_pinged_reset_key", "TEXT"], // added by 123_quota_auto_ping; back-filled here for divergent lineages ]) { if (!columnNames.has(column)) { db.exec(`ALTER TABLE provider_connections ADD COLUMN ${column} ${type}`); diff --git a/tests/unit/db-schema-columns-split.test.ts b/tests/unit/db-schema-columns-split.test.ts index 9adebe3b93..9e7e249a6a 100644 --- a/tests/unit/db-schema-columns-split.test.ts +++ b/tests/unit/db-schema-columns-split.test.ts @@ -136,6 +136,8 @@ test("ensureProviderConnectionsColumns restores base columns required by later m assert.equal(hasColumn(db, "provider_connections", "provider_specific_data"), true); assert.equal(hasColumn(db, "provider_connections", "default_model"), true); + assert.equal(hasColumn(db, "provider_connections", "last_ping_at"), true); + assert.equal(hasColumn(db, "provider_connections", "last_pinged_reset_key"), true); const columnsAfterFirstRun = getTableColumns(db, "provider_connections").sort(); const indexesAfterFirstRun = ( db.prepare("PRAGMA index_list(provider_connections)").all() as Array<{ name: string }> @@ -163,3 +165,20 @@ test("ensureProviderConnectionsColumns restores base columns required by later m db.close?.(); } }); + +test("ensureProviderConnectionsColumns back-fills last_ping columns on a pre-123 lineage", () => { + const db = openMemoryDb(); + try { + db.exec("CREATE TABLE provider_connections (id TEXT PRIMARY KEY, provider TEXT NOT NULL)"); + assert.equal(hasColumn(db, "provider_connections", "last_ping_at"), false); + assert.equal(hasColumn(db, "provider_connections", "last_pinged_reset_key"), false); + + ensureProviderConnectionsColumns(db); + + assert.equal(hasColumn(db, "provider_connections", "last_ping_at"), true); + assert.equal(hasColumn(db, "provider_connections", "last_pinged_reset_key"), true); + assert.doesNotThrow(() => ensureProviderConnectionsColumns(db)); + } finally { + db.close?.(); + } +});