Skip to content

Commit 1a6809e

Browse files
committed
test(realtime): start delivery deadline after HTTP action
1 parent ebfa1c3 commit 1a6809e

1 file changed

Lines changed: 60 additions & 31 deletions

File tree

‎apps/sim/scripts/test-file-list-realtime-e2e.ts‎

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,50 @@ function json(response: Awaited<ReturnType<typeof request>>, expected = 200) {
109109
assert.equal(response.status, expected, 'Unexpected HTTP status; inspect private app logs')
110110
return toRecord(JSON.parse(response.text))
111111
}
112-
function waitEvent(socket: Socket, event: string, rejectEvent?: string, timeout = 15_000) {
113-
return new Promise<Record<string, unknown>>((resolve, reject) => {
114-
const timer = setTimeout(() => finish(new Error(`Timed out waiting for ${event}`)), timeout)
112+
async function waitEvent(
113+
socket: Socket,
114+
event: string,
115+
rejectEvent?: string,
116+
timeout = 15_000,
117+
action?: () => Promise<void>
118+
) {
119+
let timer: ReturnType<typeof setTimeout> | undefined
120+
let settled = false
121+
let startDeadline: () => void = () => undefined
122+
let accept: (value: unknown) => void
123+
let deny: (value: unknown) => void
124+
const cleanup = () => {
125+
clearTimeout(timer)
126+
socket.off(event, accept)
127+
if (rejectEvent) socket.off(rejectEvent, deny)
128+
}
129+
const signal = new Promise<Record<string, unknown>>((resolve, reject) => {
115130
function finish(error?: Error, value?: unknown) {
116-
clearTimeout(timer)
117-
socket.off(event, accept)
118-
if (rejectEvent) socket.off(rejectEvent, deny)
131+
settled = true
132+
cleanup()
119133
if (error) reject(error)
120134
else resolve(toRecord(value))
121135
}
122-
function accept(value: unknown) {
123-
finish(undefined, value)
124-
}
125-
function deny(value: unknown) {
136+
accept = (value: unknown) => finish(undefined, value)
137+
deny = (value: unknown) =>
126138
finish(new Error(`${event} rejected: ${String(toRecord(value).code ?? 'connection error')}`))
127-
}
128139
socket.once(event, accept)
129140
if (rejectEvent) socket.once(rejectEvent, deny)
141+
/** The HTTP action has its own deadline; compilation time must not consume delivery time. */
142+
startDeadline = () => {
143+
if (!settled)
144+
timer = setTimeout(() => finish(new Error(`Timed out waiting for ${event}`)), timeout)
145+
}
130146
})
147+
/** Observe early rejection while the bounded HTTP action is still running. */
148+
void signal.catch(() => undefined)
149+
try {
150+
if (action) await action()
151+
startDeadline()
152+
return await signal
153+
} finally {
154+
cleanup()
155+
}
131156
}
132157
async function connect(cookie: string) {
133158
const token = required(
@@ -153,9 +178,7 @@ async function joinRoom(socket: Socket, type: 'project-files' | 'workspace-files
153178
}
154179
async function changed(action: () => Promise<void>) {
155180
const count = projectEvents.length
156-
const signal = waitEvent(reader, 'project-files-changed')
157-
await action()
158-
const event = await signal
181+
const event = await waitEvent(reader, 'project-files-changed', undefined, 15_000, action)
159182
assert.deepEqual(Object.keys(event).sort(), ['projectId', 'timestamp'])
160183
assert.equal(event.projectId, fixture.projectId)
161184
assert.equal(typeof event.timestamp, 'number')
@@ -294,28 +317,34 @@ try {
294317
await check(
295318
'create broadcasts only after the canonical file is readable and never to the workspace room',
296319
async () => {
297-
const retainedMembership = waitEvent(owner, 'project-files-changed')
298-
await changed(async () => {
299-
const file = toRecord(
300-
json(
301-
await request(prefix(), 'POST', {
302-
name: `live-${generateId()}.md`,
303-
content: 'first version',
304-
contentType: 'text/markdown',
305-
encoding: 'utf-8',
306-
}),
307-
201
308-
).file
309-
)
310-
fileId = required(file.id)
311-
revision = required(json(await request(`${prefix()}/${fileId}/versions`)).revision)
312-
})
320+
const retainedMembership = await waitEvent(
321+
owner,
322+
'project-files-changed',
323+
undefined,
324+
15_000,
325+
() =>
326+
changed(async () => {
327+
const file = toRecord(
328+
json(
329+
await request(prefix(), 'POST', {
330+
name: `live-${generateId()}.md`,
331+
content: 'first version',
332+
contentType: 'text/markdown',
333+
encoding: 'utf-8',
334+
}),
335+
201
336+
).file
337+
)
338+
fileId = required(file.id)
339+
revision = required(json(await request(`${prefix()}/${fileId}/versions`)).revision)
340+
})
341+
)
313342
assert.equal(
314343
toRecord(json(await request(`${prefix()}/${fileId}`, 'GET', undefined, readerCookie)).file)
315344
.id,
316345
fileId
317346
)
318-
assert.equal((await retainedMembership).projectId, fixture.projectId)
347+
assert.equal(retainedMembership.projectId, fixture.projectId)
319348
assert.equal(workspaceEvents.length, 0)
320349
}
321350
)

0 commit comments

Comments
 (0)