Skip to content

Commit d4c9d68

Browse files
committed
test(file-search): observe cleanup deadlines without sleeping
1 parent 1d4374b commit d4c9d68

1 file changed

Lines changed: 39 additions & 37 deletions

File tree

apps/sim/lib/workspace-files/search/dispatcher.integration.ts

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/** Real PostgreSQL cancellation must roll back preparation and release its advisory lock. */
22
import { withUtcTimestamps } from '@sim/db/timestamps'
33
import { getPostgresErrorCode } from '@sim/utils/errors'
4-
import { sleep } from '@sim/utils/helpers'
54
import { generateId } from '@sim/utils/id'
65
import { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js'
76
import postgres from 'postgres'
@@ -138,7 +137,7 @@ describe('workspace file search dispatch PostgreSQL deadlines', () => {
138137
await expectAdvisoryLockReleased()
139138
}, 20_000)
140139

141-
it('releases committed claims after contention exceeds the preparation lock deadline', async () => {
140+
it('releases committed claims without the preparation deadlines', async () => {
142141
const fileId = generateId()
143142
const workspaceId = generateId()
144143
await connection`UPDATE workspace_file_search_backfill SET completed_at = now()`
@@ -149,43 +148,46 @@ describe('workspace file search dispatch PostgreSQL deadlines', () => {
149148
VALUES (${fileId}, ${workspaceId}, '2026-09-16', 'pending', now())`
150149
await connection`INSERT INTO workspace_file_search_dispatch_queue
151150
(workspace_id, enqueued_at, updated_at) VALUES (${workspaceId}, now(), now())`
151+
await connection`CREATE TABLE cleanup_timeouts (
152+
lock_timeout text, statement_timeout text, transaction_timeout text
153+
)`
154+
await connection`CREATE FUNCTION record_cleanup_timeouts() RETURNS trigger LANGUAGE plpgsql AS $$
155+
BEGIN
156+
INSERT INTO cleanup_timeouts VALUES (
157+
current_setting('lock_timeout'),
158+
current_setting('statement_timeout'),
159+
current_setting('transaction_timeout')
160+
);
161+
RETURN NEW;
162+
END
163+
$$`
164+
await connection`CREATE TRIGGER record_cleanup_timeouts AFTER UPDATE OF dispatched_at
165+
ON workspace_file_search_index FOR EACH ROW
166+
WHEN (OLD.dispatched_at IS NOT NULL AND NEW.dispatched_at IS NULL)
167+
EXECUTE FUNCTION record_cleanup_timeouts()`
152168

153169
const enqueueError = new Error('Queue unavailable')
154-
let blocker: Promise<unknown> | undefined
155-
mocks.batchTrigger.mockImplementationOnce(async () => {
156-
let locked = () => {}
157-
const lockReady = new Promise<void>((resolve) => {
158-
locked = resolve
159-
})
160-
blocker = connection.begin(async (tx) => {
161-
await tx`SELECT file_id FROM workspace_file_search_index WHERE file_id = ${fileId} FOR UPDATE`
162-
locked()
163-
await sleep(3_000)
164-
})
165-
await Promise.race([lockReady, blocker])
166-
throw enqueueError
167-
})
170+
mocks.batchTrigger.mockRejectedValueOnce(enqueueError)
168171

169-
try {
170-
await expect(dispatchWorkspaceFileSearchIndexJobs()).rejects.toBe(enqueueError)
171-
expect(mocks.batchTrigger).toHaveBeenCalledWith('workspace-file-search-index', [
172-
expect.objectContaining({
173-
payload: {
174-
fileId,
175-
workspaceId,
176-
sourceContentUpdatedAt: '2026-09-16T00:00:00.000Z',
177-
},
178-
}),
179-
])
180-
const [index] = await connection`SELECT dispatched_at FROM workspace_file_search_index
181-
WHERE file_id = ${fileId}`
182-
expect(index.dispatched_at).toBeNull()
183-
const [queued] =
184-
await connection`SELECT workspace_id FROM workspace_file_search_dispatch_queue
185-
WHERE workspace_id = ${workspaceId}`
186-
expect(queued.workspace_id).toBe(workspaceId)
187-
} finally {
188-
await blocker
189-
}
172+
await expect(dispatchWorkspaceFileSearchIndexJobs()).rejects.toBe(enqueueError)
173+
expect(mocks.batchTrigger).toHaveBeenCalledWith('workspace-file-search-index', [
174+
expect.objectContaining({
175+
payload: {
176+
fileId,
177+
workspaceId,
178+
sourceContentUpdatedAt: '2026-09-16T00:00:00.000Z',
179+
},
180+
}),
181+
])
182+
const [index] = await connection`SELECT dispatched_at FROM workspace_file_search_index
183+
WHERE file_id = ${fileId}`
184+
expect(index.dispatched_at).toBeNull()
185+
const [queued] = await connection`SELECT workspace_id FROM workspace_file_search_dispatch_queue
186+
WHERE workspace_id = ${workspaceId}`
187+
expect(queued.workspace_id).toBe(workspaceId)
188+
const timeouts = await connection`SELECT * FROM cleanup_timeouts`
189+
expect([...timeouts]).toEqual([
190+
{ lock_timeout: '0', statement_timeout: '0', transaction_timeout: '0' },
191+
])
190192
})
191193
})

0 commit comments

Comments
 (0)