Skip to content

Commit 99d91d5

Browse files
committed
test(knowledge): pin the schedule rewrite's repair of already-stored rows
Scope the column-precision query to the test schema. It matched on table name alone, so in CI — where the database already holds the migrated public table — it saw four columns instead of two and failed. A local run passed because the throwaway schema was the only place that table existed. Write the sub-millisecond schedule before applying the migration rather than after, so the test pins the rewrite rounding an already-wedged row, not just the narrowed column refusing new ones. Without the migration it now fails on exactly that claim.
1 parent e5dea1b commit 99d91d5

1 file changed

Lines changed: 24 additions & 10 deletions

File tree

‎packages/db/scripts/connector-sync-schedule-precision.postgres.test.ts‎

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
migrationTestDatabaseUrl,
55
withMigrationSchema,
66
} from '@sim/db/scripts/migration-fixture'
7+
import type postgres from 'postgres'
78
import { describe, expect, it } from 'vitest'
89

910
const migration = readFileSync(
@@ -18,29 +19,42 @@ const migration = readFileSync(
1819
*/
1920
const SUB_MILLISECOND = '2026-09-16 17:15:28.261433'
2021

22+
function insertSchedule(sql: postgres.Sql, id: string): Promise<unknown> {
23+
return sql.unsafe(`INSERT INTO knowledge_connector (id, next_member_sync_at, next_sync_at)
24+
VALUES ('${id}', TIMESTAMP '${SUB_MILLISECOND}', TIMESTAMP '${SUB_MILLISECOND}')`)
25+
}
26+
27+
/** The sub-millisecond remainder of each schedule, which a `Date` round trip cannot carry. */
28+
async function subMillisecondsOf(sql: postgres.Sql, id: string): Promise<number[]> {
29+
const [row] = await sql<{ member: number; content: number }[]>`
30+
SELECT EXTRACT(microseconds FROM next_member_sync_at)::int % 1000 AS member,
31+
EXTRACT(microseconds FROM next_sync_at)::int % 1000 AS content
32+
FROM knowledge_connector WHERE id = ${id}`
33+
return [row.member, row.content]
34+
}
35+
2136
describe.skipIf(!migrationTestDatabaseUrl)('connector sync schedule precision', () => {
22-
it('discards sub-millisecond precision a SQL writer would otherwise store', async () => {
37+
it('rounds schedules a SQL writer stored, and refuses to store new ones', async () => {
2338
await withMigrationSchema('sync_precision', async (sql) => {
2439
await sql`CREATE TABLE knowledge_connector (
2540
id text PRIMARY KEY,
2641
next_member_sync_at timestamp,
2742
next_sync_at timestamp
2843
)`
44+
await insertSchedule(sql, 'wedged')
45+
expect(await subMillisecondsOf(sql, 'wedged')).toEqual([433, 433])
46+
2947
await applyMigration(sql, migration)
3048
await applyMigration(sql, migration)
3149

32-
await sql.unsafe(`INSERT INTO knowledge_connector (id, next_member_sync_at, next_sync_at)
33-
VALUES ('c1', TIMESTAMP '${SUB_MILLISECOND}', TIMESTAMP '${SUB_MILLISECOND}')`)
34-
35-
const [stored] = await sql<{ member_sub_ms: number; content_sub_ms: number }[]>`
36-
SELECT EXTRACT(microseconds FROM next_member_sync_at)::int % 1000 AS member_sub_ms,
37-
EXTRACT(microseconds FROM next_sync_at)::int % 1000 AS content_sub_ms
38-
FROM knowledge_connector WHERE id = 'c1'`
39-
expect([stored.member_sub_ms, stored.content_sub_ms]).toEqual([0, 0])
50+
expect(await subMillisecondsOf(sql, 'wedged')).toEqual([0, 0])
51+
await insertSchedule(sql, 'fresh')
52+
expect(await subMillisecondsOf(sql, 'fresh')).toEqual([0, 0])
4053

4154
const declared = await sql<{ column_name: string; datetime_precision: number }[]>`
4255
SELECT column_name, datetime_precision FROM information_schema.columns
43-
WHERE table_name = 'knowledge_connector'
56+
WHERE table_schema = current_schema()
57+
AND table_name = 'knowledge_connector'
4458
AND column_name IN ('next_member_sync_at', 'next_sync_at')
4559
ORDER BY column_name`
4660
expect(declared.map((c) => [c.column_name, c.datetime_precision])).toEqual([

0 commit comments

Comments
 (0)