effect-cf 0.33.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 +22 -0
- package/README.md +31 -1079
- package/dist/{Artifacts-DnHQA-Ax.d.mts → Artifacts-B3r3RuTB.d.mts} +1 -48
- package/dist/{Artifacts-CSIk1Oml.mjs → Artifacts-CBxWGeZB.mjs} +2 -7
- package/dist/{Binding-pfilNJmP.mjs → Binding-C82jRhdr.mjs} +1 -2
- package/dist/{Binding-xJJJPmiD.d.mts → Binding-DKcLrQCM.d.mts} +0 -45
- package/dist/ComputerArtifacts.d.mts +1 -3
- package/dist/ComputerArtifacts.mjs +1 -2
- package/dist/ComputerWorkspace.d.mts +11 -12
- package/dist/ComputerWorkspace.mjs +31 -10
- package/dist/ComputerWorkspaceHost.d.mts +1 -9
- package/dist/{ContainerNamespace-CFjiLw8b.d.mts → ContainerNamespace-DbLaeFhN.d.mts} +1 -14
- package/dist/{DurableObjectState-CVLLse69.mjs → DurableObjectState-DcqElJ4e.mjs} +82 -89
- package/dist/{DurableObjectState-BpRjz6-q.d.mts → DurableObjectState-DpYdNZgT.d.mts} +102 -266
- package/dist/{ErrorMessage-BM0K-Nik.mjs → ErrorMessage-Byx2OgNd.mjs} +0 -1
- package/dist/{Hyperdrive-z-9fFz15.d.mts → Hyperdrive-HrwFlZ6x.d.mts} +1 -4
- package/dist/HyperdrivePg.d.mts +2 -11
- package/dist/HyperdrivePg.mjs +0 -8
- package/dist/Sandbox.d.mts +2 -32
- package/dist/Sandbox.mjs +2 -11
- package/dist/Vitest.d.mts +3 -31
- package/dist/Vitest.mjs +8 -26
- package/dist/{WorkflowBinding-lBR4_-op.d.mts → WorkflowBinding-Cn3AuUyP.d.mts} +2 -5
- package/dist/index.d.mts +42 -480
- package/dist/index.mjs +267 -380
- package/package.json +1 -1
- package/src/AiGateway.ts +0 -6
- package/src/AnalyticsEngine.ts +8 -10
- package/src/Artifacts.ts +0 -47
- package/src/Binding.ts +0 -8
- package/src/BrowserRendering.ts +0 -4
- package/src/Cache.ts +0 -19
- package/src/CloudflareOtlp.ts +6 -39
- package/src/ComputerArtifacts.ts +0 -2
- package/src/ComputerWorkspace.ts +53 -35
- package/src/ComputerWorkspaceHost.ts +0 -8
- package/src/ContainerNamespace.ts +0 -13
- package/src/D1.ts +0 -22
- package/src/DurableObject.ts +51 -32
- package/src/DurableObjectAlarm.ts +6 -210
- package/src/DurableObjectDefinition.ts +8 -20
- package/src/DurableObjectNamespace.ts +88 -115
- package/src/DurableObjectRpcWebSocket.ts +5 -46
- package/src/DurableObjectSqlite.ts +0 -12
- package/src/DurableObjectState.ts +18 -38
- package/src/DurableObjectStorage.ts +55 -70
- package/src/DurableObjectWebSocket.ts +23 -72
- package/src/Email.ts +0 -12
- package/src/Environment.ts +0 -37
- package/src/Hyperdrive.ts +0 -3
- package/src/HyperdrivePg.ts +0 -9
- package/src/Images.ts +0 -5
- package/src/Kv.ts +0 -15
- package/src/QueueBinding.ts +0 -2
- package/src/R2.ts +0 -5
- package/src/RpcDefinition.ts +5 -17
- package/src/RpcTracing.ts +133 -0
- package/src/Sandbox.ts +0 -30
- package/src/ServiceBinding.ts +83 -128
- package/src/Vectorize.ts +0 -5
- package/src/Vitest.ts +18 -43
- package/src/WebTransport.ts +0 -15
- package/src/Worker.ts +140 -108
- package/src/WorkerDefinition.ts +5 -14
- package/src/WorkersAi.ts +21 -18
- package/src/Workflow.ts +45 -54
- package/src/WorkflowBinding.ts +0 -3
- package/src/index.ts +1 -0
- package/src/internal/Entrypoint.ts +23 -4
- package/src/internal/ErrorMessage.ts +0 -1
- package/src/internal/NativeCallback.ts +55 -0
- package/src/internal/RpcInvocation.ts +18 -1
- package/src/internal/Runtime.ts +12 -7
- package/src/internal/WorkerContext.ts +5 -14
package/src/Workflow.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Effect wrapper for Cloudflare Workflows entrypoints and bindings; distinct
|
|
3
|
-
* from Effect's runtime-agnostic `effect/unstable/workflow` cluster module.
|
|
4
|
-
*/
|
|
5
1
|
import {
|
|
6
2
|
WorkflowEntrypoint as CloudflareWorkflowEntrypoint,
|
|
7
3
|
type WorkflowEvent as CloudflareWorkflowEvent,
|
|
@@ -18,6 +14,7 @@ import {
|
|
|
18
14
|
Context,
|
|
19
15
|
Data,
|
|
20
16
|
Effect,
|
|
17
|
+
FiberSet,
|
|
21
18
|
Layer,
|
|
22
19
|
type ManagedRuntime,
|
|
23
20
|
Option,
|
|
@@ -44,9 +41,6 @@ export class WorkflowEvent extends Context.Service<WorkflowEvent, WorkflowEventS
|
|
|
44
41
|
"effect-cf/WorkflowEvent",
|
|
45
42
|
) {}
|
|
46
43
|
|
|
47
|
-
type RunWorkflowStepEffect = <A, E>(effect: Effect.Effect<A, E, never>) => Promise<A>;
|
|
48
|
-
|
|
49
|
-
/** Failure raised when a Cloudflare Workflow step operation rejects. */
|
|
50
44
|
export class WorkflowStepError extends Data.TaggedError("WorkflowStepError")<{
|
|
51
45
|
readonly step?: string;
|
|
52
46
|
readonly operation: string;
|
|
@@ -140,52 +134,52 @@ const exposeCloudflareNonRetryableError = <A, E, R>(
|
|
|
140
134
|
: Effect.failCause(cause);
|
|
141
135
|
});
|
|
142
136
|
|
|
143
|
-
const fromWorkflowStep = (
|
|
144
|
-
step: CloudflareWorkflowStep,
|
|
145
|
-
runPromise: RunWorkflowStepEffect,
|
|
146
|
-
): WorkflowStepService => ({
|
|
137
|
+
const fromWorkflowStep = (step: CloudflareWorkflowStep): WorkflowStepService => ({
|
|
147
138
|
raw: step,
|
|
148
139
|
do: <A, E, R>(name: string, effect: Effect.Effect<A, E, R>, config?: WorkflowStepConfig) =>
|
|
149
|
-
Effect.
|
|
150
|
-
Effect.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
do
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
140
|
+
Effect.gen(function* () {
|
|
141
|
+
const context = yield* Effect.context<Exclude<R, WorkflowStepContext>>();
|
|
142
|
+
|
|
143
|
+
return yield* Effect.scoped(
|
|
144
|
+
Effect.gen(function* () {
|
|
145
|
+
// Cloudflare owns retry timing and exposes no step cancellation API.
|
|
146
|
+
// Join the current callback on interruption and prevent later retry
|
|
147
|
+
// callbacks from starting, without waiting for native retry delays.
|
|
148
|
+
const runPromise = yield* FiberSet.makeRuntimePromise<never, A, E>();
|
|
149
|
+
|
|
150
|
+
return yield* Effect.tryPromise({
|
|
151
|
+
try: () => {
|
|
152
|
+
const run = (stepContext: CloudflareWorkflowStepContext) => {
|
|
153
|
+
const stepEffect: Effect.Effect<
|
|
154
|
+
A,
|
|
155
|
+
E,
|
|
156
|
+
Exclude<R, WorkflowStepContext>
|
|
157
|
+
> = Effect.scoped(Effect.provideService(effect, WorkflowStepContext, stepContext));
|
|
158
|
+
|
|
159
|
+
return runPromise(
|
|
160
|
+
exposeCloudflareNonRetryableError(Effect.provideContext(stepEffect, context)),
|
|
161
|
+
);
|
|
162
|
+
};
|
|
163
|
+
// SAFETY: these overloads reproduce the Cloudflare WorkflowStep.do runtime signatures used here.
|
|
164
|
+
const rawStep = step as {
|
|
165
|
+
do(
|
|
166
|
+
name: string,
|
|
167
|
+
callback: (context: CloudflareWorkflowStepContext) => Promise<A>,
|
|
168
|
+
): Promise<A>;
|
|
169
|
+
do(
|
|
170
|
+
name: string,
|
|
171
|
+
config: WorkflowStepConfig,
|
|
172
|
+
callback: (context: CloudflareWorkflowStepContext) => Promise<A>,
|
|
173
|
+
): Promise<A>;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return config === undefined ? rawStep.do(name, run) : rawStep.do(name, config, run);
|
|
177
|
+
},
|
|
178
|
+
catch: (cause) => new WorkflowStepError({ step: name, operation: "do", cause }),
|
|
179
|
+
});
|
|
186
180
|
}),
|
|
187
|
-
)
|
|
188
|
-
),
|
|
181
|
+
);
|
|
182
|
+
}),
|
|
189
183
|
sleep: (name, duration) =>
|
|
190
184
|
Effect.tryPromise({
|
|
191
185
|
try: () => step.sleep(name, duration),
|
|
@@ -268,10 +262,7 @@ export const make = <ROut, LayerError, Payload = unknown, Result = unknown>(
|
|
|
268
262
|
): Promise<Result> {
|
|
269
263
|
const workflowServices = Layer.mergeAll(
|
|
270
264
|
Layer.succeed(WorkflowEvent, fromWorkflowEvent(event)),
|
|
271
|
-
Layer.succeed(
|
|
272
|
-
WorkflowStep,
|
|
273
|
-
fromWorkflowStep(step, (effect) => this.runtime.runPromise(effect)),
|
|
274
|
-
),
|
|
265
|
+
Layer.succeed(WorkflowStep, fromWorkflowStep(step)),
|
|
275
266
|
);
|
|
276
267
|
|
|
277
268
|
return Runtime.runEventPromise(this.runtime, options.run(event.payload), workflowServices);
|
package/src/WorkflowBinding.ts
CHANGED
|
@@ -67,11 +67,8 @@ export interface WorkflowBindingDefinition<
|
|
|
67
67
|
Payload extends RpcDefinition.ServiceFreeSchema,
|
|
68
68
|
Result extends RpcDefinition.ServiceFreeSchema,
|
|
69
69
|
> {
|
|
70
|
-
/** Binding name as configured in `wrangler.jsonc`. */
|
|
71
70
|
readonly binding: string;
|
|
72
|
-
/** Codec used to encode payloads passed to `Workflow.create`. */
|
|
73
71
|
readonly payload: Payload;
|
|
74
|
-
/** Codec used to decode completed workflow status output. */
|
|
75
72
|
readonly result: Result;
|
|
76
73
|
}
|
|
77
74
|
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export * as QueueDefinition from "./QueueDefinition";
|
|
|
27
27
|
export * as R2 from "./R2";
|
|
28
28
|
export * as Rpc from "./Rpc";
|
|
29
29
|
export * as RpcDefinition from "./RpcDefinition";
|
|
30
|
+
export * as RpcTracing from "./RpcTracing";
|
|
30
31
|
export * as ServiceBinding from "./ServiceBinding";
|
|
31
32
|
export * as Vectorize from "./Vectorize";
|
|
32
33
|
export * as WebTransport from "./WebTransport";
|
|
@@ -1,26 +1,44 @@
|
|
|
1
1
|
import { Effect, Layer, Schema } from "effect";
|
|
2
2
|
|
|
3
3
|
import * as RpcDefinition from "../RpcDefinition";
|
|
4
|
+
import { RpcTraceContext, type ReceiverOptions, type RpcInvocationInfo } from "../RpcTracing";
|
|
5
|
+
import { CurrentInvocation } from "./RpcInvocation";
|
|
4
6
|
|
|
5
7
|
type AnyArgs = Array<any>;
|
|
6
8
|
type EntrypointRpcMethod = (...args: AnyArgs) => Effect.Effect<any, any, any>;
|
|
7
9
|
|
|
8
10
|
export type EntrypointRpc = Record<string, EntrypointRpcMethod>;
|
|
9
11
|
|
|
12
|
+
const isRpcTraceContext = Schema.is(RpcTraceContext);
|
|
13
|
+
|
|
10
14
|
const invokeEntrypointRpcMethod = <Self>(
|
|
11
15
|
self: Self,
|
|
12
16
|
method: EntrypointRpcMethod,
|
|
13
17
|
args: AnyArgs,
|
|
14
|
-
run: (self: Self, effect: Effect.Effect<any, any, any
|
|
18
|
+
run: (self: Self, effect: Effect.Effect<any, any, any>, rpc: RpcInvocationInfo) => Promise<any>,
|
|
15
19
|
onExit: ((self: Self) => Effect.Effect<void, never, any>) | undefined,
|
|
20
|
+
service: string,
|
|
21
|
+
key: string,
|
|
22
|
+
rpcTracing: ReceiverOptions | undefined,
|
|
16
23
|
): Promise<any> => {
|
|
17
|
-
const
|
|
24
|
+
const last = args.at(-1);
|
|
25
|
+
const parent = rpcTracing !== undefined && isRpcTraceContext(last) ? last : undefined;
|
|
26
|
+
const handlerArgs = parent === undefined ? args : args.slice(0, -1);
|
|
27
|
+
const invocation: CurrentInvocation["Service"] = {
|
|
28
|
+
service: rpcTracing?.service ?? service,
|
|
29
|
+
method: key,
|
|
30
|
+
args: handlerArgs,
|
|
31
|
+
parent,
|
|
32
|
+
};
|
|
33
|
+
const handler = Effect.suspend(() => method(...handlerArgs)).pipe(
|
|
34
|
+
Effect.provideService(CurrentInvocation, invocation),
|
|
18
35
|
Effect.mapError(RpcDefinition.encodeWireError),
|
|
19
36
|
);
|
|
20
37
|
|
|
21
38
|
return run(
|
|
22
39
|
self,
|
|
23
40
|
onExit === undefined ? handler : handler.pipe(Effect.onExit(() => onExit(self))),
|
|
41
|
+
invocation,
|
|
24
42
|
);
|
|
25
43
|
};
|
|
26
44
|
|
|
@@ -36,8 +54,9 @@ export const defineEntrypointRpcMethods = <Self, Prototype extends object = obje
|
|
|
36
54
|
prototype: Prototype,
|
|
37
55
|
rpc: EntrypointRpc | undefined,
|
|
38
56
|
reservedMethodNames: ReadonlySet<string>,
|
|
39
|
-
run: (self: Self, effect: Effect.Effect<any, any, any
|
|
57
|
+
run: (self: Self, effect: Effect.Effect<any, any, any>, rpc: RpcInvocationInfo) => Promise<any>,
|
|
40
58
|
onExit?: (self: Self) => Effect.Effect<void, never, any>,
|
|
59
|
+
rpcTracing?: ReceiverOptions,
|
|
41
60
|
): void => {
|
|
42
61
|
const methods = rpc ?? {};
|
|
43
62
|
|
|
@@ -47,7 +66,7 @@ export const defineEntrypointRpcMethods = <Self, Prototype extends object = obje
|
|
|
47
66
|
Object.defineProperty(prototype, key, {
|
|
48
67
|
enumerable: true,
|
|
49
68
|
value(this: Self, ...args: AnyArgs) {
|
|
50
|
-
return invokeEntrypointRpcMethod(this, method, args, run, onExit);
|
|
69
|
+
return invokeEntrypointRpcMethod(this, method, args, run, onExit, target, key, rpcTracing);
|
|
51
70
|
},
|
|
52
71
|
});
|
|
53
72
|
}
|
|
@@ -18,7 +18,6 @@ export const causeMessage = (cause: unknown): string => {
|
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
/** Renders a violation list as a single `path: message; ...` line. */
|
|
22
21
|
export const violationsMessage = (
|
|
23
22
|
violations: ReadonlyArray<{ readonly path: string; readonly message: string }>,
|
|
24
23
|
): string => violations.map((violation) => `${violation.path}: ${violation.message}`).join("; ");
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Effect, Exit, FiberSet } from "effect";
|
|
2
|
+
|
|
3
|
+
type RunCallback<A, E, R> = (effect: Effect.Effect<A, E, R>) => Promise<Exit.Exit<A, E>>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Runs an Effect callback owned by a native Promise operation.
|
|
7
|
+
*
|
|
8
|
+
* The callback keeps the caller's context, while a private scope owns its
|
|
9
|
+
* fiber. Closing that scope interrupts and joins the callback before awaiting
|
|
10
|
+
* the native operation's settlement.
|
|
11
|
+
*/
|
|
12
|
+
export const runNativeCallback = Effect.fnUntraced(function* <A, E, R, B>(
|
|
13
|
+
operation: (run: RunCallback<A, E, R>) => Promise<B>,
|
|
14
|
+
): Effect.fn.Return<B, unknown, R> {
|
|
15
|
+
const callerContext = yield* Effect.context<R>();
|
|
16
|
+
|
|
17
|
+
return yield* Effect.scoped(
|
|
18
|
+
Effect.gen(function* () {
|
|
19
|
+
let nativePromise: Promise<B> | undefined;
|
|
20
|
+
|
|
21
|
+
// Registered before the FiberSet so scope closure first interrupts and
|
|
22
|
+
// joins the callback, then waits for the native rollback/gate to settle.
|
|
23
|
+
yield* Effect.addFinalizer(() => {
|
|
24
|
+
const promise = nativePromise;
|
|
25
|
+
|
|
26
|
+
return promise === undefined
|
|
27
|
+
? Effect.void
|
|
28
|
+
: Effect.promise(() =>
|
|
29
|
+
promise.then(
|
|
30
|
+
() => undefined,
|
|
31
|
+
() => undefined,
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
const runPromise = yield* FiberSet.makeRuntimePromise<never, Exit.Exit<A, E>, never>();
|
|
36
|
+
|
|
37
|
+
return yield* Effect.callback<B, unknown>((resume) => {
|
|
38
|
+
try {
|
|
39
|
+
nativePromise = operation((effect) =>
|
|
40
|
+
runPromise(Effect.provideContext(Effect.exit(effect), callerContext)),
|
|
41
|
+
);
|
|
42
|
+
} catch (cause) {
|
|
43
|
+
resume(Effect.fail(cause));
|
|
44
|
+
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
nativePromise.then(
|
|
49
|
+
(value) => resume(Effect.succeed(value)),
|
|
50
|
+
(cause) => resume(Effect.fail(cause)),
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
});
|
|
@@ -1,9 +1,26 @@
|
|
|
1
|
-
import { Effect, Predicate, Schema } from "effect";
|
|
1
|
+
import { Context, Effect, Option, Predicate, Schema } from "effect";
|
|
2
2
|
|
|
3
3
|
import type * as CloudflareRpc from "../Rpc";
|
|
4
|
+
import type { RpcInvocationInfo } from "../RpcTracing";
|
|
4
5
|
|
|
5
6
|
type AnyArgs = Array<any>;
|
|
6
7
|
|
|
8
|
+
interface Invocation extends RpcInvocationInfo {
|
|
9
|
+
decodedArgs?: ReadonlyArray<unknown>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Scoped to the incoming event effect, never the instance runtime or storage. */
|
|
13
|
+
export class CurrentInvocation extends Context.Service<CurrentInvocation, Invocation>()(
|
|
14
|
+
"effect-cf/internal/RpcInvocation",
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
export const recordDecodedArgs = (args: ReadonlyArray<unknown>): Effect.Effect<void> =>
|
|
18
|
+
Effect.map(Effect.serviceOption(CurrentInvocation), (invocation) => {
|
|
19
|
+
if (Option.isSome(invocation)) {
|
|
20
|
+
invocation.value.decodedArgs = args;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
7
24
|
export type AsyncMethodKey<Api> = {
|
|
8
25
|
[Key in keyof Api]-?: Key extends string
|
|
9
26
|
? Api[Key] extends (...args: AnyArgs) => Promise<any>
|
package/src/internal/Runtime.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigProvider, Effect, Layer, ManagedRuntime, type Scope } from "effect";
|
|
1
|
+
import { ConfigProvider, Effect, Layer, ManagedRuntime, type Scope, type Tracer } from "effect";
|
|
2
2
|
|
|
3
3
|
import { WorkerConfig, WorkerEnvironment, type WorkerEnv } from "../Environment";
|
|
4
4
|
import { provideEntrypointServices } from "./Entrypoint";
|
|
@@ -26,17 +26,18 @@ export const makeEntrypointRuntime = <ROut, LayerError, Services>(
|
|
|
26
26
|
return ManagedRuntime.make(provideEntrypointServices(layer, entrypointServices));
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
/** Runs an event effect whose requirements are already available in the runtime. */
|
|
30
29
|
export function runEventPromise<A, E, R, LayerError>(
|
|
31
30
|
runtime: ManagedRuntime.ManagedRuntime<R, LayerError>,
|
|
32
31
|
effect: Effect.Effect<A, E, NoInfer<R> | Scope.Scope>,
|
|
33
32
|
eventLayer?: undefined,
|
|
33
|
+
parent?: Tracer.AnySpan,
|
|
34
34
|
): Promise<A>;
|
|
35
35
|
/** Builds and provides an event layer inside the event effect's scope. */
|
|
36
36
|
export function runEventPromise<A, E, R, REvent, EventLayerError, LayerError>(
|
|
37
37
|
runtime: ManagedRuntime.ManagedRuntime<R, LayerError>,
|
|
38
38
|
effect: Effect.Effect<A, E, NoInfer<R> | REvent | Scope.Scope>,
|
|
39
39
|
eventLayer: Layer.Layer<REvent, EventLayerError, NoInfer<R>>,
|
|
40
|
+
parent?: Tracer.AnySpan,
|
|
40
41
|
): Promise<A>;
|
|
41
42
|
export function runEventPromise<A, E, R, REvent, EventLayerError, LayerError>(
|
|
42
43
|
...args:
|
|
@@ -44,20 +45,24 @@ export function runEventPromise<A, E, R, REvent, EventLayerError, LayerError>(
|
|
|
44
45
|
runtime: ManagedRuntime.ManagedRuntime<R, LayerError>,
|
|
45
46
|
effect: Effect.Effect<A, E, R | Scope.Scope>,
|
|
46
47
|
eventLayer?: undefined,
|
|
48
|
+
parent?: Tracer.AnySpan,
|
|
47
49
|
]
|
|
48
50
|
| readonly [
|
|
49
51
|
runtime: ManagedRuntime.ManagedRuntime<R, LayerError>,
|
|
50
52
|
effect: Effect.Effect<A, E, R | REvent | Scope.Scope>,
|
|
51
53
|
eventLayer: Layer.Layer<REvent, EventLayerError, R>,
|
|
54
|
+
parent?: Tracer.AnySpan,
|
|
52
55
|
]
|
|
53
56
|
): Promise<A> {
|
|
54
|
-
const [runtime, effect, eventLayer] = args;
|
|
57
|
+
const [runtime, effect, eventLayer, parent] = args;
|
|
55
58
|
|
|
56
59
|
if (eventLayer === undefined) {
|
|
57
|
-
|
|
60
|
+
const event = Effect.scoped(effect);
|
|
61
|
+
|
|
62
|
+
return runtime.runPromise(parent === undefined ? event : Effect.withParentSpan(event, parent));
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
);
|
|
65
|
+
const event = Effect.scoped(effect.pipe(Effect.provide(eventLayer, { local: true })));
|
|
66
|
+
|
|
67
|
+
return runtime.runPromise(parent === undefined ? event : Effect.withParentSpan(event, parent));
|
|
63
68
|
}
|
|
@@ -17,7 +17,9 @@ const failureHandler = <E, R>(
|
|
|
17
17
|
cause: Cause.Cause<E>,
|
|
18
18
|
options: WorkerContextWaitUntilOptions<E, R> | undefined,
|
|
19
19
|
) =>
|
|
20
|
-
|
|
20
|
+
Effect.suspend(
|
|
21
|
+
() => options?.onFailure?.(cause) ?? Effect.logError(`${label} failed`, Cause.pretty(cause)),
|
|
22
|
+
).pipe(
|
|
21
23
|
Effect.catchCause((handlerCause) =>
|
|
22
24
|
Effect.logError(
|
|
23
25
|
`${label} failure handler failed`,
|
|
@@ -27,14 +29,6 @@ const failureHandler = <E, R>(
|
|
|
27
29
|
),
|
|
28
30
|
);
|
|
29
31
|
|
|
30
|
-
/**
|
|
31
|
-
* Builds a `waitUntil` scheduler for any Cloudflare lifecycle that accepts
|
|
32
|
-
* background promises (`ExecutionContext`, `DurableObjectState`).
|
|
33
|
-
*
|
|
34
|
-
* Background effects capture the calling fiber's context via `Effect.context`
|
|
35
|
-
* before being registered, so the default module-level `Effect.runPromiseExit`
|
|
36
|
-
* runner is sufficient; entrypoints may still pass a runtime-bound runner.
|
|
37
|
-
*/
|
|
38
32
|
export const makeWaitUntilScheduler = (
|
|
39
33
|
label: string,
|
|
40
34
|
register: (promise: Promise<unknown>) => void,
|
|
@@ -50,7 +44,7 @@ export const makeWaitUntilScheduler = (
|
|
|
50
44
|
Effect.sync(() => {
|
|
51
45
|
const runHandler = (cause: Cause.Cause<E>) =>
|
|
52
46
|
runPromiseExit(
|
|
53
|
-
Effect.
|
|
47
|
+
Effect.provideContext(Effect.scoped(failureHandler(label, cause, options)), context),
|
|
54
48
|
).then((exit) => {
|
|
55
49
|
if (Exit.isFailure(exit)) {
|
|
56
50
|
console.error(`${label} failure handler failed`, Cause.pretty(exit.cause));
|
|
@@ -58,7 +52,7 @@ export const makeWaitUntilScheduler = (
|
|
|
58
52
|
});
|
|
59
53
|
|
|
60
54
|
register(
|
|
61
|
-
runPromiseExit(Effect.
|
|
55
|
+
runPromiseExit(Effect.provideContext(Effect.scoped(effect), context)).then(
|
|
62
56
|
async (exit) => {
|
|
63
57
|
if (Exit.isSuccess(exit)) {
|
|
64
58
|
return;
|
|
@@ -77,9 +71,6 @@ export const makeWaitUntilScheduler = (
|
|
|
77
71
|
);
|
|
78
72
|
};
|
|
79
73
|
|
|
80
|
-
/**
|
|
81
|
-
* Builds the `WorkerContext` service from a native `ExecutionContext`.
|
|
82
|
-
*/
|
|
83
74
|
export const fromExecutionContext = (
|
|
84
75
|
ctx: globalThis.ExecutionContext,
|
|
85
76
|
runPromiseExit: RunWaitUntilEffect = (effect) => Effect.runPromiseExit(effect),
|