-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshared.test.ts
More file actions
134 lines (118 loc) Β· 3.51 KB
/
shared.test.ts
File metadata and controls
134 lines (118 loc) Β· 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { describe, expect, it } from "bun:test"
import { Panic } from "../../errors"
import { sleep } from "../../utils"
import { TaskExecution } from "../shared"
describe("TaskExecution", () => {
it("runs fail-fast task graphs and returns plain values", async () => {
await using execution = new TaskExecution(
undefined,
{
a() {
return 1
},
async b(this: { $result: { a: Promise<number> } }) {
const a = await this.$result.a
return a + 1
},
},
"fail-fast"
)
const result = await execution.execute()
expect(result).toEqual({ a: 1, b: 2 })
expect(execution.failedTask).toBeUndefined()
})
it("records failedTask and aborts siblings in fail-fast mode", async () => {
let signalAbortedInB = false
let resolveBReady!: () => void
const bReady = new Promise<void>((resolve) => {
resolveBReady = resolve
})
let resolveAbortObserved!: () => void
const abortObserved = new Promise<void>((resolve) => {
resolveAbortObserved = resolve
})
await using execution = new TaskExecution(
undefined,
{
async a() {
await bReady
throw new Error("boom")
},
async b(this: { $signal: AbortSignal }) {
if (this.$signal.aborted) {
resolveBReady()
signalAbortedInB = true
resolveAbortObserved()
return "never"
}
await new Promise<void>((resolve) => {
this.$signal.addEventListener(
"abort",
() => {
resolve()
},
{ once: true }
)
resolveBReady()
})
signalAbortedInB = this.$signal.aborted
resolveAbortObserved()
return "never"
},
},
"fail-fast"
)
try {
await execution.execute()
expect.unreachable("should have thrown")
} catch (error) {
expect((error as Error).message).toBe("boom")
}
await abortObserved
expect(execution.failedTask).toBe("a")
expect(signalAbortedInB).toBe(true)
})
it("collects all outcomes in settled mode without aborting siblings", async () => {
const error = new Error("boom")
let signalAbortedInB = false
await using execution = new TaskExecution(
undefined,
{
a() {
throw error
},
async b(this: { $signal: AbortSignal }) {
await sleep(5)
signalAbortedInB = this.$signal.aborted
return 2
},
},
"settled"
)
const result = (await execution.execute()) as {
a: { reason: unknown; status: string }
b: { status: string; value: unknown }
}
expect(result.a).toEqual({ reason: error, status: "rejected" })
expect(result.b).toEqual({ status: "fulfilled", value: 2 })
expect(signalAbortedInB).toBe(false)
expect(execution.failedTask).toBe("a")
})
it("marks invalid result references as rejected in settled mode", async () => {
await using execution = new TaskExecution(
undefined,
{
async a(this: { $result: Record<string, Promise<unknown>> }) {
return await this.$result.missing
},
},
"settled"
)
const result = (await execution.execute()) as {
a: { reason: unknown; status: string }
}
expect(result.a.status).toBe("rejected")
expect(result.a.reason).toBeInstanceOf(Panic)
expect((result.a.reason as Panic).code).toBe("TASK_UNKNOWN_REFERENCE")
})
})