effect-cf 0.34.0 → 0.35.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/CHANGELOG.md +10 -0
- package/dist/ComputerWorkspace.d.mts +11 -3
- package/dist/ComputerWorkspace.mjs +31 -9
- package/dist/{DurableObjectState-De4ZojhY.mjs → DurableObjectState-DcqElJ4e.mjs} +81 -50
- package/dist/{DurableObjectState-CrEunfQ-.d.mts → DurableObjectState-DpYdNZgT.d.mts} +35 -29
- package/dist/Vitest.d.mts +2 -2
- package/dist/Vitest.mjs +7 -10
- package/dist/{WorkflowBinding-BumVQTuW.d.mts → WorkflowBinding-Cn3AuUyP.d.mts} +1 -1
- package/dist/index.d.mts +12 -4
- package/dist/index.mjs +102 -77
- package/package.json +1 -1
- package/src/AnalyticsEngine.ts +8 -1
- package/src/CloudflareOtlp.ts +6 -3
- package/src/ComputerWorkspace.ts +53 -26
- package/src/DurableObject.ts +8 -9
- package/src/DurableObjectNamespace.ts +33 -5
- package/src/DurableObjectRpcWebSocket.ts +2 -27
- package/src/DurableObjectState.ts +18 -20
- package/src/DurableObjectStorage.ts +53 -35
- package/src/DurableObjectWebSocket.ts +23 -41
- package/src/RpcDefinition.ts +5 -15
- package/src/ServiceBinding.ts +37 -5
- package/src/Vitest.ts +18 -15
- package/src/Worker.ts +107 -54
- package/src/WorkersAi.ts +21 -14
- package/src/Workflow.ts +45 -49
- package/src/internal/NativeCallback.ts +55 -0
- package/src/internal/WorkerContext.ts +5 -3
|
@@ -230,7 +230,6 @@ export const layer = (
|
|
|
230
230
|
const disconnects = yield* Queue.make<number>();
|
|
231
231
|
const connectionsBySocket = new Map<WebSocket, RpcConnection>();
|
|
232
232
|
const connectionsById = new Map<number, RpcConnection>();
|
|
233
|
-
const clientIds = new Set<number>();
|
|
234
233
|
const resetSockets = new WeakSet<WebSocket>();
|
|
235
234
|
const declarationsById = new Map<string, AnyResumableStreamDeclaration>();
|
|
236
235
|
const declarationsByTag = new Map<string, AnyResumableStreamDeclaration>();
|
|
@@ -268,21 +267,6 @@ export const layer = (
|
|
|
268
267
|
}
|
|
269
268
|
|
|
270
269
|
const reserveClientId = (socket: DurableWebSocket): AttachmentMetadata => {
|
|
271
|
-
const attachment = readAttachment(socket.raw, attachmentKey);
|
|
272
|
-
|
|
273
|
-
if (attachment._tag === "Invalid") {
|
|
274
|
-
throw new Error("Invalid Durable Object RPC websocket attachment metadata");
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (attachment._tag === "Valid") {
|
|
278
|
-
const metadata = attachment.metadata;
|
|
279
|
-
|
|
280
|
-
nextClientId = Math.max(nextClientId, metadata.clientId + 1);
|
|
281
|
-
writeAttachment(socket.raw, attachmentKey, metadata);
|
|
282
|
-
|
|
283
|
-
return metadata;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
270
|
const id = nextClientId++;
|
|
287
271
|
const created: LegacyAttachmentMetadata = {
|
|
288
272
|
version: legacyAttachmentVersion,
|
|
@@ -377,7 +361,6 @@ export const layer = (
|
|
|
377
361
|
|
|
378
362
|
connectionsBySocket.set(socket.raw, connection);
|
|
379
363
|
connectionsById.set(connection.id, connection);
|
|
380
|
-
clientIds.add(connection.id);
|
|
381
364
|
nextClientId = Math.max(nextClientId, connection.id + 1);
|
|
382
365
|
|
|
383
366
|
return connection;
|
|
@@ -434,7 +417,6 @@ export const layer = (
|
|
|
434
417
|
|
|
435
418
|
connectionsBySocket.delete(socket.raw);
|
|
436
419
|
connectionsById.delete(connection.id);
|
|
437
|
-
clientIds.delete(connection.id);
|
|
438
420
|
activeNonResumableRequestCount -= connection.nonResumableRequestIds.size;
|
|
439
421
|
connection.requestIds.clear();
|
|
440
422
|
connection.nonResumableRequestIds.clear();
|
|
@@ -847,7 +829,7 @@ export const layer = (
|
|
|
847
829
|
|
|
848
830
|
connection?.socket.raw.close();
|
|
849
831
|
}),
|
|
850
|
-
clientIds: Effect.sync(() =>
|
|
832
|
+
clientIds: Effect.sync(() => new Set(connectionsById.keys())),
|
|
851
833
|
initialMessage: Effect.succeedNone,
|
|
852
834
|
supportsAck: true,
|
|
853
835
|
supportsTransferables: false,
|
|
@@ -1141,17 +1123,10 @@ const writeAttachment = (socket: WebSocket, key: string, metadata: AttachmentMet
|
|
|
1141
1123
|
}
|
|
1142
1124
|
|
|
1143
1125
|
const attachment = Predicate.isObject(current) ? current : {};
|
|
1144
|
-
const currentMetadata =
|
|
1145
|
-
Predicate.hasProperty(attachment, key) && Predicate.isObject(attachment[key])
|
|
1146
|
-
? attachment[key]
|
|
1147
|
-
: {};
|
|
1148
1126
|
|
|
1149
1127
|
socket.serializeAttachment({
|
|
1150
1128
|
...attachment,
|
|
1151
|
-
[key]:
|
|
1152
|
-
...currentMetadata,
|
|
1153
|
-
...metadata,
|
|
1154
|
-
},
|
|
1129
|
+
[key]: metadata,
|
|
1155
1130
|
});
|
|
1156
1131
|
};
|
|
1157
1132
|
|
|
@@ -3,6 +3,7 @@ import { Cause, Context, Effect, Exit } from "effect";
|
|
|
3
3
|
import { fromDurableObjectStorage, type DurableObjectStorage } from "./DurableObjectStorage";
|
|
4
4
|
import { fromWebSocket, type DurableWebSocket } from "./DurableObjectWebSocket";
|
|
5
5
|
import type { WorkerContextWaitUntilOptions } from "./Worker";
|
|
6
|
+
import { runNativeCallback } from "./internal/NativeCallback";
|
|
6
7
|
import { makeWaitUntilScheduler } from "./internal/WorkerContext";
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -87,24 +88,21 @@ export const fromDurableObjectState = (
|
|
|
87
88
|
storage: fromDurableObjectStorage(state.storage),
|
|
88
89
|
waitUntil,
|
|
89
90
|
blockConcurrencyWhile: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
state.blockConcurrencyWhile(() =>
|
|
94
|
-
runPromiseExitPreservingTypedFailures(context, effect),
|
|
95
|
-
),
|
|
96
|
-
),
|
|
97
|
-
),
|
|
98
|
-
Effect.flatten,
|
|
99
|
-
),
|
|
91
|
+
runNativeCallback<A, E, R, Exit.Exit<A, E>>((run) =>
|
|
92
|
+
state.blockConcurrencyWhile(() => runExitPreservingTypedFailures(run, effect)),
|
|
93
|
+
).pipe(Effect.orDie, Effect.flatten),
|
|
100
94
|
blockConcurrencyWhileOrReset: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
|
|
95
|
+
runNativeCallback<A, E, R, A>((run) =>
|
|
96
|
+
state.blockConcurrencyWhile(async () => {
|
|
97
|
+
const exit = await run(effect);
|
|
98
|
+
|
|
99
|
+
if (Exit.isFailure(exit)) {
|
|
100
|
+
throw Cause.squash(exit.cause);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return exit.value;
|
|
104
|
+
}),
|
|
105
|
+
).pipe(Effect.orDie),
|
|
108
106
|
acceptWebSocket: (ws: DurableWebSocket, tags?: Array<string>) =>
|
|
109
107
|
Effect.sync(() => state.acceptWebSocket(ws.raw, tags)),
|
|
110
108
|
getWebSockets: (tag?: string) =>
|
|
@@ -125,11 +123,11 @@ export const fromDurableObjectState = (
|
|
|
125
123
|
};
|
|
126
124
|
};
|
|
127
125
|
|
|
128
|
-
const
|
|
129
|
-
|
|
126
|
+
const runExitPreservingTypedFailures = async <A, E, R>(
|
|
127
|
+
run: (effect: Effect.Effect<A, E, R>) => Promise<Exit.Exit<A, E>>,
|
|
130
128
|
effect: Effect.Effect<A, E, R>,
|
|
131
129
|
): Promise<Exit.Exit<A, E>> => {
|
|
132
|
-
const exit = await
|
|
130
|
+
const exit = await run(effect);
|
|
133
131
|
|
|
134
132
|
if (Exit.isFailure(exit) && (Cause.hasDies(exit.cause) || Cause.hasInterrupts(exit.cause))) {
|
|
135
133
|
throw Cause.squash(exit.cause);
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Cause,
|
|
3
|
+
Clock,
|
|
4
|
+
Data,
|
|
5
|
+
Duration,
|
|
6
|
+
Effect,
|
|
7
|
+
Exit,
|
|
8
|
+
Fiber,
|
|
9
|
+
Option,
|
|
10
|
+
Predicate,
|
|
11
|
+
Result,
|
|
12
|
+
Schema as S,
|
|
13
|
+
} from "effect";
|
|
2
14
|
|
|
3
15
|
import * as ErrorMessage from "./internal/ErrorMessage";
|
|
16
|
+
import { runNativeCallback } from "./internal/NativeCallback";
|
|
4
17
|
|
|
5
18
|
export type SqlStorageValue = globalThis.SqlStorageValue;
|
|
6
19
|
|
|
@@ -331,6 +344,7 @@ export const fromDurableObjectStorage = (
|
|
|
331
344
|
// failed Exit is thrown to abort it. Keep a typed reference to that
|
|
332
345
|
// Exit rather than recovering its type from the untyped catch binding.
|
|
333
346
|
let aborted: Exit.Exit<A, E> | undefined;
|
|
347
|
+
let escapedFiber: Fiber.Fiber<unknown, unknown> | undefined;
|
|
334
348
|
|
|
335
349
|
try {
|
|
336
350
|
return Effect.succeed(
|
|
@@ -340,55 +354,59 @@ export const fromDurableObjectStorage = (
|
|
|
340
354
|
if (Exit.isSuccess(exit)) {
|
|
341
355
|
return exit.value;
|
|
342
356
|
}
|
|
357
|
+
const defect = Cause.findDefect(exit.cause);
|
|
358
|
+
|
|
359
|
+
if (Result.isSuccess(defect) && Cause.isAsyncFiberError(defect.success)) {
|
|
360
|
+
escapedFiber = defect.success.fiber;
|
|
361
|
+
escapedFiber.interruptUnsafe();
|
|
362
|
+
}
|
|
343
363
|
aborted = exit;
|
|
344
364
|
|
|
345
365
|
throw exit;
|
|
346
366
|
}),
|
|
347
367
|
);
|
|
348
368
|
} catch (cause) {
|
|
349
|
-
|
|
350
|
-
|
|
369
|
+
const failure: Effect.Effect<never, E | StorageOperationError> =
|
|
370
|
+
aborted !== undefined && cause === aborted && Exit.isFailure(aborted)
|
|
371
|
+
? Effect.failCause(aborted.cause)
|
|
372
|
+
: Effect.fail(storageError("transactionSync", cause));
|
|
373
|
+
const fiber = escapedFiber;
|
|
374
|
+
|
|
375
|
+
if (fiber !== undefined) {
|
|
376
|
+
return Fiber.interrupt(fiber).pipe(Effect.andThen(failure));
|
|
351
377
|
}
|
|
352
378
|
|
|
353
|
-
return
|
|
379
|
+
return failure;
|
|
354
380
|
}
|
|
355
381
|
}),
|
|
356
382
|
),
|
|
357
383
|
),
|
|
358
384
|
transaction: <A, E, R>(closure: (txn: DurableObjectTransaction) => Effect.Effect<A, E, R>) =>
|
|
359
|
-
Effect.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
// transaction, and holding it here keeps its error type.
|
|
364
|
-
let aborted: Exit.Exit<A, E> | undefined;
|
|
385
|
+
Effect.suspend(() => {
|
|
386
|
+
// See `transactionSync`: the thrown Exit aborts Cloudflare's
|
|
387
|
+
// transaction, and holding it here keeps its error type.
|
|
388
|
+
let aborted: Exit.Exit<A, E> | undefined;
|
|
365
389
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
throw exit;
|
|
378
|
-
})
|
|
379
|
-
.then(
|
|
380
|
-
(value) => resume(Effect.succeed(value)),
|
|
381
|
-
(cause) => {
|
|
382
|
-
if (aborted !== undefined && cause === aborted && Exit.isFailure(aborted)) {
|
|
383
|
-
resume(Effect.failCause(aborted.cause));
|
|
384
|
-
} else {
|
|
385
|
-
resume(Effect.fail(storageError("transaction", cause)));
|
|
386
|
-
}
|
|
387
|
-
},
|
|
388
|
-
);
|
|
390
|
+
return runNativeCallback<A, E, R, A>((run) =>
|
|
391
|
+
storage.transaction(async (txn) => {
|
|
392
|
+
const exit = await run(Effect.suspend(() => closure(fromDurableObjectTransaction(txn))));
|
|
393
|
+
|
|
394
|
+
if (Exit.isSuccess(exit)) {
|
|
395
|
+
return exit.value;
|
|
396
|
+
}
|
|
397
|
+
aborted = exit;
|
|
398
|
+
|
|
399
|
+
throw exit;
|
|
389
400
|
}),
|
|
390
|
-
)
|
|
391
|
-
|
|
401
|
+
).pipe(
|
|
402
|
+
Effect.catch(
|
|
403
|
+
(cause): Effect.Effect<never, E | StorageOperationError> =>
|
|
404
|
+
aborted !== undefined && cause === aborted && Exit.isFailure(aborted)
|
|
405
|
+
? Effect.failCause(aborted.cause)
|
|
406
|
+
: Effect.fail(storageError("transaction", cause)),
|
|
407
|
+
),
|
|
408
|
+
);
|
|
409
|
+
}),
|
|
392
410
|
sync: () => tryStoragePromise("sync", () => storage.sync()),
|
|
393
411
|
getCurrentBookmark: () =>
|
|
394
412
|
tryStoragePromise("getCurrentBookmark", () => storage.getCurrentBookmark()),
|
|
@@ -38,53 +38,37 @@ export interface DurableWebSocket<Attachment = unknown> {
|
|
|
38
38
|
send(data: DurableWebSocketSendData): Effect.Effect<void, DurableWebSocketSendError>;
|
|
39
39
|
close(code?: number, reason?: string): Effect.Effect<void, DurableWebSocketCloseError>;
|
|
40
40
|
/** Serializes hibernation attachment metadata onto the socket. */
|
|
41
|
-
serializeAttachment<A = Attachment>(
|
|
41
|
+
serializeAttachment<A extends Attachment = Attachment>(
|
|
42
42
|
value: A,
|
|
43
43
|
): Effect.Effect<void, DurableWebSocketAttachmentError>;
|
|
44
44
|
/** Deserializes hibernation attachment metadata from the socket. */
|
|
45
45
|
readonly deserializeAttachment: Effect.Effect<unknown, DurableWebSocketAttachmentError>;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const wrappers = new WeakMap<WebSocket, DurableWebSocket<unknown>>();
|
|
49
|
-
|
|
50
48
|
export const fromWebSocket = <Attachment = unknown>(
|
|
51
49
|
raw: WebSocket,
|
|
52
|
-
): DurableWebSocket<Attachment> => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const socket: DurableWebSocket<unknown> = {
|
|
61
|
-
raw,
|
|
62
|
-
send: (data) =>
|
|
63
|
-
Effect.try({
|
|
64
|
-
try: () => raw.send(data),
|
|
65
|
-
catch: (cause) => new DurableWebSocketSendError({ cause }),
|
|
66
|
-
}),
|
|
67
|
-
close: (code, reason) =>
|
|
68
|
-
Effect.try({
|
|
69
|
-
try: () => raw.close(code, reason),
|
|
70
|
-
catch: (cause) => new DurableWebSocketCloseError({ cause }),
|
|
71
|
-
}),
|
|
72
|
-
serializeAttachment: (value) =>
|
|
73
|
-
Effect.try({
|
|
74
|
-
try: () => raw.serializeAttachment(value),
|
|
75
|
-
catch: (cause) => new DurableWebSocketAttachmentError({ operation: "serialize", cause }),
|
|
76
|
-
}),
|
|
77
|
-
deserializeAttachment: Effect.try({
|
|
78
|
-
try: () => raw.deserializeAttachment(),
|
|
79
|
-
catch: (cause) => new DurableWebSocketAttachmentError({ operation: "deserialize", cause }),
|
|
50
|
+
): DurableWebSocket<Attachment> => ({
|
|
51
|
+
raw,
|
|
52
|
+
send: (data) =>
|
|
53
|
+
Effect.try({
|
|
54
|
+
try: () => raw.send(data),
|
|
55
|
+
catch: (cause) => new DurableWebSocketSendError({ cause }),
|
|
80
56
|
}),
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
57
|
+
close: (code, reason) =>
|
|
58
|
+
Effect.try({
|
|
59
|
+
try: () => raw.close(code, reason),
|
|
60
|
+
catch: (cause) => new DurableWebSocketCloseError({ cause }),
|
|
61
|
+
}),
|
|
62
|
+
serializeAttachment: <A extends Attachment = Attachment>(value: A) =>
|
|
63
|
+
Effect.try({
|
|
64
|
+
try: () => raw.serializeAttachment(value),
|
|
65
|
+
catch: (cause) => new DurableWebSocketAttachmentError({ operation: "serialize", cause }),
|
|
66
|
+
}),
|
|
67
|
+
deserializeAttachment: Effect.try({
|
|
68
|
+
try: () => raw.deserializeAttachment(),
|
|
69
|
+
catch: (cause) => new DurableWebSocketAttachmentError({ operation: "deserialize", cause }),
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
88
72
|
|
|
89
73
|
export interface AcceptUpgradeOptions<Attachment = unknown> {
|
|
90
74
|
readonly tags?: ReadonlyArray<string> | undefined;
|
|
@@ -165,15 +149,13 @@ export const attachment = <const AttachmentSchema extends S.Codec<any, any, neve
|
|
|
165
149
|
S.Codec.Encoded<AttachmentSchema>
|
|
166
150
|
> => {
|
|
167
151
|
type Attachment = S.Schema.Type<AttachmentSchema>;
|
|
168
|
-
type Encoded = S.Codec.Encoded<AttachmentSchema>;
|
|
169
152
|
|
|
170
153
|
const serialize = (socket: DurableWebSocket<unknown>, value: Attachment) =>
|
|
171
154
|
S.encodeEffect(schema)(value).pipe(
|
|
172
155
|
Effect.mapError(
|
|
173
156
|
(cause) => new DurableWebSocketAttachmentError({ operation: "serialize", cause }),
|
|
174
157
|
),
|
|
175
|
-
|
|
176
|
-
Effect.flatMap((encoded) => socket.serializeAttachment(encoded as Encoded)),
|
|
158
|
+
Effect.flatMap((encoded) => socket.serializeAttachment(encoded)),
|
|
177
159
|
);
|
|
178
160
|
|
|
179
161
|
const deserialize = (socket: DurableWebSocket<unknown>) =>
|
package/src/RpcDefinition.ts
CHANGED
|
@@ -124,7 +124,7 @@ export const decodeWireError = (cause: WireValue): WireValue => {
|
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
const reservedMethodNameValues = [
|
|
128
128
|
"constructor",
|
|
129
129
|
"fetch",
|
|
130
130
|
"connect",
|
|
@@ -137,21 +137,11 @@ export const reservedMethodNames = new Set([
|
|
|
137
137
|
"dispose",
|
|
138
138
|
"serialize",
|
|
139
139
|
"deserialize",
|
|
140
|
-
]
|
|
140
|
+
] as const;
|
|
141
|
+
|
|
142
|
+
export const reservedMethodNames = new Set<string>(reservedMethodNameValues);
|
|
141
143
|
|
|
142
|
-
export type ReservedMethodName =
|
|
143
|
-
| "constructor"
|
|
144
|
-
| "fetch"
|
|
145
|
-
| "connect"
|
|
146
|
-
| "alarm"
|
|
147
|
-
| "webSocketMessage"
|
|
148
|
-
| "webSocketClose"
|
|
149
|
-
| "webSocketError"
|
|
150
|
-
| "then"
|
|
151
|
-
| "dup"
|
|
152
|
-
| "dispose"
|
|
153
|
-
| "serialize"
|
|
154
|
-
| "deserialize";
|
|
144
|
+
export type ReservedMethodName = (typeof reservedMethodNameValues)[number];
|
|
155
145
|
|
|
156
146
|
export type ServiceFreeSchema = S.Codec<any, any, never, never>;
|
|
157
147
|
|
package/src/ServiceBinding.ts
CHANGED
|
@@ -145,7 +145,11 @@ export type ServiceBindingEffectClient<
|
|
|
145
145
|
readonly scopedCall: <Method extends ServiceMethodKey<Api>>(
|
|
146
146
|
method: Method,
|
|
147
147
|
...args: ServiceMethodArgs<Api, Method>
|
|
148
|
-
) => Effect.Effect<
|
|
148
|
+
) => Effect.Effect<
|
|
149
|
+
Awaited<ServiceMethodSuccess<Api, Method>>,
|
|
150
|
+
ServiceBindingRpcError,
|
|
151
|
+
Scope.Scope
|
|
152
|
+
>;
|
|
149
153
|
};
|
|
150
154
|
|
|
151
155
|
export type ServiceBindingStaticClient<
|
|
@@ -168,7 +172,11 @@ export type ServiceBindingStaticClient<
|
|
|
168
172
|
readonly scopedCall: <Method extends ServiceMethodKey<Api>>(
|
|
169
173
|
method: Method,
|
|
170
174
|
...args: ServiceMethodArgs<Api, Method>
|
|
171
|
-
) => Effect.Effect<
|
|
175
|
+
) => Effect.Effect<
|
|
176
|
+
Awaited<ServiceMethodSuccess<Api, Method>>,
|
|
177
|
+
ServiceBindingRpcError,
|
|
178
|
+
Scope.Scope | R
|
|
179
|
+
>;
|
|
172
180
|
};
|
|
173
181
|
|
|
174
182
|
type ServiceBindingValue = Schema.Schema.Type<typeof Schema.Unknown>;
|
|
@@ -195,7 +203,22 @@ export const makeClient = <
|
|
|
195
203
|
init?: RequestInit,
|
|
196
204
|
) {
|
|
197
205
|
return yield* Effect.tryPromise({
|
|
198
|
-
try: () =>
|
|
206
|
+
try: (signal) => {
|
|
207
|
+
const callerSignal =
|
|
208
|
+
init?.signal !== undefined
|
|
209
|
+
? init.signal
|
|
210
|
+
: input instanceof Request
|
|
211
|
+
? input.signal
|
|
212
|
+
: undefined;
|
|
213
|
+
|
|
214
|
+
return service.fetch(input, {
|
|
215
|
+
...init,
|
|
216
|
+
signal:
|
|
217
|
+
callerSignal === null || callerSignal === undefined
|
|
218
|
+
? signal
|
|
219
|
+
: AbortSignal.any([callerSignal, signal]),
|
|
220
|
+
});
|
|
221
|
+
},
|
|
199
222
|
catch: (cause) => new ServiceBindingFetchError({ binding: definition.binding, cause }),
|
|
200
223
|
});
|
|
201
224
|
});
|
|
@@ -298,10 +321,19 @@ export const makeClient = <
|
|
|
298
321
|
function* <Method extends ServiceMethodKey<Api>>(
|
|
299
322
|
method: Method,
|
|
300
323
|
...args: ServiceMethodArgs<Api, Method>
|
|
301
|
-
): Effect.fn.Return<ServiceMethodSuccess<Api, Method>,
|
|
324
|
+
): Effect.fn.Return<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError, Scope.Scope> {
|
|
302
325
|
const methodName = String(method);
|
|
303
326
|
const result = yield* rpc(method, ...args);
|
|
304
|
-
const value = yield* CloudflareRpc.scoped(result)
|
|
327
|
+
const value = yield* CloudflareRpc.scoped(result).pipe(
|
|
328
|
+
Effect.mapError(
|
|
329
|
+
(cause) =>
|
|
330
|
+
new ServiceBindingRpcError({
|
|
331
|
+
binding: definition.binding,
|
|
332
|
+
method: methodName,
|
|
333
|
+
cause,
|
|
334
|
+
}),
|
|
335
|
+
),
|
|
336
|
+
);
|
|
305
337
|
|
|
306
338
|
return yield* decodeSuccess<Method>(methodName, value);
|
|
307
339
|
},
|
package/src/Vitest.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
} from "./DurableObjectState";
|
|
34
34
|
import { WorkerConfig, WorkerEnvironment, type WorkerEnv } from "./Environment";
|
|
35
35
|
import type { WorkflowInstanceStatusName } from "./WorkflowBinding";
|
|
36
|
+
import { runNativeCallback } from "./internal/NativeCallback";
|
|
36
37
|
|
|
37
38
|
const currentEnv: WorkerEnv = env;
|
|
38
39
|
|
|
@@ -207,15 +208,20 @@ export const runInDurableObject = Effect.fn("effect-cf/vitest/runInDurableObject
|
|
|
207
208
|
stub: globalThis.DurableObjectStub<Object>,
|
|
208
209
|
use: (instance: Object, state: DurableObjectStateService) => Effect.Effect<A, E, R>,
|
|
209
210
|
): Effect.fn.Return<A, E, Exclude<R, DurableObjectState>> {
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
211
|
+
const exit = yield* runNativeCallback<A, E, Exclude<R, DurableObjectState>, Exit.Exit<A, E>>(
|
|
212
|
+
(run) =>
|
|
213
|
+
runInDurableObjectPromise(stub, (instance, nativeState) => {
|
|
214
|
+
const state = fromDurableObjectState(nativeState);
|
|
215
|
+
|
|
216
|
+
return run(
|
|
217
|
+
Effect.provideService(
|
|
218
|
+
Effect.suspend(() => use(instance, state)),
|
|
219
|
+
DurableObjectState,
|
|
220
|
+
state,
|
|
221
|
+
),
|
|
222
|
+
);
|
|
223
|
+
}),
|
|
224
|
+
).pipe(Effect.orDie);
|
|
219
225
|
|
|
220
226
|
return yield* exit;
|
|
221
227
|
});
|
|
@@ -394,15 +400,12 @@ const runWorkflowModifier = Effect.fnUntraced(function* <A, E, R>(
|
|
|
394
400
|
register: (use: (modifier: NativeWorkflowInstanceModifier) => Promise<void>) => Promise<any>,
|
|
395
401
|
use: (modifier: WorkflowInstanceModifier) => Effect.Effect<A, E, R>,
|
|
396
402
|
): Effect.fn.Return<A, E, R> {
|
|
397
|
-
const
|
|
398
|
-
const exit = yield* Effect.promise(async () => {
|
|
403
|
+
const exit = yield* runNativeCallback<A, E, R, Exit.Exit<A, E>>(async (run) => {
|
|
399
404
|
let callbackExit: Exit.Exit<A, E> | undefined;
|
|
400
405
|
|
|
401
406
|
try {
|
|
402
407
|
await register(async (modifier) => {
|
|
403
|
-
callbackExit = await Effect.
|
|
404
|
-
use(wrapWorkflowModifier(modifier)),
|
|
405
|
-
);
|
|
408
|
+
callbackExit = await run(Effect.suspend(() => use(wrapWorkflowModifier(modifier))));
|
|
406
409
|
|
|
407
410
|
if (Exit.isFailure(callbackExit)) {
|
|
408
411
|
throw callbackExit;
|
|
@@ -421,7 +424,7 @@ const runWorkflowModifier = Effect.fnUntraced(function* <A, E, R>(
|
|
|
421
424
|
}
|
|
422
425
|
|
|
423
426
|
return callbackExit;
|
|
424
|
-
});
|
|
427
|
+
}).pipe(Effect.orDie);
|
|
425
428
|
|
|
426
429
|
return yield* exit;
|
|
427
430
|
});
|