@akterjs/cli 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +47 -2
- package/dist/Argument-D81dqizB.mjs +57 -0
- package/dist/Array-B4kuTQeW.mjs +2323 -0
- package/dist/Boolean-kILIvmhE.mjs +26 -0
- package/dist/ChildProcess-BCIwxPGc.mjs +577 -0
- package/dist/CliError-Cf5xqkkj.mjs +633 -0
- package/dist/Command-Dzq9KM-h.mjs +5135 -0
- package/dist/Config-B6OND9WR.mjs +854 -0
- package/dist/Console-BKHUkH6a.mjs +141 -0
- package/dist/Data-CeCULr0-.mjs +251 -0
- package/dist/Digest-CBd3uv5B.mjs +348 -0
- package/dist/Duration-EH9Vy4U6.mjs +791 -0
- package/dist/Effect-CKFpqbmw.mjs +12911 -0
- package/dist/FileSystem-4pPcEb_i.mjs +1366 -0
- package/dist/HttpClientError-BUeMWx70.mjs +303 -0
- package/dist/HttpClientResponse-D5ZKICVV.mjs +855 -0
- package/dist/Match-CGPLZYrV.mjs +434 -0
- package/dist/MutableHashMap-f8nW8AJR.mjs +376 -0
- package/dist/MutableHashSet-_HI572Ya.mjs +155 -0
- package/dist/MutableRef-D4Qv592C.mjs +107 -0
- package/dist/Number-BvkRkfc-.mjs +137 -0
- package/dist/Option-DkxSnBhp.mjs +3967 -0
- package/dist/Order-C1JC991I.mjs +481 -0
- package/dist/Path-Djdv_eF5.mjs +130 -0
- package/dist/Queue-CO5UQ6os.mjs +1394 -0
- package/dist/Redacted-RkJrG5Me.mjs +160 -0
- package/dist/Ref-BIPOxJNH.mjs +267 -0
- package/dist/Runtime-BInIAwK3.mjs +297 -0
- package/dist/Schema-MiKt5K1v.mjs +10999 -0
- package/dist/SecureRandom-B_U4ysO3.mjs +279 -0
- package/dist/Semaphore-DOVJ4ZGS.mjs +177 -0
- package/dist/Stdio-KylmOBX_.mjs +74 -0
- package/dist/Stream-bK9QIETN.mjs +4012 -0
- package/dist/String-q5dcsVe4.mjs +351 -0
- package/dist/TerminalCapabilities-w_44MAca.mjs +1769 -0
- package/dist/WebCrypto-ZI_GNVlw.mjs +33 -0
- package/dist/actor-call.service-CGM_vD9u.mjs +1269 -0
- package/dist/actor-client.adapter-Coem7gF1.mjs +3691 -0
- package/dist/akter-program.config-C4cXx4Fr.mjs +7034 -0
- package/dist/akter.cli.mjs +5 -0
- package/dist/app-cli.config.mjs +49 -0
- package/dist/app-entry.pure.mjs +31 -0
- package/dist/archive/akter-archive.schema.mjs +65 -0
- package/dist/archive/akter-archive.service.mjs +309 -0
- package/dist/archive/archive-cli.config.mjs +45 -0
- package/dist/archive/archive-invalid.errors.mjs +5 -0
- package/dist/archive/archived-lineage.pure.mjs +13 -0
- package/dist/archive/tar.pure.mjs +291 -0
- package/dist/archive/zstd.adapter.mjs +46 -0
- package/dist/bench/bench-report.pure.mjs +120 -0
- package/dist/bench/bench-runner.pure.mjs +89 -0
- package/dist/bench/bench.service.mjs +301 -0
- package/dist/cli-runtime.layer-BqK2mmVL.mjs +1191 -0
- package/dist/cli-runtime.layer.mjs +1 -0
- package/dist/cloud-client.adapter-Cy1BjDbG.mjs +3186 -0
- package/dist/cloud-client.adapter-DOVMoYAj.mjs +304 -0
- package/dist/command/akter-commands.config.mjs +32 -0
- package/dist/command/akter-program.config.mjs +1 -0
- package/dist/credentials/credentials.service.mjs +226 -0
- package/dist/credentials/keychain.adapter.mjs +92 -0
- package/dist/credentials/login.config.mjs +251 -0
- package/dist/deploy/auth/api-attempt.service.mjs +30 -0
- package/dist/deploy/auth/token-refresh.errors.mjs +4 -0
- package/dist/deploy/build-bundle.adapter.mjs +133 -0
- package/dist/deploy/build-manifest.pure.mjs +44 -0
- package/dist/deploy/cloud-client.adapter.mjs +1 -0
- package/dist/deploy/cloud-url.pure.mjs +17 -0
- package/dist/deploy/deploy-failed.errors.mjs +17 -0
- package/dist/deploy/deploy.service.mjs +156 -0
- package/dist/deploy/request-failure.pure.mjs +87 -0
- package/dist/dev-runner.pure.mjs +30 -0
- package/dist/docs/doc-topics.pure.mjs +21 -0
- package/dist/docs/docs.config.mjs +1 -0
- package/dist/docs.config-_21Xi6HU.mjs +190 -0
- package/dist/export/actor-export.service.mjs +267 -0
- package/dist/export/export-failed.errors.mjs +4 -0
- package/dist/export/export-failure.pure.mjs +18 -0
- package/dist/export/ordered-lines.pure.mjs +43 -0
- package/dist/export/ranged-download.pure.mjs +66 -0
- package/dist/export/snapshot-download.pure.mjs +86 -0
- package/dist/history-runner.pure.mjs +186 -0
- package/dist/history-since.pure.mjs +17 -0
- package/dist/hosted-runtime.layer-Cx3IPsEd.mjs +16358 -0
- package/dist/local/environment-cli.config.mjs +90 -0
- package/dist/local/environment-runner.pure.mjs +75 -0
- package/dist/local/local-cli.config.mjs +159 -0
- package/dist/logs/log-follow.config.mjs +21 -0
- package/dist/logs/log-follow.service.mjs +87 -0
- package/dist/logs/log-lines.pure.mjs +44 -0
- package/dist/migrate-runner.pure.mjs +28 -0
- package/dist/operation-input.pure-CS9iUhqK.mjs +1383 -0
- package/dist/operation-registry.pure-DVC8EDgj.mjs +283 -0
- package/dist/registry/actor-call.service.mjs +1 -0
- package/dist/registry/actor-commands.config.mjs +127 -0
- package/dist/registry/actor-refusal.pure.mjs +34 -0
- package/dist/registry/approval.service.mjs +80 -0
- package/dist/registry/cloud-commands.config.mjs +151 -0
- package/dist/registry/cloud-served.pure.mjs +31 -0
- package/dist/registry/operation-call.service.mjs +262 -0
- package/dist/registry/operation-input.pure.mjs +1 -0
- package/dist/registry/operation-output.pure.mjs +91 -0
- package/dist/registry/served-command.config.mjs +57 -0
- package/dist/runner-exited.errors.mjs +10 -0
- package/dist/terminal/cli-exit.errors.mjs +38 -0
- package/dist/terminal/cli-failure.pure.mjs +31 -0
- package/dist/terminal/confirm.adapter.mjs +27 -0
- package/package.json +61 -3
|
@@ -0,0 +1,1394 @@
|
|
|
1
|
+
import { h as fromIterable, o as empty, st as normalize } from "./Array-B4kuTQeW.mjs";
|
|
2
|
+
import { $ as evaluate, B as args, F as PipeInspectableProto, K as causeFail, S as none, Sn as identity, bn as dual, ft as makePrimitive, gn as constTrue, k as Done, lt as isExit, mt as withFiber, nt as exitFailCause, rt as exitSucceed, tt as exitFail, w as some, yn as constant } from "./Option-DkxSnBhp.mjs";
|
|
3
|
+
import { Fn as catchDone, Gi as sync, Hi as succeed, Ji as whileLoop, Rn as isDoneCause, Wi as suspend, bi as exitZipRight, di as andThen, fi as as, mi as callback, qi as void_, vi as exitInterrupt$1, yi as exitVoid } from "./Effect-CKFpqbmw.mjs";
|
|
4
|
+
// ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/MutableList.js
|
|
5
|
+
/**
|
|
6
|
+
* Mutable lists for collecting ordered values and draining them from the front.
|
|
7
|
+
* A `MutableList<A>` can append values to the end, prepend values to the
|
|
8
|
+
* beginning, take one or more values from the front, inspect its contents as an
|
|
9
|
+
* array, filter values, remove values, and clear itself. All operations update
|
|
10
|
+
* the same list object in place and keep its `length` field current. Taking
|
|
11
|
+
* from an empty list returns the `Empty` symbol.
|
|
12
|
+
*
|
|
13
|
+
* @stability stable
|
|
14
|
+
* @since 4.0.0
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Defines the unique symbol used to represent an empty result when taking elements from a MutableList.
|
|
18
|
+
* This symbol is returned by `take` when the list is empty, allowing for safe type checking.
|
|
19
|
+
*
|
|
20
|
+
* **When to use**
|
|
21
|
+
*
|
|
22
|
+
* Use to detect that `take` returned no element before handling the result as a
|
|
23
|
+
* list item.
|
|
24
|
+
*
|
|
25
|
+
* **Example** (Checking for empty results)
|
|
26
|
+
*
|
|
27
|
+
* ```ts import.meta.vitest
|
|
28
|
+
* import { MutableList } from "effect"
|
|
29
|
+
*
|
|
30
|
+
* const list = MutableList.make<string>()
|
|
31
|
+
*
|
|
32
|
+
* MutableList.take(list) === MutableList.Empty // => true
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @stability stable
|
|
36
|
+
* @category symbols
|
|
37
|
+
* @since 4.0.0
|
|
38
|
+
*/
|
|
39
|
+
const Empty = /*#__PURE__*/ Symbol.for("effect/MutableList/Empty");
|
|
40
|
+
/**
|
|
41
|
+
* Creates an empty MutableList.
|
|
42
|
+
*
|
|
43
|
+
* **Example** (Creating an empty mutable list)
|
|
44
|
+
*
|
|
45
|
+
* ```ts import.meta.vitest
|
|
46
|
+
* import { MutableList } from "effect"
|
|
47
|
+
*
|
|
48
|
+
* const list = MutableList.make<string>()
|
|
49
|
+
*
|
|
50
|
+
* list.length // => 0
|
|
51
|
+
* MutableList.append(list, "first")
|
|
52
|
+
* MutableList.take(list) // => "first"
|
|
53
|
+
* list.length // => 0
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @stability stable
|
|
57
|
+
* @category constructors
|
|
58
|
+
* @since 2.0.0
|
|
59
|
+
*/
|
|
60
|
+
const make$1 = () => ({
|
|
61
|
+
head: void 0,
|
|
62
|
+
tail: void 0,
|
|
63
|
+
length: 0
|
|
64
|
+
});
|
|
65
|
+
const compactHead = (self) => {
|
|
66
|
+
const head = self.head;
|
|
67
|
+
if (head.offset >= 1024 && head === self.tail && head.mutable && (head.array.length - head.offset) * 8 <= head.offset) self.head = self.tail = {
|
|
68
|
+
array: head.array.slice(head.offset),
|
|
69
|
+
mutable: true,
|
|
70
|
+
offset: 0,
|
|
71
|
+
next: void 0
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
const emptyBucket = () => ({
|
|
75
|
+
array: [],
|
|
76
|
+
mutable: true,
|
|
77
|
+
offset: 0,
|
|
78
|
+
next: void 0
|
|
79
|
+
});
|
|
80
|
+
/**
|
|
81
|
+
* Appends an element to the end of the MutableList.
|
|
82
|
+
* This operation is optimized for high-frequency usage.
|
|
83
|
+
*
|
|
84
|
+
* **Example** (Appending elements)
|
|
85
|
+
*
|
|
86
|
+
* ```ts import.meta.vitest
|
|
87
|
+
* import { MutableList } from "effect"
|
|
88
|
+
*
|
|
89
|
+
* const list = MutableList.make<number>()
|
|
90
|
+
* MutableList.append(list, 1)
|
|
91
|
+
* MutableList.append(list, 2)
|
|
92
|
+
* MutableList.append(list, 3)
|
|
93
|
+
*
|
|
94
|
+
* MutableList.toArray(list) // => [1, 2, 3]
|
|
95
|
+
* list.length // => 3
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @stability stable
|
|
99
|
+
* @category mutations
|
|
100
|
+
* @since 2.0.0
|
|
101
|
+
*/
|
|
102
|
+
const append = (self, message) => {
|
|
103
|
+
if (!self.tail) self.head = self.tail = emptyBucket();
|
|
104
|
+
else if (!self.tail.mutable) {
|
|
105
|
+
self.tail.next = emptyBucket();
|
|
106
|
+
self.tail = self.tail.next;
|
|
107
|
+
}
|
|
108
|
+
self.tail.array.push(message);
|
|
109
|
+
self.length++;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Appends all elements from an iterable to the end of the MutableList.
|
|
113
|
+
* Returns the number of elements added. The elements are copied, so the input
|
|
114
|
+
* can be reused afterward. Use `appendAllUnsafe` to transfer ownership of an
|
|
115
|
+
* array instead.
|
|
116
|
+
*
|
|
117
|
+
* **Example** (Appending multiple elements)
|
|
118
|
+
*
|
|
119
|
+
* ```ts import.meta.vitest
|
|
120
|
+
* import { MutableList } from "effect"
|
|
121
|
+
*
|
|
122
|
+
* const list = MutableList.make<number>()
|
|
123
|
+
* MutableList.append(list, 1)
|
|
124
|
+
* MutableList.append(list, 2)
|
|
125
|
+
*
|
|
126
|
+
* MutableList.appendAll(list, [3, 4, 5]) // => 3
|
|
127
|
+
* MutableList.toArray(list) // => [1, 2, 3, 4, 5]
|
|
128
|
+
* list.length // => 5
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @stability stable
|
|
132
|
+
* @category mutations
|
|
133
|
+
* @since 4.0.0
|
|
134
|
+
*/
|
|
135
|
+
const appendAll = (self, messages) => appendAllUnsafe(self, Array.from(messages), true);
|
|
136
|
+
/**
|
|
137
|
+
* Appends all elements from a ReadonlyArray to the end of the MutableList.
|
|
138
|
+
* This is an optimized version that can reuse the array when mutable=true.
|
|
139
|
+
* Returns the number of elements added.
|
|
140
|
+
*
|
|
141
|
+
* **When to use**
|
|
142
|
+
*
|
|
143
|
+
* Use when appending a trusted array directly is worth the optimized path and
|
|
144
|
+
* you can transfer ownership of the input when enabling mutation.
|
|
145
|
+
*
|
|
146
|
+
* **Gotchas**
|
|
147
|
+
*
|
|
148
|
+
* When mutable=true, ownership of the input array transfers to the list. Do not
|
|
149
|
+
* read or modify the array afterward.
|
|
150
|
+
*
|
|
151
|
+
* **Example** (Transferring an array when appending)
|
|
152
|
+
*
|
|
153
|
+
* ```ts import.meta.vitest
|
|
154
|
+
* import { MutableList } from "effect"
|
|
155
|
+
*
|
|
156
|
+
* const list = MutableList.make<number>()
|
|
157
|
+
* MutableList.append(list, 1)
|
|
158
|
+
* const items = [2, 3, 4]
|
|
159
|
+
* MutableList.appendAllUnsafe(list, items, true) // => 3
|
|
160
|
+
*
|
|
161
|
+
* MutableList.toArray(list) // => [1, 2, 3, 4]
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @stability stable
|
|
165
|
+
* @category mutations
|
|
166
|
+
* @since 4.0.0
|
|
167
|
+
*/
|
|
168
|
+
const appendAllUnsafe = (self, messages, mutable = false) => {
|
|
169
|
+
if (messages.length === 0) return 0;
|
|
170
|
+
const chunk = {
|
|
171
|
+
array: messages,
|
|
172
|
+
mutable,
|
|
173
|
+
offset: 0,
|
|
174
|
+
next: void 0
|
|
175
|
+
};
|
|
176
|
+
if (self.head) self.tail = self.tail.next = chunk;
|
|
177
|
+
else self.head = self.tail = chunk;
|
|
178
|
+
self.length += messages.length;
|
|
179
|
+
return messages.length;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Removes all elements from the MutableList, resetting it to an empty state.
|
|
183
|
+
* This operation is highly optimized and releases all internal memory.
|
|
184
|
+
*
|
|
185
|
+
* **Example** (Clearing a mutable list)
|
|
186
|
+
*
|
|
187
|
+
* ```ts import.meta.vitest
|
|
188
|
+
* import { MutableList } from "effect"
|
|
189
|
+
*
|
|
190
|
+
* const list = MutableList.make<number>()
|
|
191
|
+
* MutableList.appendAll(list, [1, 2, 3, 4, 5])
|
|
192
|
+
*
|
|
193
|
+
* MutableList.clear(list)
|
|
194
|
+
*
|
|
195
|
+
* MutableList.toArray(list) // => []
|
|
196
|
+
* list.length // => 0
|
|
197
|
+
* MutableList.take(list) === MutableList.Empty // => true
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @stability stable
|
|
201
|
+
* @category mutations
|
|
202
|
+
* @since 4.0.0
|
|
203
|
+
*/
|
|
204
|
+
const clear = (self) => {
|
|
205
|
+
self.head = self.tail = void 0;
|
|
206
|
+
self.length = 0;
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Takes up to N elements from the beginning of the MutableList and returns them as an array.
|
|
210
|
+
* The taken elements are removed from the list. This operation is optimized for performance
|
|
211
|
+
* and includes zero-copy optimizations when possible.
|
|
212
|
+
*
|
|
213
|
+
* **Details**
|
|
214
|
+
*
|
|
215
|
+
* Finite fractional values of `n` are rounded down. `NaN` and non-positive
|
|
216
|
+
* values leave the list unchanged and return an empty array.
|
|
217
|
+
*
|
|
218
|
+
* **Example** (Taking batches)
|
|
219
|
+
*
|
|
220
|
+
* ```ts import.meta.vitest
|
|
221
|
+
* import { MutableList } from "effect"
|
|
222
|
+
*
|
|
223
|
+
* const list = MutableList.make<number>()
|
|
224
|
+
* MutableList.appendAll(list, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
225
|
+
*
|
|
226
|
+
* MutableList.takeN(list, 3) // => [1, 2, 3]
|
|
227
|
+
* MutableList.toArray(list) // => [4, 5, 6, 7, 8, 9, 10]
|
|
228
|
+
* list.length // => 7
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @stability stable
|
|
232
|
+
* @category mutations
|
|
233
|
+
* @since 4.0.0
|
|
234
|
+
*/
|
|
235
|
+
const takeN = (self, n) => {
|
|
236
|
+
n = normalize(n);
|
|
237
|
+
if (n <= 0 || !self.head) return [];
|
|
238
|
+
n = Math.min(n, self.length);
|
|
239
|
+
if (n === self.length && self.head?.offset === 0 && !self.head.next) {
|
|
240
|
+
const array = self.head.array;
|
|
241
|
+
clear(self);
|
|
242
|
+
return array;
|
|
243
|
+
}
|
|
244
|
+
const array = new Array(n);
|
|
245
|
+
let index = 0;
|
|
246
|
+
let chunk = self.head;
|
|
247
|
+
while (chunk) {
|
|
248
|
+
while (chunk.offset < chunk.array.length) {
|
|
249
|
+
array[index++] = chunk.array[chunk.offset];
|
|
250
|
+
if (chunk.mutable) chunk.array[chunk.offset] = void 0;
|
|
251
|
+
chunk.offset++;
|
|
252
|
+
if (index === n) {
|
|
253
|
+
self.head = chunk.offset === chunk.array.length && chunk.next ? chunk.next : chunk;
|
|
254
|
+
self.length -= n;
|
|
255
|
+
if (self.length === 0) clear(self);
|
|
256
|
+
else compactHead(self);
|
|
257
|
+
return array;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
chunk = chunk.next;
|
|
261
|
+
}
|
|
262
|
+
clear(self);
|
|
263
|
+
return array;
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Takes a single element from the beginning of the MutableList.
|
|
267
|
+
* Returns the element if available, or the Empty symbol if the list is empty.
|
|
268
|
+
* The taken element is removed from the list.
|
|
269
|
+
*
|
|
270
|
+
* **Example** (Taking one element)
|
|
271
|
+
*
|
|
272
|
+
* ```ts import.meta.vitest
|
|
273
|
+
* import { MutableList } from "effect"
|
|
274
|
+
*
|
|
275
|
+
* const list = MutableList.make<string>()
|
|
276
|
+
* MutableList.appendAll(list, ["first", "second", "third"])
|
|
277
|
+
*
|
|
278
|
+
* MutableList.take(list) // => "first"
|
|
279
|
+
* MutableList.toArray(list) // => ["second", "third"]
|
|
280
|
+
* list.length // => 2
|
|
281
|
+
* ```
|
|
282
|
+
*
|
|
283
|
+
* @stability stable
|
|
284
|
+
* @category mutations
|
|
285
|
+
* @since 4.0.0
|
|
286
|
+
*/
|
|
287
|
+
const take$1 = (self) => {
|
|
288
|
+
if (!self.head) return Empty;
|
|
289
|
+
const message = self.head.array[self.head.offset];
|
|
290
|
+
if (self.head.mutable) self.head.array[self.head.offset] = void 0;
|
|
291
|
+
self.head.offset++;
|
|
292
|
+
self.length--;
|
|
293
|
+
if (self.head.offset === self.head.array.length) {
|
|
294
|
+
if (self.head.next) self.head = self.head.next;
|
|
295
|
+
else clear(self);
|
|
296
|
+
} else compactHead(self);
|
|
297
|
+
return message;
|
|
298
|
+
};
|
|
299
|
+
// ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/Queue.js
|
|
300
|
+
/**
|
|
301
|
+
* Passes values asynchronously between fibers.
|
|
302
|
+
*
|
|
303
|
+
* A `Queue<A, E>` accepts values, hands each value to one consumer in offer
|
|
304
|
+
* order, and can complete, fail, interrupt, or shut down. Queues can be bounded
|
|
305
|
+
* or unbounded, and bounded queues can suspend, drop, or slide values when
|
|
306
|
+
* producers are faster than consumers.
|
|
307
|
+
*
|
|
308
|
+
* @stability stable
|
|
309
|
+
* @since 3.8.0
|
|
310
|
+
*/
|
|
311
|
+
const TypeId = "~effect/Queue";
|
|
312
|
+
const EnqueueTypeId = "~effect/Queue/Enqueue";
|
|
313
|
+
const DequeueTypeId = "~effect/Queue/Dequeue";
|
|
314
|
+
const variance = {
|
|
315
|
+
_A: identity,
|
|
316
|
+
_E: identity
|
|
317
|
+
};
|
|
318
|
+
const QueueProto = {
|
|
319
|
+
[TypeId]: variance,
|
|
320
|
+
[EnqueueTypeId]: variance,
|
|
321
|
+
[DequeueTypeId]: variance,
|
|
322
|
+
...PipeInspectableProto,
|
|
323
|
+
toJSON() {
|
|
324
|
+
return {
|
|
325
|
+
_id: "effect/Queue",
|
|
326
|
+
state: this.state._tag,
|
|
327
|
+
size: sizeUnsafe(this)
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Creates a `Queue` with optional capacity and overflow strategy.
|
|
333
|
+
*
|
|
334
|
+
* **Details**
|
|
335
|
+
*
|
|
336
|
+
* By default the queue is unbounded and uses the `"suspend"` strategy. Provide
|
|
337
|
+
* `capacity` for a bounded queue and choose `"suspend"`, `"dropping"`, or
|
|
338
|
+
* `"sliding"` to control what happens when the queue is full. The returned
|
|
339
|
+
* queue can be offered to, taken from, failed, ended, interrupted, or shut down.
|
|
340
|
+
*
|
|
341
|
+
* **Example** (Creating queues)
|
|
342
|
+
*
|
|
343
|
+
* ```ts import.meta.vitest
|
|
344
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
345
|
+
*
|
|
346
|
+
* const program = Effect.gen(function*() {
|
|
347
|
+
* const queue = yield* Queue.make<number, string | Cause.Done>()
|
|
348
|
+
*
|
|
349
|
+
* // add messages to the queue
|
|
350
|
+
* yield* Queue.offer(queue, 1)
|
|
351
|
+
* yield* Queue.offer(queue, 2)
|
|
352
|
+
* yield* Queue.offerAll(queue, [3, 4, 5])
|
|
353
|
+
*
|
|
354
|
+
* // take messages from the queue
|
|
355
|
+
* const messages = yield* Queue.takeAll(queue)
|
|
356
|
+
*
|
|
357
|
+
* // signal that the queue is done
|
|
358
|
+
* yield* Queue.end(queue)
|
|
359
|
+
* const done = yield* Effect.flip(Queue.take(queue))
|
|
360
|
+
*
|
|
361
|
+
* // signal that another queue has failed
|
|
362
|
+
* const failedQueue = yield* Queue.make<number, string>()
|
|
363
|
+
* const failed = yield* Queue.fail(failedQueue, "boom")
|
|
364
|
+
* return { messages, done, failed }
|
|
365
|
+
* })
|
|
366
|
+
*
|
|
367
|
+
* await Effect.runPromise(program) // => { messages: [1, 2, 3, 4, 5], done: Cause.Done(), failed: true }
|
|
368
|
+
* ```
|
|
369
|
+
*
|
|
370
|
+
* @stability stable
|
|
371
|
+
* @category constructors
|
|
372
|
+
* @since 4.0.0
|
|
373
|
+
*/
|
|
374
|
+
const make = (options) => withFiber((fiber) => {
|
|
375
|
+
const self = Object.create(QueueProto);
|
|
376
|
+
self.dispatcher = fiber.currentDispatcher;
|
|
377
|
+
self.capacity = options?.capacity ?? Number.POSITIVE_INFINITY;
|
|
378
|
+
self.strategy = options?.strategy ?? "suspend";
|
|
379
|
+
self.messages = make$1();
|
|
380
|
+
self.scheduleRunning = false;
|
|
381
|
+
self.state = {
|
|
382
|
+
_tag: "Open",
|
|
383
|
+
takers: /* @__PURE__ */ new Set(),
|
|
384
|
+
offers: /* @__PURE__ */ new Set(),
|
|
385
|
+
awaiters: /* @__PURE__ */ new Set()
|
|
386
|
+
};
|
|
387
|
+
return succeed(self);
|
|
388
|
+
});
|
|
389
|
+
/**
|
|
390
|
+
* Creates a bounded queue with the specified capacity that uses backpressure strategy.
|
|
391
|
+
*
|
|
392
|
+
* **Details**
|
|
393
|
+
*
|
|
394
|
+
* When the queue reaches capacity, producers will be suspended until space becomes available.
|
|
395
|
+
* This ensures all messages are processed but may slow down producers.
|
|
396
|
+
*
|
|
397
|
+
* **Example** (Creating bounded queues)
|
|
398
|
+
*
|
|
399
|
+
* ```ts import.meta.vitest
|
|
400
|
+
* import { Effect, Queue } from "effect"
|
|
401
|
+
*
|
|
402
|
+
* const program = Effect.gen(function*() {
|
|
403
|
+
* const queue = yield* Queue.bounded<string>(5)
|
|
404
|
+
*
|
|
405
|
+
* // This will succeed as queue has capacity
|
|
406
|
+
* yield* Queue.offer(queue, "first")
|
|
407
|
+
* yield* Queue.offer(queue, "second")
|
|
408
|
+
*
|
|
409
|
+
* const size = yield* Queue.size(queue)
|
|
410
|
+
* return size
|
|
411
|
+
* })
|
|
412
|
+
*
|
|
413
|
+
* await Effect.runPromise(program) // => 2
|
|
414
|
+
* ```
|
|
415
|
+
*
|
|
416
|
+
* @stability stable
|
|
417
|
+
* @category constructors
|
|
418
|
+
* @since 2.0.0
|
|
419
|
+
*/
|
|
420
|
+
const bounded = (capacity) => make({ capacity });
|
|
421
|
+
/**
|
|
422
|
+
* Creates a bounded queue with sliding strategy. When the queue reaches capacity,
|
|
423
|
+
* new elements are added and the oldest elements are dropped.
|
|
424
|
+
*
|
|
425
|
+
* **When to use**
|
|
426
|
+
*
|
|
427
|
+
* Use when you need producer offers not to block and can accept dropping the
|
|
428
|
+
* oldest messages, such as when maintaining a rolling window of recent values.
|
|
429
|
+
*
|
|
430
|
+
* **Example** (Creating sliding queues)
|
|
431
|
+
*
|
|
432
|
+
* ```ts import.meta.vitest
|
|
433
|
+
* import { Effect, Queue } from "effect"
|
|
434
|
+
*
|
|
435
|
+
* const program = Effect.gen(function*() {
|
|
436
|
+
* const queue = yield* Queue.sliding<number>(3)
|
|
437
|
+
*
|
|
438
|
+
* // Fill the queue to capacity
|
|
439
|
+
* yield* Queue.offer(queue, 1)
|
|
440
|
+
* yield* Queue.offer(queue, 2)
|
|
441
|
+
* yield* Queue.offer(queue, 3)
|
|
442
|
+
*
|
|
443
|
+
* // This will succeed, dropping the oldest element (1)
|
|
444
|
+
* yield* Queue.offer(queue, 4)
|
|
445
|
+
*
|
|
446
|
+
* const all = yield* Queue.takeAll(queue)
|
|
447
|
+
* return all
|
|
448
|
+
* })
|
|
449
|
+
*
|
|
450
|
+
* await Effect.runPromise(program) // => [2, 3, 4]
|
|
451
|
+
* ```
|
|
452
|
+
*
|
|
453
|
+
* @stability stable
|
|
454
|
+
* @category constructors
|
|
455
|
+
* @since 2.0.0
|
|
456
|
+
*/
|
|
457
|
+
const sliding = (capacity) => make({
|
|
458
|
+
capacity,
|
|
459
|
+
strategy: "sliding"
|
|
460
|
+
});
|
|
461
|
+
/**
|
|
462
|
+
* Creates an unbounded queue that can grow to any size without blocking producers.
|
|
463
|
+
*
|
|
464
|
+
* **When to use**
|
|
465
|
+
*
|
|
466
|
+
* Use when you need producers to add messages without backpressure and accept
|
|
467
|
+
* unbounded memory growth.
|
|
468
|
+
*
|
|
469
|
+
* **Example** (Creating unbounded queues)
|
|
470
|
+
*
|
|
471
|
+
* ```ts import.meta.vitest
|
|
472
|
+
* import { Effect, Queue } from "effect"
|
|
473
|
+
*
|
|
474
|
+
* const program = Effect.gen(function*() {
|
|
475
|
+
* const queue = yield* Queue.unbounded<string>()
|
|
476
|
+
*
|
|
477
|
+
* // Producers can always add messages without blocking
|
|
478
|
+
* yield* Queue.offer(queue, "message1")
|
|
479
|
+
* yield* Queue.offer(queue, "message2")
|
|
480
|
+
* yield* Queue.offerAll(queue, ["message3", "message4", "message5"])
|
|
481
|
+
*
|
|
482
|
+
* // Check current size
|
|
483
|
+
* const size = yield* Queue.size(queue)
|
|
484
|
+
*
|
|
485
|
+
* // Take all messages
|
|
486
|
+
* const messages = yield* Queue.takeAll(queue)
|
|
487
|
+
* return { size, messages }
|
|
488
|
+
* })
|
|
489
|
+
*
|
|
490
|
+
* await Effect.runPromise(program) // => { size: 5, messages: ["message1", "message2", "message3", "message4", "message5"] }
|
|
491
|
+
* ```
|
|
492
|
+
*
|
|
493
|
+
* @stability stable
|
|
494
|
+
* @category constructors
|
|
495
|
+
* @since 2.0.0
|
|
496
|
+
*/
|
|
497
|
+
const unbounded = () => make();
|
|
498
|
+
/**
|
|
499
|
+
* Adds a message to the queue. Returns `false` if the queue is done.
|
|
500
|
+
*
|
|
501
|
+
* **Details**
|
|
502
|
+
*
|
|
503
|
+
* For bounded queues, this operation may suspend if the queue is at capacity,
|
|
504
|
+
* depending on the backpressure strategy. For dropping/sliding queues, it may
|
|
505
|
+
* return false or succeed immediately by dropping/sliding existing messages.
|
|
506
|
+
*
|
|
507
|
+
* **Example** (Offering a value)
|
|
508
|
+
*
|
|
509
|
+
* ```ts import.meta.vitest
|
|
510
|
+
* import { Effect, Queue } from "effect"
|
|
511
|
+
*
|
|
512
|
+
* const program = Effect.gen(function*() {
|
|
513
|
+
* const queue = yield* Queue.bounded<number>(3)
|
|
514
|
+
*
|
|
515
|
+
* // Successfully add messages to queue
|
|
516
|
+
* const success1 = yield* Queue.offer(queue, 1)
|
|
517
|
+
* const success2 = yield* Queue.offer(queue, 2)
|
|
518
|
+
*
|
|
519
|
+
* // Queue state
|
|
520
|
+
* const size = yield* Queue.size(queue)
|
|
521
|
+
* return { offered: [success1, success2], size }
|
|
522
|
+
* })
|
|
523
|
+
*
|
|
524
|
+
* await Effect.runPromise(program) // => { offered: [true, true], size: 2 }
|
|
525
|
+
* ```
|
|
526
|
+
*
|
|
527
|
+
* @stability stable
|
|
528
|
+
* @category offering
|
|
529
|
+
* @since 2.0.0
|
|
530
|
+
*/
|
|
531
|
+
const offer = /*#__PURE__*/ dual(2, (self, message) => suspend(() => offerUnsafe(self, message) ? exitTrue : self.state._tag === "Open" && self.strategy === "suspend" ? offerOrWait(self, message) : exitFalse));
|
|
532
|
+
/**
|
|
533
|
+
* Adds a message to the queue synchronously. Returns `false` without adding the
|
|
534
|
+
* message if the queue is closing or done, or if it is full with a non-sliding
|
|
535
|
+
* strategy (`"suspend"` or `"dropping"`). A queue with non-positive capacity can
|
|
536
|
+
* still accept a message when a taker is waiting.
|
|
537
|
+
*
|
|
538
|
+
* **When to use**
|
|
539
|
+
*
|
|
540
|
+
* Use when you are already in synchronous queue internals or a performance
|
|
541
|
+
* boundary where wrapping the mutation in `Effect` is intentionally avoided.
|
|
542
|
+
*
|
|
543
|
+
* **Gotchas**
|
|
544
|
+
*
|
|
545
|
+
* This is an unsafe operation that directly modifies the queue without Effect wrapping.
|
|
546
|
+
* Use this only when you're certain about the synchronous nature of the operation.
|
|
547
|
+
*
|
|
548
|
+
* **Example** (Offering a value synchronously)
|
|
549
|
+
*
|
|
550
|
+
* ```ts import.meta.vitest
|
|
551
|
+
* import { Effect, Queue } from "effect"
|
|
552
|
+
*
|
|
553
|
+
* // Create a queue effect and extract the queue for unsafe operations
|
|
554
|
+
* const program = Effect.gen(function*() {
|
|
555
|
+
* const queue = yield* Queue.bounded<number>(3)
|
|
556
|
+
*
|
|
557
|
+
* // Add messages synchronously using unsafe API
|
|
558
|
+
* const success1 = Queue.offerUnsafe(queue, 1)
|
|
559
|
+
* const success2 = Queue.offerUnsafe(queue, 2)
|
|
560
|
+
*
|
|
561
|
+
* // Check current size
|
|
562
|
+
* const size = Queue.sizeUnsafe(queue)
|
|
563
|
+
* return { offered: [success1, success2], size }
|
|
564
|
+
* })
|
|
565
|
+
*
|
|
566
|
+
* await Effect.runPromise(program) // => { offered: [true, true], size: 2 }
|
|
567
|
+
* ```
|
|
568
|
+
*
|
|
569
|
+
* @stability stable
|
|
570
|
+
* @category offering
|
|
571
|
+
* @since 4.0.0
|
|
572
|
+
*/
|
|
573
|
+
const offerUnsafe = (self, message) => {
|
|
574
|
+
if (self.state._tag !== "Open") return false;
|
|
575
|
+
else if (self.messages.length >= self.capacity) {
|
|
576
|
+
if (self.strategy === "sliding") {
|
|
577
|
+
take$1(self.messages);
|
|
578
|
+
append(self.messages, message);
|
|
579
|
+
return true;
|
|
580
|
+
} else if (self.capacity <= 0 && self.state.takers.size > 0) {
|
|
581
|
+
append(self.messages, message);
|
|
582
|
+
releaseTakers(self);
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
append(self.messages, message);
|
|
588
|
+
scheduleReleaseTaker(self);
|
|
589
|
+
return true;
|
|
590
|
+
};
|
|
591
|
+
/**
|
|
592
|
+
* Adds multiple messages to the queue. Returns the remaining messages that
|
|
593
|
+
* were not added.
|
|
594
|
+
*
|
|
595
|
+
* **When to use**
|
|
596
|
+
*
|
|
597
|
+
* Use when producers can submit a batch at once and need to know which messages
|
|
598
|
+
* did not fit under the queue's capacity strategy.
|
|
599
|
+
*
|
|
600
|
+
* **Details**
|
|
601
|
+
*
|
|
602
|
+
* For bounded queues, this operation may suspend if the queue doesn't have
|
|
603
|
+
* enough capacity. The operation returns an array of messages that couldn't
|
|
604
|
+
* be added (empty array means all messages were successfully added).
|
|
605
|
+
*
|
|
606
|
+
* **Example** (Offering multiple values)
|
|
607
|
+
*
|
|
608
|
+
* ```ts import.meta.vitest
|
|
609
|
+
* import { Effect, Queue } from "effect"
|
|
610
|
+
*
|
|
611
|
+
* const program = Effect.gen(function*() {
|
|
612
|
+
* const queue = yield* Queue.dropping<number>(3)
|
|
613
|
+
*
|
|
614
|
+
* // Try to add more messages than capacity without suspending
|
|
615
|
+
* const remaining1 = yield* Queue.offerAll(queue, [1, 2, 3, 4, 5])
|
|
616
|
+
* return remaining1
|
|
617
|
+
* })
|
|
618
|
+
*
|
|
619
|
+
* await Effect.runPromise(program) // => [4, 5]
|
|
620
|
+
* ```
|
|
621
|
+
*
|
|
622
|
+
* @stability stable
|
|
623
|
+
* @category offering
|
|
624
|
+
* @since 2.0.0
|
|
625
|
+
*/
|
|
626
|
+
const offerAll = /*#__PURE__*/ dual(2, (self, messages) => callback((resume) => {
|
|
627
|
+
const remaining = offerAllUnsafe(self, messages);
|
|
628
|
+
if (remaining.length === 0 || self.strategy === "dropping") return resume(exitSucceed(remaining));
|
|
629
|
+
return waitToOffer(self, {
|
|
630
|
+
_tag: "Array",
|
|
631
|
+
remaining,
|
|
632
|
+
offset: 0,
|
|
633
|
+
resume
|
|
634
|
+
});
|
|
635
|
+
}));
|
|
636
|
+
/**
|
|
637
|
+
* Adds multiple messages to the queue synchronously. Returns the remaining messages that
|
|
638
|
+
* were not added.
|
|
639
|
+
*
|
|
640
|
+
* **When to use**
|
|
641
|
+
*
|
|
642
|
+
* Use when queue internals or a performance boundary need a synchronous batch
|
|
643
|
+
* offer and can handle any messages that do not fit.
|
|
644
|
+
*
|
|
645
|
+
* **Gotchas**
|
|
646
|
+
*
|
|
647
|
+
* This is an unsafe operation that directly modifies the queue without Effect wrapping.
|
|
648
|
+
*
|
|
649
|
+
* **Example** (Offering multiple values synchronously)
|
|
650
|
+
*
|
|
651
|
+
* ```ts import.meta.vitest
|
|
652
|
+
* import { Effect, Queue } from "effect"
|
|
653
|
+
*
|
|
654
|
+
* // Create a bounded queue and use unsafe API
|
|
655
|
+
* const program = Effect.gen(function*() {
|
|
656
|
+
* const queue = yield* Queue.bounded<number>(3)
|
|
657
|
+
*
|
|
658
|
+
* // Try to add 5 messages to capacity-3 queue using unsafe API
|
|
659
|
+
* const remaining = Queue.offerAllUnsafe(queue, [1, 2, 3, 4, 5])
|
|
660
|
+
*
|
|
661
|
+
* // Check what's in the queue
|
|
662
|
+
* const size = Queue.sizeUnsafe(queue)
|
|
663
|
+
* return { remaining, size }
|
|
664
|
+
* })
|
|
665
|
+
*
|
|
666
|
+
* await Effect.runPromise(program) // => { remaining: [4, 5], size: 3 }
|
|
667
|
+
* ```
|
|
668
|
+
*
|
|
669
|
+
* @stability stable
|
|
670
|
+
* @category offering
|
|
671
|
+
* @since 4.0.0
|
|
672
|
+
*/
|
|
673
|
+
const offerAllUnsafe = (self, messages) => {
|
|
674
|
+
if (self.state._tag !== "Open") return fromIterable(messages);
|
|
675
|
+
else if (self.capacity === Number.POSITIVE_INFINITY || self.strategy === "sliding") {
|
|
676
|
+
appendAll(self.messages, messages);
|
|
677
|
+
if (self.strategy === "sliding") takeN(self.messages, self.messages.length - self.capacity);
|
|
678
|
+
scheduleReleaseTaker(self);
|
|
679
|
+
return [];
|
|
680
|
+
}
|
|
681
|
+
const free = self.capacity <= 0 ? self.state.takers.size : self.capacity - self.messages.length;
|
|
682
|
+
if (free === 0) return fromIterable(messages);
|
|
683
|
+
const remaining = [];
|
|
684
|
+
let i = 0;
|
|
685
|
+
for (const message of messages) {
|
|
686
|
+
if (i < free) append(self.messages, message);
|
|
687
|
+
else remaining.push(message);
|
|
688
|
+
i++;
|
|
689
|
+
}
|
|
690
|
+
scheduleReleaseTaker(self);
|
|
691
|
+
return remaining;
|
|
692
|
+
};
|
|
693
|
+
/**
|
|
694
|
+
* Fails the queue with an error. If the queue is already done, `false` is
|
|
695
|
+
* returned.
|
|
696
|
+
*
|
|
697
|
+
* **Example** (Failing queues with an error)
|
|
698
|
+
*
|
|
699
|
+
* ```ts import.meta.vitest
|
|
700
|
+
* import { Effect, Exit, Queue } from "effect"
|
|
701
|
+
*
|
|
702
|
+
* const program = Effect.gen(function*() {
|
|
703
|
+
* const queue = yield* Queue.bounded<number, string>(10)
|
|
704
|
+
*
|
|
705
|
+
* // Fail the queue with an error
|
|
706
|
+
* const failed = yield* Queue.fail(queue, "Something went wrong")
|
|
707
|
+
*
|
|
708
|
+
* // Taking from the failed queue fails with the error
|
|
709
|
+
* const exit = yield* Effect.exit(Queue.take(queue))
|
|
710
|
+
* return [failed, exit]
|
|
711
|
+
* })
|
|
712
|
+
*
|
|
713
|
+
* await Effect.runPromise(program) // => [true, Exit.fail("Something went wrong")]
|
|
714
|
+
* ```
|
|
715
|
+
*
|
|
716
|
+
* @stability stable
|
|
717
|
+
* @category completion
|
|
718
|
+
* @since 4.0.0
|
|
719
|
+
*/
|
|
720
|
+
const fail = /*#__PURE__*/ dual(2, (self, error) => failCause(self, causeFail(error)));
|
|
721
|
+
/**
|
|
722
|
+
* Fails the queue with a cause. If the queue is already done, `false` is
|
|
723
|
+
* returned.
|
|
724
|
+
*
|
|
725
|
+
* **Example** (Failing queues with a cause)
|
|
726
|
+
*
|
|
727
|
+
* ```ts import.meta.vitest
|
|
728
|
+
* import { Cause, Effect, Exit, Queue } from "effect"
|
|
729
|
+
*
|
|
730
|
+
* const program = Effect.gen(function*() {
|
|
731
|
+
* const queue = yield* Queue.bounded<number, string>(10)
|
|
732
|
+
*
|
|
733
|
+
* // Create a cause and fail the queue
|
|
734
|
+
* const cause = Cause.fail("Queue processing failed")
|
|
735
|
+
* const failed = yield* Queue.failCause(queue, cause)
|
|
736
|
+
*
|
|
737
|
+
* // The queue is now done with the specified failure cause
|
|
738
|
+
* const exit = yield* Effect.exit(Queue.take(queue))
|
|
739
|
+
* return [failed, exit]
|
|
740
|
+
* })
|
|
741
|
+
*
|
|
742
|
+
* await Effect.runPromise(program) // => [true, Exit.failCause(Cause.fail("Queue processing failed"))]
|
|
743
|
+
* ```
|
|
744
|
+
*
|
|
745
|
+
* @stability stable
|
|
746
|
+
* @category completion
|
|
747
|
+
* @since 4.0.0
|
|
748
|
+
*/
|
|
749
|
+
const failCause = /*#__PURE__*/ dual(2, (self, cause) => sync(() => failCauseUnsafe(self, cause)));
|
|
750
|
+
/**
|
|
751
|
+
* Fails the queue with a cause synchronously. If the queue is already done, `false` is
|
|
752
|
+
* returned.
|
|
753
|
+
*
|
|
754
|
+
* **When to use**
|
|
755
|
+
*
|
|
756
|
+
* Use when queue completion must be driven from synchronous internals while
|
|
757
|
+
* preserving the full failure `Cause`.
|
|
758
|
+
*
|
|
759
|
+
* **Gotchas**
|
|
760
|
+
*
|
|
761
|
+
* This is an unsafe operation that directly modifies the queue without Effect wrapping.
|
|
762
|
+
*
|
|
763
|
+
* **Example** (Failing queues with a cause synchronously)
|
|
764
|
+
*
|
|
765
|
+
* ```ts import.meta.vitest
|
|
766
|
+
* import { Cause, Effect, Exit, Queue } from "effect"
|
|
767
|
+
*
|
|
768
|
+
* const program = Effect.gen(function*() {
|
|
769
|
+
* const queue = yield* Queue.bounded<number, string>(10)
|
|
770
|
+
*
|
|
771
|
+
* // Create a cause and fail the queue synchronously
|
|
772
|
+
* const cause = Cause.fail("Processing error")
|
|
773
|
+
* const failed = Queue.failCauseUnsafe(queue, cause)
|
|
774
|
+
*
|
|
775
|
+
* // The queue is now done with the specified failure cause
|
|
776
|
+
* const exit = Queue.takeUnsafe(queue)
|
|
777
|
+
* return [failed, exit]
|
|
778
|
+
* })
|
|
779
|
+
*
|
|
780
|
+
* await Effect.runPromise(program) // => [true, Exit.failCause(Cause.fail("Processing error"))]
|
|
781
|
+
* ```
|
|
782
|
+
*
|
|
783
|
+
* @stability stable
|
|
784
|
+
* @category completion
|
|
785
|
+
* @since 4.0.0
|
|
786
|
+
*/
|
|
787
|
+
const failCauseUnsafe = (self, cause) => {
|
|
788
|
+
if (self.state._tag !== "Open") return false;
|
|
789
|
+
const exit = exitFailCause(cause);
|
|
790
|
+
const fail = exitZipRight(exit, exitFailDone);
|
|
791
|
+
if (self.state.offers.size === 0 && self.messages.length === 0) {
|
|
792
|
+
finalize(self, fail);
|
|
793
|
+
return true;
|
|
794
|
+
}
|
|
795
|
+
self.state = {
|
|
796
|
+
...self.state,
|
|
797
|
+
_tag: "Closing",
|
|
798
|
+
exit: fail
|
|
799
|
+
};
|
|
800
|
+
scheduleReleaseTaker(self);
|
|
801
|
+
return true;
|
|
802
|
+
};
|
|
803
|
+
/**
|
|
804
|
+
* Signals queue completion.
|
|
805
|
+
*
|
|
806
|
+
* **When to use**
|
|
807
|
+
*
|
|
808
|
+
* Use to stop accepting new offers while allowing already queued messages to be
|
|
809
|
+
* consumed.
|
|
810
|
+
*
|
|
811
|
+
* **Details**
|
|
812
|
+
*
|
|
813
|
+
* Returns `false` if the queue is already done.
|
|
814
|
+
*
|
|
815
|
+
* **Example** (Ending queues)
|
|
816
|
+
*
|
|
817
|
+
* ```ts import.meta.vitest
|
|
818
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
819
|
+
*
|
|
820
|
+
* const program = Effect.gen(function*() {
|
|
821
|
+
* const queue = yield* Queue.bounded<number, Cause.Done>(10)
|
|
822
|
+
*
|
|
823
|
+
* // Add some messages
|
|
824
|
+
* yield* Queue.offer(queue, 1)
|
|
825
|
+
* yield* Queue.offer(queue, 2)
|
|
826
|
+
*
|
|
827
|
+
* // Signal completion - no more messages will be accepted
|
|
828
|
+
* const ended = yield* Queue.end(queue)
|
|
829
|
+
*
|
|
830
|
+
* // Trying to offer more messages will return false
|
|
831
|
+
* const offerResult = yield* Queue.offer(queue, 3)
|
|
832
|
+
*
|
|
833
|
+
* // But we can still take existing messages
|
|
834
|
+
* const message = yield* Queue.take(queue)
|
|
835
|
+
* return [ended, offerResult, message]
|
|
836
|
+
* })
|
|
837
|
+
*
|
|
838
|
+
* await Effect.runPromise(program) // => [true, false, 1]
|
|
839
|
+
* ```
|
|
840
|
+
*
|
|
841
|
+
* @stability stable
|
|
842
|
+
* @category completion
|
|
843
|
+
* @since 4.0.0
|
|
844
|
+
*/
|
|
845
|
+
const end = (self) => failCause(self, causeFail(Done()));
|
|
846
|
+
/**
|
|
847
|
+
* Signals queue completion synchronously.
|
|
848
|
+
*
|
|
849
|
+
* **When to use**
|
|
850
|
+
*
|
|
851
|
+
* Use when implementing low-level queue integrations that must complete a queue
|
|
852
|
+
* without wrapping the operation in `Effect`.
|
|
853
|
+
*
|
|
854
|
+
* **Details**
|
|
855
|
+
*
|
|
856
|
+
* Returns `false` if the queue is already done.
|
|
857
|
+
*
|
|
858
|
+
* **Gotchas**
|
|
859
|
+
*
|
|
860
|
+
* This is an unsafe operation that directly modifies the queue without Effect wrapping.
|
|
861
|
+
*
|
|
862
|
+
* **Example** (Ending queues synchronously)
|
|
863
|
+
*
|
|
864
|
+
* ```ts import.meta.vitest
|
|
865
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
866
|
+
*
|
|
867
|
+
* // Create a queue and use unsafe operations
|
|
868
|
+
* const program = Effect.gen(function*() {
|
|
869
|
+
* const queue = yield* Queue.bounded<number, Cause.Done>(10)
|
|
870
|
+
*
|
|
871
|
+
* // Add some messages
|
|
872
|
+
* Queue.offerUnsafe(queue, 1)
|
|
873
|
+
* Queue.offerUnsafe(queue, 2)
|
|
874
|
+
*
|
|
875
|
+
* // End the queue synchronously
|
|
876
|
+
* const ended = Queue.endUnsafe(queue)
|
|
877
|
+
*
|
|
878
|
+
* // Existing messages can still be consumed while the queue is closing
|
|
879
|
+
* const states = [queue.state._tag]
|
|
880
|
+
*
|
|
881
|
+
* Queue.takeUnsafe(queue)
|
|
882
|
+
* Queue.takeUnsafe(queue)
|
|
883
|
+
*
|
|
884
|
+
* // After buffered messages are consumed, the queue is done
|
|
885
|
+
* states.push(queue.state._tag)
|
|
886
|
+
* return { ended, states }
|
|
887
|
+
* })
|
|
888
|
+
*
|
|
889
|
+
* await Effect.runPromise(program) // => { ended: true, states: ["Closing", "Done"] }
|
|
890
|
+
* ```
|
|
891
|
+
*
|
|
892
|
+
* @stability stable
|
|
893
|
+
* @category completion
|
|
894
|
+
* @since 4.0.0
|
|
895
|
+
*/
|
|
896
|
+
const endUnsafe = (self) => failCauseUnsafe(self, causeFail(Done()));
|
|
897
|
+
/**
|
|
898
|
+
* Shuts down the queue immediately, discarding buffered messages and resuming
|
|
899
|
+
* pending operations.
|
|
900
|
+
*
|
|
901
|
+
* **Details**
|
|
902
|
+
*
|
|
903
|
+
* Returns `true` when the queue is shut down by this call, or `false` when it
|
|
904
|
+
* has already been shut down or completed.
|
|
905
|
+
*
|
|
906
|
+
* **Example** (Shutting down queues)
|
|
907
|
+
*
|
|
908
|
+
* ```ts import.meta.vitest
|
|
909
|
+
* import { Effect, Queue } from "effect"
|
|
910
|
+
*
|
|
911
|
+
* const program = Effect.gen(function*() {
|
|
912
|
+
* const queue = yield* Queue.bounded<number>(2)
|
|
913
|
+
*
|
|
914
|
+
* // Add messages
|
|
915
|
+
* yield* Queue.offer(queue, 1)
|
|
916
|
+
* yield* Queue.offer(queue, 2)
|
|
917
|
+
*
|
|
918
|
+
* // Shutdown clears buffered messages and prevents further offers
|
|
919
|
+
* const wasShutdown = yield* Queue.shutdown(queue)
|
|
920
|
+
*
|
|
921
|
+
* // Queue is now done and cleared
|
|
922
|
+
* const size = yield* Queue.size(queue)
|
|
923
|
+
* return { wasShutdown, size }
|
|
924
|
+
* })
|
|
925
|
+
*
|
|
926
|
+
* await Effect.runPromise(program) // => { wasShutdown: true, size: 0 }
|
|
927
|
+
* ```
|
|
928
|
+
*
|
|
929
|
+
* @see {@link shutdownUnsafe} for synchronous shutdown
|
|
930
|
+
* @stability stable
|
|
931
|
+
* @category completion
|
|
932
|
+
* @since 2.0.0
|
|
933
|
+
*/
|
|
934
|
+
const shutdown = (self) => sync(() => shutdownUnsafe(self));
|
|
935
|
+
/**
|
|
936
|
+
* Shuts down the queue synchronously, discarding buffered messages and resuming
|
|
937
|
+
* pending operations.
|
|
938
|
+
*
|
|
939
|
+
* **When to use**
|
|
940
|
+
*
|
|
941
|
+
* Use when a synchronous callback must discard buffered messages and settle
|
|
942
|
+
* pending queue operations before returning.
|
|
943
|
+
*
|
|
944
|
+
* **Details**
|
|
945
|
+
*
|
|
946
|
+
* An open queue completes with an interruption. A queue already closing retains
|
|
947
|
+
* its completion cause. Call `failCauseUnsafe` first to shut down with a specific
|
|
948
|
+
* failure. Returns `true` when the queue is shut down by this call, or `false`
|
|
949
|
+
* when it has already been shut down or completed.
|
|
950
|
+
*
|
|
951
|
+
* @see {@link shutdown} for the effectful variant
|
|
952
|
+
* @see {@link failCauseUnsafe} to set a failure before discarding buffered messages
|
|
953
|
+
* @stability stable
|
|
954
|
+
* @category completion
|
|
955
|
+
* @since 4.0.0
|
|
956
|
+
*/
|
|
957
|
+
const shutdownUnsafe = (self) => {
|
|
958
|
+
if (self.state._tag === "Done") return false;
|
|
959
|
+
clear(self.messages);
|
|
960
|
+
const offers = self.state.offers;
|
|
961
|
+
finalize(self, self.state._tag === "Open" ? exitInterrupt : self.state.exit);
|
|
962
|
+
for (const entry of offers) resumeUnoffered(entry);
|
|
963
|
+
return true;
|
|
964
|
+
};
|
|
965
|
+
/**
|
|
966
|
+
* Takes all currently available messages, waiting until at least one message
|
|
967
|
+
* is available when the queue is empty.
|
|
968
|
+
*
|
|
969
|
+
* **When to use**
|
|
970
|
+
*
|
|
971
|
+
* Use when consumers should process the next non-empty batch of buffered
|
|
972
|
+
* messages instead of repeatedly taking one message at a time.
|
|
973
|
+
*
|
|
974
|
+
* **Details**
|
|
975
|
+
*
|
|
976
|
+
* Returns a non-empty array. If the queue completes or fails before a message
|
|
977
|
+
* can be taken, the effect fails with the queue's terminal error.
|
|
978
|
+
*
|
|
979
|
+
* **Example** (Taking all available values)
|
|
980
|
+
*
|
|
981
|
+
* ```ts import.meta.vitest
|
|
982
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
983
|
+
*
|
|
984
|
+
* const program = Effect.gen(function*() {
|
|
985
|
+
* const queue = yield* Queue.bounded<number, Cause.Done>(5)
|
|
986
|
+
*
|
|
987
|
+
* // Add several messages
|
|
988
|
+
* yield* Queue.offerAll(queue, [1, 2, 3, 4, 5])
|
|
989
|
+
*
|
|
990
|
+
* // Take all available messages
|
|
991
|
+
* const messages1 = yield* Queue.takeAll(queue)
|
|
992
|
+
* return messages1
|
|
993
|
+
* })
|
|
994
|
+
*
|
|
995
|
+
* await Effect.runPromise(program) // => [1, 2, 3, 4, 5]
|
|
996
|
+
* ```
|
|
997
|
+
*
|
|
998
|
+
* @stability stable
|
|
999
|
+
* @category taking
|
|
1000
|
+
* @since 2.0.0
|
|
1001
|
+
*/
|
|
1002
|
+
const takeAll = (self) => takeBetween(self, 1, Number.POSITIVE_INFINITY);
|
|
1003
|
+
/**
|
|
1004
|
+
* Takes all messages from the queue, until the queue has errored or is done.
|
|
1005
|
+
*
|
|
1006
|
+
* **Example** (Collecting values until completion)
|
|
1007
|
+
*
|
|
1008
|
+
* ```ts import.meta.vitest
|
|
1009
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
1010
|
+
*
|
|
1011
|
+
* const program = Effect.gen(function*() {
|
|
1012
|
+
* const queue = yield* Queue.bounded<number, Cause.Done>(5)
|
|
1013
|
+
*
|
|
1014
|
+
* // Add several messages
|
|
1015
|
+
* yield* Queue.offerAll(queue, [1, 2, 3, 4, 5])
|
|
1016
|
+
* yield* Queue.end(queue)
|
|
1017
|
+
*
|
|
1018
|
+
* // Collect all available messages
|
|
1019
|
+
* return yield* Queue.collect(queue)
|
|
1020
|
+
* })
|
|
1021
|
+
*
|
|
1022
|
+
* await Effect.runPromise(program) // => [1, 2, 3, 4, 5]
|
|
1023
|
+
* ```
|
|
1024
|
+
*
|
|
1025
|
+
* @stability stable
|
|
1026
|
+
* @category taking
|
|
1027
|
+
* @since 4.0.0
|
|
1028
|
+
*/
|
|
1029
|
+
const collect = (self) => suspend(() => {
|
|
1030
|
+
const out = empty();
|
|
1031
|
+
return as(catchDone(whileLoop({
|
|
1032
|
+
while: constTrue,
|
|
1033
|
+
body: constant(takeAll(self)),
|
|
1034
|
+
step(items) {
|
|
1035
|
+
for (let i = 0; i < items.length; i++) out.push(items[i]);
|
|
1036
|
+
}
|
|
1037
|
+
}), () => void_), out);
|
|
1038
|
+
});
|
|
1039
|
+
/**
|
|
1040
|
+
* Takes between `min` and `max` messages from the queue.
|
|
1041
|
+
*
|
|
1042
|
+
* **Details**
|
|
1043
|
+
*
|
|
1044
|
+
* The operation waits when fewer than the required minimum messages are
|
|
1045
|
+
* available. It returns at most `max` messages. Finite fractional bounds are
|
|
1046
|
+
* rounded down, while `NaN` and non-positive bounds are treated as `0`. If the
|
|
1047
|
+
* queue is closing, drains the currently available messages even when fewer
|
|
1048
|
+
* than `min` are available. Once the queue is done, the effect fails with the
|
|
1049
|
+
* queue's terminal error.
|
|
1050
|
+
*
|
|
1051
|
+
* **Example** (Taking a bounded batch of values)
|
|
1052
|
+
*
|
|
1053
|
+
* ```ts import.meta.vitest
|
|
1054
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
1055
|
+
*
|
|
1056
|
+
* const program = Effect.gen(function*() {
|
|
1057
|
+
* const queue = yield* Queue.bounded<number>(10)
|
|
1058
|
+
*
|
|
1059
|
+
* // Add several messages
|
|
1060
|
+
* yield* Queue.offerAll(queue, [1, 2, 3, 4, 5, 6, 7, 8])
|
|
1061
|
+
*
|
|
1062
|
+
* // Take between 2 and 5 messages
|
|
1063
|
+
* const batch1 = yield* Queue.takeBetween(queue, 2, 5)
|
|
1064
|
+
*
|
|
1065
|
+
* // Take between 1 and 10 messages (but only 3 remain)
|
|
1066
|
+
* const batch2 = yield* Queue.takeBetween(queue, 1, 10)
|
|
1067
|
+
*
|
|
1068
|
+
* // No more messages available, will wait or return done
|
|
1069
|
+
* // const batch3 = yield* Queue.takeBetween(queue, 1, 3)
|
|
1070
|
+
* return [batch1, batch2]
|
|
1071
|
+
* })
|
|
1072
|
+
*
|
|
1073
|
+
* await Effect.runPromise(program) // => [[1, 2, 3, 4, 5], [6, 7, 8]]
|
|
1074
|
+
* ```
|
|
1075
|
+
*
|
|
1076
|
+
* @stability stable
|
|
1077
|
+
* @category taking
|
|
1078
|
+
* @since 2.0.0
|
|
1079
|
+
*/
|
|
1080
|
+
const takeBetween = /*#__PURE__*/ dual(3, (self, min, max) => {
|
|
1081
|
+
min = normalize(min);
|
|
1082
|
+
max = normalize(max);
|
|
1083
|
+
return suspendTake(() => takeBetweenUnsafe(self, min, max) ?? andThen(awaitTake(self, () => canTake(self, min)), takeBetween(self, min, max)));
|
|
1084
|
+
});
|
|
1085
|
+
/**
|
|
1086
|
+
* Takes a single message from the queue, or wait for a message to be
|
|
1087
|
+
* available.
|
|
1088
|
+
*
|
|
1089
|
+
* **Details**
|
|
1090
|
+
*
|
|
1091
|
+
* If the queue is done, it will fail with `Done`. If the
|
|
1092
|
+
* queue fails, the Effect will fail with the error.
|
|
1093
|
+
*
|
|
1094
|
+
* **Example** (Taking one value)
|
|
1095
|
+
*
|
|
1096
|
+
* ```ts import.meta.vitest
|
|
1097
|
+
* import { Cause, Effect, Exit, Queue } from "effect"
|
|
1098
|
+
*
|
|
1099
|
+
* const program = Effect.gen(function*() {
|
|
1100
|
+
* const queue = yield* Queue.bounded<string, Cause.Done>(3)
|
|
1101
|
+
*
|
|
1102
|
+
* // Add some messages
|
|
1103
|
+
* yield* Queue.offer(queue, "first")
|
|
1104
|
+
* yield* Queue.offer(queue, "second")
|
|
1105
|
+
*
|
|
1106
|
+
* // Take messages one by one
|
|
1107
|
+
* const msg1 = yield* Queue.take(queue)
|
|
1108
|
+
* const msg2 = yield* Queue.take(queue)
|
|
1109
|
+
*
|
|
1110
|
+
* // End the queue
|
|
1111
|
+
* yield* Queue.end(queue)
|
|
1112
|
+
*
|
|
1113
|
+
* // Taking from an ended queue fails with Done
|
|
1114
|
+
* const result = yield* Effect.exit(Queue.take(queue))
|
|
1115
|
+
* return [[msg1, msg2], result]
|
|
1116
|
+
* })
|
|
1117
|
+
*
|
|
1118
|
+
* await Effect.runPromise(program) // => [["first", "second"], Exit.fail(Cause.Done())]
|
|
1119
|
+
* ```
|
|
1120
|
+
*
|
|
1121
|
+
* @stability stable
|
|
1122
|
+
* @category taking
|
|
1123
|
+
* @since 2.0.0
|
|
1124
|
+
*/
|
|
1125
|
+
const take = (self) => suspendTake(() => takeUnsafe(self) ?? andThen(awaitTake(self, () => canTake(self, 1)), take(self)));
|
|
1126
|
+
/**
|
|
1127
|
+
* Attempts to take one item from the queue without waiting.
|
|
1128
|
+
*
|
|
1129
|
+
* **Details**
|
|
1130
|
+
*
|
|
1131
|
+
* Returns `Option.some` when an item is immediately available. Returns
|
|
1132
|
+
* `Option.none` when no item is available, when the queue is done, or when the
|
|
1133
|
+
* immediate take observes a queue failure.
|
|
1134
|
+
*
|
|
1135
|
+
* **Example** (Polling without blocking)
|
|
1136
|
+
*
|
|
1137
|
+
* ```ts import.meta.vitest
|
|
1138
|
+
* import { Effect, Option, Queue } from "effect"
|
|
1139
|
+
*
|
|
1140
|
+
* const program = Effect.gen(function*() {
|
|
1141
|
+
* const queue = yield* Queue.bounded<number>(10)
|
|
1142
|
+
*
|
|
1143
|
+
* // Poll returns Option.none if empty
|
|
1144
|
+
* const maybe1 = yield* Queue.poll(queue)
|
|
1145
|
+
*
|
|
1146
|
+
* // Add an item
|
|
1147
|
+
* yield* Queue.offer(queue, 42)
|
|
1148
|
+
*
|
|
1149
|
+
* // Poll returns Option.some with the item
|
|
1150
|
+
* const maybe2 = yield* Queue.poll(queue)
|
|
1151
|
+
* return [maybe1, maybe2]
|
|
1152
|
+
* })
|
|
1153
|
+
*
|
|
1154
|
+
* await Effect.runPromise(program) // => [Option.none(), Option.some(42)]
|
|
1155
|
+
* ```
|
|
1156
|
+
*
|
|
1157
|
+
* @stability stable
|
|
1158
|
+
* @category taking
|
|
1159
|
+
* @since 2.0.0
|
|
1160
|
+
*/
|
|
1161
|
+
const poll = (self) => suspendTake(() => {
|
|
1162
|
+
const result = takeUnsafe(self);
|
|
1163
|
+
if (result === void 0) return succeed(none());
|
|
1164
|
+
if (result._tag === "Success") return succeed(some(result.value));
|
|
1165
|
+
return succeed(none());
|
|
1166
|
+
});
|
|
1167
|
+
/**
|
|
1168
|
+
* Attempts to take one message from the queue synchronously.
|
|
1169
|
+
*
|
|
1170
|
+
* **When to use**
|
|
1171
|
+
*
|
|
1172
|
+
* Use when polling queue internals must not suspend or register a waiting taker,
|
|
1173
|
+
* and `undefined` is an acceptable result for an empty queue.
|
|
1174
|
+
*
|
|
1175
|
+
* **Details**
|
|
1176
|
+
*
|
|
1177
|
+
* Returns an `Exit` for an immediately available message or for the queue's
|
|
1178
|
+
* terminal state. Returns `undefined` when no message is immediately available.
|
|
1179
|
+
* This operation does not wait or register a taker.
|
|
1180
|
+
*
|
|
1181
|
+
* **Example** (Taking one value synchronously)
|
|
1182
|
+
*
|
|
1183
|
+
* ```ts import.meta.vitest
|
|
1184
|
+
* import { Effect, Exit, Queue } from "effect"
|
|
1185
|
+
*
|
|
1186
|
+
* // Create a queue and use unsafe operations
|
|
1187
|
+
* const program = Effect.gen(function*() {
|
|
1188
|
+
* const queue = yield* Queue.bounded<number>(10)
|
|
1189
|
+
*
|
|
1190
|
+
* // Add some messages
|
|
1191
|
+
* Queue.offerUnsafe(queue, 1)
|
|
1192
|
+
* Queue.offerUnsafe(queue, 2)
|
|
1193
|
+
*
|
|
1194
|
+
* // Take a message synchronously
|
|
1195
|
+
* const result1 = Queue.takeUnsafe(queue)
|
|
1196
|
+
*
|
|
1197
|
+
* const result2 = Queue.takeUnsafe(queue)
|
|
1198
|
+
*
|
|
1199
|
+
* // No more messages - returns undefined
|
|
1200
|
+
* const result3 = Queue.takeUnsafe(queue)
|
|
1201
|
+
* return [result1, result2, result3]
|
|
1202
|
+
* })
|
|
1203
|
+
*
|
|
1204
|
+
* await Effect.runPromise(program) // => [Exit.succeed(1), Exit.succeed(2), undefined]
|
|
1205
|
+
* ```
|
|
1206
|
+
*
|
|
1207
|
+
* @stability stable
|
|
1208
|
+
* @category taking
|
|
1209
|
+
* @since 4.0.0
|
|
1210
|
+
*/
|
|
1211
|
+
const takeUnsafe = (self) => {
|
|
1212
|
+
if (self.state._tag === "Done") return self.state.exit;
|
|
1213
|
+
if (self.messages.length > 0) {
|
|
1214
|
+
const message = take$1(self.messages);
|
|
1215
|
+
releaseCapacity(self);
|
|
1216
|
+
return exitSucceed(message);
|
|
1217
|
+
} else if (self.capacity <= 0 && self.state.offers.size > 0) {
|
|
1218
|
+
const message = takeOfferUnsafe(self.state.offers);
|
|
1219
|
+
releaseCapacity(self);
|
|
1220
|
+
return exitSucceed(message);
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
/**
|
|
1224
|
+
* Returns the current number of buffered messages in the queue synchronously.
|
|
1225
|
+
*
|
|
1226
|
+
* **When to use**
|
|
1227
|
+
*
|
|
1228
|
+
* Use when you need an immediate `Queue` size snapshot for diagnostics or
|
|
1229
|
+
* internals and do not need the read wrapped in `Effect`.
|
|
1230
|
+
*
|
|
1231
|
+
* **Details**
|
|
1232
|
+
*
|
|
1233
|
+
* After `endUnsafe`, a queue remains `Closing` while buffered messages are
|
|
1234
|
+
* drained, and its size continues to include those messages. A `Done` queue
|
|
1235
|
+
* reports a size of `0`. This unsafe operation reads the queue state directly
|
|
1236
|
+
* without Effect wrapping.
|
|
1237
|
+
*
|
|
1238
|
+
* **Example** (Checking queue size synchronously)
|
|
1239
|
+
*
|
|
1240
|
+
* ```ts import.meta.vitest
|
|
1241
|
+
* import { Cause, Effect, Queue } from "effect"
|
|
1242
|
+
*
|
|
1243
|
+
* const program = Effect.gen(function*() {
|
|
1244
|
+
* const queue = yield* Queue.bounded<number, Cause.Done>(10)
|
|
1245
|
+
*
|
|
1246
|
+
* // Check size of empty queue
|
|
1247
|
+
* const size1 = Queue.sizeUnsafe(queue)
|
|
1248
|
+
*
|
|
1249
|
+
* // Add some messages
|
|
1250
|
+
* Queue.offerUnsafe(queue, 1)
|
|
1251
|
+
* Queue.offerUnsafe(queue, 2)
|
|
1252
|
+
* Queue.offerUnsafe(queue, 3)
|
|
1253
|
+
*
|
|
1254
|
+
* // Check size after adding messages
|
|
1255
|
+
* const size2 = Queue.sizeUnsafe(queue)
|
|
1256
|
+
*
|
|
1257
|
+
* // End the queue
|
|
1258
|
+
* Queue.endUnsafe(queue)
|
|
1259
|
+
*
|
|
1260
|
+
* // Ending retains the buffered size while the queue is Closing
|
|
1261
|
+
* const size3 = Queue.sizeUnsafe(queue)
|
|
1262
|
+
* return [size1, size2, size3]
|
|
1263
|
+
* })
|
|
1264
|
+
*
|
|
1265
|
+
* await Effect.runPromise(program) // => [0, 3, 3]
|
|
1266
|
+
* ```
|
|
1267
|
+
*
|
|
1268
|
+
* @stability stable
|
|
1269
|
+
* @category sizes
|
|
1270
|
+
* @since 4.0.0
|
|
1271
|
+
*/
|
|
1272
|
+
const sizeUnsafe = (self) => self.state._tag === "Done" ? 0 : self.messages.length;
|
|
1273
|
+
const exitFalse = /*#__PURE__*/ exitSucceed(false);
|
|
1274
|
+
const exitTrue = /*#__PURE__*/ exitSucceed(true);
|
|
1275
|
+
const exitFailDone = /*#__PURE__*/ exitFail(/*#__PURE__*/ Done());
|
|
1276
|
+
const exitInterrupt = /*#__PURE__*/ exitInterrupt$1();
|
|
1277
|
+
const releaseTakers = (self) => {
|
|
1278
|
+
if (self.state._tag === "Done" || self.state.takers.size === 0) return;
|
|
1279
|
+
for (const taker of self.state.takers) {
|
|
1280
|
+
if (!taker.ready()) continue;
|
|
1281
|
+
self.state.takers.delete(taker);
|
|
1282
|
+
taker.resume(exitVoid);
|
|
1283
|
+
if (self.messages.length === 0) break;
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
const scheduleReleaseTaker = (self) => {
|
|
1287
|
+
if (self.scheduleRunning || self.state._tag === "Done" || self.state.takers.size === 0) return;
|
|
1288
|
+
self.scheduleRunning = true;
|
|
1289
|
+
self.dispatcher.scheduleTask(() => {
|
|
1290
|
+
self.scheduleRunning = false;
|
|
1291
|
+
releaseTakers(self);
|
|
1292
|
+
}, 0);
|
|
1293
|
+
};
|
|
1294
|
+
const takeBetweenUnsafe = (self, min, max) => {
|
|
1295
|
+
if (self.state._tag === "Done") return self.state.exit;
|
|
1296
|
+
else if (max <= 0 || min <= 0) return exitSucceed([]);
|
|
1297
|
+
else if (!canTake(self, min)) return;
|
|
1298
|
+
const messages = self.messages.length > 0 ? takeN(self.messages, max) : [takeOfferUnsafe(self.state.offers)];
|
|
1299
|
+
releaseCapacity(self);
|
|
1300
|
+
return exitSucceed(messages);
|
|
1301
|
+
};
|
|
1302
|
+
const suspendTake = /*#__PURE__*/ makePrimitive({
|
|
1303
|
+
op: "QueueTake",
|
|
1304
|
+
[evaluate](fiber) {
|
|
1305
|
+
const effect = this[args]();
|
|
1306
|
+
return isExit(effect) ? effect[evaluate](fiber) : effect;
|
|
1307
|
+
}
|
|
1308
|
+
});
|
|
1309
|
+
const canTake = (self, min) => self.messages.length >= (self.state._tag === "Closing" ? 1 : Math.min(min, self.capacity || 1)) || self.capacity <= 0 && self.state._tag !== "Done" && self.state.offers.size > 0;
|
|
1310
|
+
const awaitTake = (self, ready) => callback((resume) => {
|
|
1311
|
+
if (self.state._tag === "Done") return resume(self.state.exit);
|
|
1312
|
+
if (ready()) return resume(exitVoid);
|
|
1313
|
+
const taker = {
|
|
1314
|
+
ready,
|
|
1315
|
+
resume
|
|
1316
|
+
};
|
|
1317
|
+
self.state.takers.add(taker);
|
|
1318
|
+
return sync(() => {
|
|
1319
|
+
if (self.state._tag !== "Done") self.state.takers.delete(taker);
|
|
1320
|
+
});
|
|
1321
|
+
});
|
|
1322
|
+
const offerOrWait = (self, message) => callback((resume) => offerUnsafe(self, message) ? resume(exitTrue) : waitToOffer(self, {
|
|
1323
|
+
_tag: "Single",
|
|
1324
|
+
message,
|
|
1325
|
+
resume
|
|
1326
|
+
}));
|
|
1327
|
+
const waitToOffer = (self, entry) => {
|
|
1328
|
+
if (self.state._tag !== "Open") return resumeUnoffered(entry);
|
|
1329
|
+
const offers = self.state.offers;
|
|
1330
|
+
offers.add(entry);
|
|
1331
|
+
return sync(() => {
|
|
1332
|
+
if (self.state._tag === "Done") return;
|
|
1333
|
+
offers.delete(entry);
|
|
1334
|
+
if (self.state._tag === "Closing" && offers.size === 0 && self.messages.length === 0) finalize(self, self.state.exit);
|
|
1335
|
+
});
|
|
1336
|
+
};
|
|
1337
|
+
const resumeUnoffered = (entry) => entry._tag === "Single" ? entry.resume(exitFalse) : entry.resume(exitSucceed(entry.remaining.slice(entry.offset)));
|
|
1338
|
+
const takeOfferUnsafe = (offers) => {
|
|
1339
|
+
const entry = offers.values().next().value;
|
|
1340
|
+
if (entry._tag === "Single") {
|
|
1341
|
+
offers.delete(entry);
|
|
1342
|
+
entry.resume(exitTrue);
|
|
1343
|
+
return entry.message;
|
|
1344
|
+
}
|
|
1345
|
+
const message = entry.remaining[entry.offset++];
|
|
1346
|
+
if (entry.offset === entry.remaining.length) {
|
|
1347
|
+
offers.delete(entry);
|
|
1348
|
+
entry.resume(exitSucceed([]));
|
|
1349
|
+
}
|
|
1350
|
+
return message;
|
|
1351
|
+
};
|
|
1352
|
+
const releaseCapacity = (self) => {
|
|
1353
|
+
if (self.state._tag === "Done") return isDoneCause(self.state.exit.cause);
|
|
1354
|
+
else if (self.state.offers.size === 0) {
|
|
1355
|
+
if (self.state._tag === "Closing" && self.messages.length === 0) {
|
|
1356
|
+
finalize(self, self.state.exit);
|
|
1357
|
+
return isDoneCause(self.state.exit.cause);
|
|
1358
|
+
}
|
|
1359
|
+
return false;
|
|
1360
|
+
}
|
|
1361
|
+
for (const entry of self.state.offers) {
|
|
1362
|
+
let n = self.capacity - self.messages.length;
|
|
1363
|
+
if (n <= 0) break;
|
|
1364
|
+
else if (entry._tag === "Single") {
|
|
1365
|
+
append(self.messages, entry.message);
|
|
1366
|
+
self.state.offers.delete(entry);
|
|
1367
|
+
entry.resume(exitTrue);
|
|
1368
|
+
} else {
|
|
1369
|
+
for (; entry.offset < entry.remaining.length; entry.offset++) {
|
|
1370
|
+
if (n === 0) return false;
|
|
1371
|
+
append(self.messages, entry.remaining[entry.offset]);
|
|
1372
|
+
n--;
|
|
1373
|
+
}
|
|
1374
|
+
self.state.offers.delete(entry);
|
|
1375
|
+
entry.resume(exitSucceed([]));
|
|
1376
|
+
}
|
|
1377
|
+
const state = self.state;
|
|
1378
|
+
if (state._tag === "Done") return isDoneCause(state.exit.cause);
|
|
1379
|
+
}
|
|
1380
|
+
return false;
|
|
1381
|
+
};
|
|
1382
|
+
const finalize = (self, exit) => {
|
|
1383
|
+
if (self.state._tag === "Done") return;
|
|
1384
|
+
const openState = self.state;
|
|
1385
|
+
self.state = {
|
|
1386
|
+
_tag: "Done",
|
|
1387
|
+
exit
|
|
1388
|
+
};
|
|
1389
|
+
for (const taker of openState.takers) taker.resume(exit);
|
|
1390
|
+
openState.takers.clear();
|
|
1391
|
+
for (const awaiter of openState.awaiters) awaiter(exit);
|
|
1392
|
+
openState.awaiters.clear();
|
|
1393
|
+
};
|
|
1394
|
+
export { takeAll as _, fail as a, make as c, offerUnsafe as d, poll as f, take as g, sliding as h, endUnsafe as i, offer as l, shutdownUnsafe as m, collect as n, failCause as o, shutdown as p, end as r, failCauseUnsafe as s, bounded as t, offerAll as u, unbounded as v };
|