mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
Merge PR 2966 into release/v3.8.8
fix(db): resolve 077 migration version collision blocking getDbInstance
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -53,6 +53,17 @@
|
||||
`INSPECTOR_TLS_INTERCEPT`, `INSPECTOR_SYSTEM_PROXY_GUARD_MINUTES`, `INSPECTOR_MAX_BODY_KB`,
|
||||
`INSPECTOR_MASK_SECRETS`, `INSPECTOR_LLM_HOSTS_EXTRA`, `INSPECTOR_INTERNAL_INGEST_TOKEN`).
|
||||
|
||||
### Fixed
|
||||
|
||||
- **db/migrations:** resolve a `077` migration version collision
|
||||
(`077_api_key_stream_default_mode.sql` vs `077_quota_pools.sql`) that made
|
||||
`getMigrationFiles()` throw and blocked `getDbInstance()` at startup (app would
|
||||
not boot; every DB-touching test was red). Renumbered the dependency-free,
|
||||
idempotent `quota_pools` migration to `085`, kept the non-idempotent
|
||||
`api_key_stream_default_mode` `ALTER` at `077`, added a retroactive
|
||||
`isSchemaAlreadyApplied` guard (case `085`), and a regression test enforcing
|
||||
unique migration prefixes.
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- **notion:** add Notion as an MCP context source — 6 tools (`notion_search`, `notion_list_databases`, `notion_get_database`, `notion_query_database`, `notion_read`, `notion_append_blocks`) scoped under `read:notion` / `write:notion`, with dashboard "Context Sources" tab, settings API, and token persistence in `key_value` table (#2959)
|
||||
|
||||
@@ -444,6 +444,11 @@ function isSchemaAlreadyApplied(
|
||||
// mid-file and skip the CREATE INDEX that follows, leaving the index
|
||||
// missing on DBs that re-execute the script after a partial first run.
|
||||
return hasColumn(db, "memories", "needs_reindex");
|
||||
case "085":
|
||||
// Retroactive guard for quota_pools migration renumbered from 077 → 085
|
||||
// (077 collided with 077_api_key_stream_default_mode). DBs that already
|
||||
// applied quota_pools under the old 077 number should not re-run as 085.
|
||||
return hasTable(db, "quota_pools") && hasTable(db, "quota_allocations");
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
-- Migration 073: quota_pools + quota_allocations
|
||||
-- Migration 085: quota_pools + quota_allocations
|
||||
--
|
||||
-- Renumbered from 077 → 085 (#2900 sibling fix): 077 collided with
|
||||
-- 077_api_key_stream_default_mode.sql, which made getMigrationFiles() throw a
|
||||
-- version-collision error and blocked getDbInstance() at startup. quota_pools
|
||||
-- has no dependents (no other migration references these tables) and is fully
|
||||
-- idempotent, so it can safely move to the next free number. DBs that already
|
||||
-- applied it under the old 077 number are guarded in isSchemaAlreadyApplied
|
||||
-- (case "085").
|
||||
--
|
||||
-- Creates the two tables that persist quota-sharing pools and per-API-key
|
||||
-- allocations within each pool. Idempotent: safe to run more than once.
|
||||
68
tests/unit/db-migration-version-uniqueness.test.ts
Normal file
68
tests/unit/db-migration-version-uniqueness.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Regression guard for the migration version collision that blocked
|
||||
* release/v3.8.8: `077_api_key_stream_default_mode.sql` and `077_quota_pools.sql`
|
||||
* both claimed prefix 077. getMigrationFiles() throws on such a collision, which
|
||||
* made getDbInstance() fail at startup and turned every DB-touching test red.
|
||||
*
|
||||
* quota_pools was renumbered 077 → 085 (it is dependency-free and idempotent;
|
||||
* api_key_stream_default_mode is a non-idempotent ALTER and stays at 077).
|
||||
*
|
||||
* This test asserts — purely from the filesystem, without booting the DB — that
|
||||
* no two live migration files share a numeric prefix (mirroring the runner's
|
||||
* own collision check, minus any SUPERSEDED_DUPLICATE_MIGRATIONS allowlisted
|
||||
* renamed pairs). It prevents the collision from being reintroduced.
|
||||
*/
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const MIGRATIONS_DIR = path.join(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"..",
|
||||
"..",
|
||||
"src",
|
||||
"lib",
|
||||
"db",
|
||||
"migrations"
|
||||
);
|
||||
|
||||
function migrationFiles(): Array<{ version: string; name: string }> {
|
||||
return fs
|
||||
.readdirSync(MIGRATIONS_DIR)
|
||||
.filter((f) => f.endsWith(".sql"))
|
||||
.map((filename) => {
|
||||
const m = filename.match(/^(\d+)_(.+)\.sql$/);
|
||||
return m ? { version: m[1], name: m[2] } : null;
|
||||
})
|
||||
.filter((x): x is { version: string; name: string } => x !== null);
|
||||
}
|
||||
|
||||
test("no two migration files share the same numeric prefix", () => {
|
||||
const byVersion = new Map<string, string[]>();
|
||||
for (const f of migrationFiles()) {
|
||||
if (!byVersion.has(f.version)) byVersion.set(f.version, []);
|
||||
byVersion.get(f.version)!.push(f.name);
|
||||
}
|
||||
const collisions = [...byVersion.entries()]
|
||||
.filter(([, names]) => names.length > 1)
|
||||
.map(([version, names]) => `${version} → [${names.join(", ")}]`);
|
||||
assert.deepEqual(
|
||||
collisions,
|
||||
[],
|
||||
`Migration version collision(s) detected: ${collisions.join("; ")}. ` +
|
||||
`Each migration must have a unique numeric prefix (rename to the next free number).`
|
||||
);
|
||||
});
|
||||
|
||||
test("quota_pools lives at 085 (renumbered from the 077 collision)", () => {
|
||||
const files = migrationFiles();
|
||||
const quotaPools = files.find((f) => f.name === "quota_pools");
|
||||
assert.ok(quotaPools, "quota_pools migration must exist");
|
||||
assert.equal(quotaPools.version, "085", "quota_pools must be renumbered to 085");
|
||||
// The standalone, non-idempotent column add stays at 077.
|
||||
const streamDefault = files.find((f) => f.name === "api_key_stream_default_mode");
|
||||
assert.ok(streamDefault, "api_key_stream_default_mode migration must exist");
|
||||
assert.equal(streamDefault.version, "077", "api_key_stream_default_mode stays at 077");
|
||||
});
|
||||
Reference in New Issue
Block a user