effect-cf 0.53.0 → 0.54.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/README.md +6 -0
- package/dist/DurableObject.d.mts +1 -0
- package/dist/DurableObject.mjs +33 -11
- package/dist/DurableObjectAlarm.d.mts +74 -9
- package/dist/DurableObjectAlarm.mjs +245 -35
- package/dist/RateLimit.d.mts +50 -0
- package/dist/RateLimit.mjs +46 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/dist/internal/Runtime.mjs +5 -3
- package/package.json +1 -1
- package/src/DurableObject.ts +93 -30
- package/src/DurableObjectAlarm.ts +601 -59
- package/src/RateLimit.ts +110 -0
- package/src/index.ts +1 -0
- package/src/internal/Entrypoint.ts +8 -4
- package/src/internal/Runtime.ts +12 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# effect-cf
|
|
2
2
|
|
|
3
|
+
## 0.54.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#208](https://github.com/danieljvdm/effect-cf/pull/208) [`be9befa`](https://github.com/danieljvdm/effect-cf/commit/be9befaf7e07cdfff2a5c92e886065725edf90e6) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add an Effect-native RateLimit binding client with service layers, native admission outcomes, and typed operation errors preserving the original cause.
|
|
8
|
+
|
|
9
|
+
- [#210](https://github.com/danieljvdm/effect-cf/pull/210) [`abcdb42`](https://github.com/danieljvdm/effect-cf/commit/abcdb4204b3b32d7e979f449e36d9727693e5d73) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Compose typed alarm services with `DurableObjectAlarm.mergeAll` under one native Durable Object alarm owner. Use `lifecycle: "manual"` for queues that own completion and retry policy, and `deferWakes` to coalesce native alarm changes during processing while retaining durable recovery.
|
|
10
|
+
|
|
11
|
+
Enable `ScheduleConfiguration.dispatchAfterEvent` to dispatch due alarms after RPC/fetch responses unwind, using the same scoped pass as native delivery. Overlapping native alarms join the pass, deferred regions delay dispatch, and durable native scheduling retains recovery authority. Cold Objects can deliver responses later because post-response processing shares the same CPU.
|
|
12
|
+
|
|
3
13
|
## 0.53.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -220,6 +220,12 @@ Applications own SERVER spans. Override the exported `DurableObject.RunSymbol` o
|
|
|
220
220
|
|
|
221
221
|
This metadata belongs only to the live native call. Do not store it in domain envelopes, alarms, queues, or WebSocket attachments, or reuse it for resumed work. Sampling and exporter configuration remain application choices.
|
|
222
222
|
|
|
223
|
+
## Native rate limiting
|
|
224
|
+
|
|
225
|
+
Use `RateLimit.Tag` or `RateLimit.make` to call a native binding as an Effect:
|
|
226
|
+
`yield* requests.limit({ key })` returns `{ success }`, including ordinary denial.
|
|
227
|
+
See [binding configuration and usage](../../docs/rate-limiting.md).
|
|
228
|
+
|
|
223
229
|
## API
|
|
224
230
|
|
|
225
231
|
See the [exports](src/index.ts) and [tests](https://github.com/danieljvdm/effect-cf/tree/main/packages/effect-cf/tests) for the remaining APIs.
|
package/dist/DurableObject.d.mts
CHANGED
|
@@ -94,6 +94,7 @@ type DurableObjectOptions<RRuntime, REvent = never, EventLayerError = never, Rpc
|
|
|
94
94
|
* Cloudflare `DurableObject` constructor produced by {@link make}.
|
|
95
95
|
*/
|
|
96
96
|
type DurableObjectClass<Rpc extends DurableObjectRpc<ROut>, ROut> = new (state: globalThis.DurableObjectState, env: WorkerEnv) => DurableObject<WorkerEnv> & DurableObjectRpcApi<Rpc, ROut> & {
|
|
97
|
+
alarm(alarmInfo?: globalThis.AlarmInvocationInfo): Promise<void> | void;
|
|
97
98
|
[RunSymbol]<A, E>(effect: Effect.Effect<A, E, HandlerContext<ROut>>, options?: RunOptions): Promise<A>;
|
|
98
99
|
};
|
|
99
100
|
/**
|
package/dist/DurableObject.mjs
CHANGED
|
@@ -3,10 +3,10 @@ import { fromWebSocket } from "./DurableObjectWebSocket.mjs";
|
|
|
3
3
|
import { DurableObjectState, fromDurableObjectState } from "./DurableObjectState.mjs";
|
|
4
4
|
import { reservedMethodNames as reservedMethodNames$1 } from "./RpcDefinition.mjs";
|
|
5
5
|
import { assumeEntrypointClass, defineEntrypointRpcMethods } from "./internal/Entrypoint.mjs";
|
|
6
|
-
import { makeEntrypointRuntime, runEventPromise } from "./internal/Runtime.mjs";
|
|
6
|
+
import { makeEntrypointRuntime, runEventPromise, scopeEvent } from "./internal/Runtime.mjs";
|
|
7
7
|
import { scheduleTelemetryFlush as scheduleTelemetryFlush$1 } from "./internal/Telemetry.mjs";
|
|
8
8
|
import { NativeRequest } from "./Worker.mjs";
|
|
9
|
-
import { DurableObjectAlarm } from "./DurableObjectAlarm.mjs";
|
|
9
|
+
import { DispatchAfterEvent, DurableObjectAlarm, HasDueAlarms, RunAlarm, dispatchRawAlarm } from "./DurableObjectAlarm.mjs";
|
|
10
10
|
import { Tag, implement, method, native } from "./DurableObjectDefinition.mjs";
|
|
11
11
|
import * as Effect from "effect/Effect";
|
|
12
12
|
import * as Layer from "effect/Layer";
|
|
@@ -28,7 +28,7 @@ const RunSymbol = Symbol.for("effect-cf/DurableObject/run");
|
|
|
28
28
|
const scheduleTelemetryFlush = scheduleTelemetryFlush$1((flush) => Effect.flatMap(DurableObjectState, (state) => state.waitUntil(flush)));
|
|
29
29
|
function make(layer, options = {}) {
|
|
30
30
|
const registration = options.alarms !== void 0 && !Effect.isEffect(options.alarms) ? options.alarms : void 0;
|
|
31
|
-
const
|
|
31
|
+
const legacyAlarms = Effect.isEffect(options.alarms) ? options.alarms.pipe(Effect.asVoid) : void 0;
|
|
32
32
|
class EffectDurableObject extends DurableObject {
|
|
33
33
|
runtime;
|
|
34
34
|
constructor(state, env) {
|
|
@@ -46,8 +46,18 @@ function make(layer, options = {}) {
|
|
|
46
46
|
const eventLayer = runOptions.eventLayer === false ? void 0 : options.eventLayer;
|
|
47
47
|
const parent = runOptions.rpc?.parent;
|
|
48
48
|
const parentSpan = parent === void 0 ? void 0 : Tracer.externalSpan(parent);
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const afterResponse = runOptions.event === "rpc" || runOptions.event === "fetch";
|
|
50
|
+
let dispatchAfterEvent = false;
|
|
51
|
+
const handler = afterResponse ? effect.pipe(Effect.onExit(() => Effect.flatMap(DurableObjectAlarm, (alarms) => Effect.map(alarms[DispatchAfterEvent], (enabled) => {
|
|
52
|
+
dispatchAfterEvent = enabled;
|
|
53
|
+
})))) : effect;
|
|
54
|
+
let response;
|
|
55
|
+
if (eventLayer === void 0) response = runEventPromise(this.runtime, handler, void 0, parentSpan, runOptions.onFailure);
|
|
56
|
+
else response = runEventPromise(this.runtime, handler, eventLayer, parentSpan, runOptions.onFailure);
|
|
57
|
+
if (!afterResponse) return response;
|
|
58
|
+
return response.finally(() => {
|
|
59
|
+
if (dispatchAfterEvent) this.ctx.waitUntil(Effect.runPromise(Effect.yieldNow.pipe(Effect.andThen(Effect.promise(() => this.#runAlarm(false))))));
|
|
60
|
+
});
|
|
51
61
|
}
|
|
52
62
|
fetch(request) {
|
|
53
63
|
const fetchHandler = options.fetch;
|
|
@@ -55,12 +65,24 @@ function make(layer, options = {}) {
|
|
|
55
65
|
return this[RunSymbol](Effect.provideService(fetchHandler, NativeRequest, request), { event: "fetch" });
|
|
56
66
|
}
|
|
57
67
|
alarm(alarmInfo) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
return this.#runAlarm(true, alarmInfo);
|
|
69
|
+
}
|
|
70
|
+
#runAlarm(native, alarmInfo) {
|
|
71
|
+
const event = (beginDispatch) => {
|
|
72
|
+
const alarmEffect = Effect.gen(function* () {
|
|
73
|
+
const alarms = yield* DurableObjectAlarm;
|
|
74
|
+
if (!native && !(yield* alarms[HasDueAlarms])) return;
|
|
75
|
+
const rawAlarm = options.alarm?.(alarmInfo);
|
|
76
|
+
const customAlarm = legacyAlarms === void 0 ? rawAlarm ?? Effect.void : legacyAlarms.pipe(Effect.andThen(rawAlarm ?? Effect.void));
|
|
77
|
+
yield* beginDispatch;
|
|
78
|
+
yield* registration === void 0 || rawAlarm !== void 0 ? dispatchRawAlarm(customAlarm, registration) : registration.run.pipe(Effect.asVoid);
|
|
79
|
+
}).pipe(Effect.onExit(() => scheduleTelemetryFlush));
|
|
80
|
+
return scopeEvent(options.eventLayer === void 0 ? alarmEffect : alarmEffect.pipe(Effect.provide(options.eventLayer, { local: true })));
|
|
81
|
+
};
|
|
82
|
+
return this[RunSymbol](Effect.flatMap(DurableObjectAlarm, (alarms) => alarms[RunAlarm](event, native)), {
|
|
83
|
+
event: "alarm",
|
|
84
|
+
eventLayer: false
|
|
85
|
+
});
|
|
64
86
|
}
|
|
65
87
|
webSocketMessage(socket, message) {
|
|
66
88
|
if (options.webSocketMessage !== void 0) return this[RunSymbol](options.webSocketMessage(fromWebSocket(socket), message), { event: "webSocketMessage" });
|
|
@@ -7,7 +7,7 @@ import * as Layer from "effect/Layer";
|
|
|
7
7
|
import * as Duration from "effect/Duration";
|
|
8
8
|
import * as DateTime from "effect/DateTime";
|
|
9
9
|
declare namespace DurableObjectAlarm_d_exports {
|
|
10
|
-
export { AlarmDefinitionConfig, AlarmDefinitionEntry, AlarmDefinitionPayload, AlarmDefinitions, AlarmFailurePolicy, AlarmParked, AlarmPayload, AlarmPayloadSchema, AlarmRef, AlarmRegistration, AlarmReporter, AlarmRetryPolicy, AlarmScheduler, AlarmService, AlarmStatus, AlarmTagClass, AlarmTransaction, DEFAULT_MIN_REPEAT_INTERVAL_MS, DefinedAlarmEvent, DefinedAlarmHandlers, DefinedAlarmScheduler, DefinedAlarmTransaction, DefinedScheduleAlarmInput, DurableObjectAlarm, DurableObjectAlarmError, DurableObjectAlarmEvent, InvalidAlarmPayloadError, InvalidAlarmRefError, InvalidProcessDueAlarmsOptionsError, InvalidRepeatEveryError, InvalidScheduleConfigurationError, MIN_REPEAT_INTERVAL_MS, MIN_RETRY_DELAY_MS, PARKED_RETRY_DELAY_MS, ProcessDueAlarmsFailure, ProcessDueAlarmsFailureAction, ProcessDueAlarmsHandler, ProcessDueAlarmsOptions, ProcessDueAlarmsResult, ScheduleAlarmInput, ScheduleConfiguration, StoredAlarmDecodeError, Tag, UNCHANGED_ATTEMPT_BUDGET, define, processDue };
|
|
10
|
+
export { AlarmDefinitionConfig, AlarmDefinitionEntry, AlarmDefinitionPayload, AlarmDefinitions, AlarmFailurePolicy, AlarmLifecycle, AlarmParked, AlarmPayload, AlarmPayloadSchema, AlarmRef, AlarmRegistration, AlarmReporter, AlarmRetryPolicy, AlarmScheduler, AlarmService, AlarmStatus, AlarmTagClass, AlarmTransaction, DEFAULT_MIN_REPEAT_INTERVAL_MS, DefinedAlarmEvent, DefinedAlarmHandlers, DefinedAlarmScheduler, DefinedAlarmTransaction, DefinedScheduleAlarmInput, DispatchAfterEvent, DurableObjectAlarm, DurableObjectAlarmError, DurableObjectAlarmEvent, HasDueAlarms, InvalidAlarmPayloadError, InvalidAlarmRefError, InvalidAlarmRegistrationError, InvalidProcessDueAlarmsOptionsError, InvalidRepeatEveryError, InvalidScheduleConfigurationError, MIN_REPEAT_INTERVAL_MS, MIN_RETRY_DELAY_MS, PARKED_RETRY_DELAY_MS, ProcessDueAlarmsFailure, ProcessDueAlarmsFailureAction, ProcessDueAlarmsHandler, ProcessDueAlarmsOptions, ProcessDueAlarmsResult, RunAlarm, ScheduleAlarmInput, ScheduleConfiguration, StoredAlarmDecodeError, Tag, UNCHANGED_ATTEMPT_BUDGET, define, dispatchRawAlarm, mergeAll, processDue };
|
|
11
11
|
}
|
|
12
12
|
declare const MIN_RETRY_DELAY_MS = 1000;
|
|
13
13
|
/** Default unchanged-attempt budget. */
|
|
@@ -19,6 +19,8 @@ declare const MIN_REPEAT_INTERVAL_MS = 1000;
|
|
|
19
19
|
/** Default product schedule floor. Never use repeats to poll state. */
|
|
20
20
|
declare const DEFAULT_MIN_REPEAT_INTERVAL_MS = 60000;
|
|
21
21
|
interface ScheduleConfiguration {
|
|
22
|
+
/** Check for due alarms after RPC/fetch responses unwind. Native alarms remain recovery authority. */
|
|
23
|
+
readonly dispatchAfterEvent?: boolean;
|
|
22
24
|
/** Retry floor, at least one second. Defaults to one second. */
|
|
23
25
|
readonly minimumRetryDelay?: Duration.Input;
|
|
24
26
|
/** Positive safe integer. Defaults to eight unchanged attempts. */
|
|
@@ -30,6 +32,8 @@ interface ScheduleConfiguration {
|
|
|
30
32
|
}
|
|
31
33
|
/** Optional policy overrides. Provide with Layer.succeed in the Durable Object's application layer. */
|
|
32
34
|
declare const ScheduleConfiguration: Context.Reference<ScheduleConfiguration>;
|
|
35
|
+
/** Automatic alarms acknowledge/retry on handler exit; manual alarms retain consumer control. */
|
|
36
|
+
type AlarmLifecycle = "automatic" | "manual";
|
|
33
37
|
type AlarmPayload = S.Json;
|
|
34
38
|
/** Content-free: no alarm identifiers, payload, error text or consumer state. */
|
|
35
39
|
declare const AlarmParked: S.TaggedStruct<"AlarmParked", {
|
|
@@ -39,6 +43,7 @@ declare const AlarmParked: S.TaggedStruct<"AlarmParked", {
|
|
|
39
43
|
type AlarmParked = typeof AlarmParked.Type;
|
|
40
44
|
/** Install with Layer.succeed / Effect.provideService. Reporting cannot undo a committed guard. */
|
|
41
45
|
declare const AlarmReporter: Context.Reference<(event: AlarmParked) => Effect.Effect<void>>;
|
|
46
|
+
declare const ManualTags: unique symbol;
|
|
42
47
|
declare const InvalidAlarmRefError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
43
48
|
readonly _tag: "InvalidAlarmRefError";
|
|
44
49
|
} & Readonly<A>;
|
|
@@ -79,6 +84,14 @@ declare class InvalidScheduleConfigurationError extends InvalidScheduleConfigura
|
|
|
79
84
|
}> {
|
|
80
85
|
get message(): string;
|
|
81
86
|
}
|
|
87
|
+
declare const InvalidAlarmRegistrationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
88
|
+
readonly _tag: "InvalidAlarmRegistrationError";
|
|
89
|
+
} & Readonly<A>;
|
|
90
|
+
declare class InvalidAlarmRegistrationError extends InvalidAlarmRegistrationError_base<{
|
|
91
|
+
readonly cause: unknown;
|
|
92
|
+
}> {
|
|
93
|
+
get message(): string;
|
|
94
|
+
}
|
|
82
95
|
declare const StoredAlarmDecodeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
83
96
|
readonly _tag: "StoredAlarmDecodeError";
|
|
84
97
|
} & Readonly<A>;
|
|
@@ -88,7 +101,7 @@ declare class StoredAlarmDecodeError extends StoredAlarmDecodeError_base<{
|
|
|
88
101
|
}> {
|
|
89
102
|
get message(): string;
|
|
90
103
|
}
|
|
91
|
-
type DurableObjectAlarmError = InvalidAlarmPayloadError | InvalidAlarmRefError | InvalidProcessDueAlarmsOptionsError | InvalidRepeatEveryError | InvalidScheduleConfigurationError | StorageOperationError | StoredAlarmDecodeError;
|
|
104
|
+
type DurableObjectAlarmError = InvalidAlarmRegistrationError | InvalidAlarmPayloadError | InvalidAlarmRefError | InvalidProcessDueAlarmsOptionsError | InvalidRepeatEveryError | InvalidScheduleConfigurationError | StorageOperationError | StoredAlarmDecodeError;
|
|
92
105
|
declare const DurableObjectAlarmEvent: S.TaggedUnion<{
|
|
93
106
|
readonly AlarmDue: S.TaggedStruct<"AlarmDue", {
|
|
94
107
|
readonly id: S.NonEmptyString;
|
|
@@ -108,6 +121,8 @@ type AlarmRef<Tag extends string = string> = {
|
|
|
108
121
|
* Reusing `{tag, id}` replaces an alarm. Product repeats use the configured floor and run after completion.
|
|
109
122
|
*/
|
|
110
123
|
type ScheduleAlarmInput<Tag extends string = string> = AlarmRef<Tag> & {
|
|
124
|
+
/** Prefer selecting the lifecycle in a typed Tag definition. Defaults to automatic. */
|
|
125
|
+
readonly lifecycle?: AlarmLifecycle;
|
|
111
126
|
readonly payload: AlarmPayload;
|
|
112
127
|
readonly repeatEvery?: Duration.Input;
|
|
113
128
|
readonly runAt: DateTime.Utc;
|
|
@@ -133,6 +148,7 @@ type ProcessDueAlarmsFailureAction = "retry" | "skip-and-advance-repeat" | {
|
|
|
133
148
|
readonly mode: "skip-and-advance-repeat";
|
|
134
149
|
};
|
|
135
150
|
interface ProcessDueAlarmsOptions<OnFailureR = never, OnFailureE = never> {
|
|
151
|
+
readonly [ManualTags]?: ReadonlySet<string>;
|
|
136
152
|
readonly limit?: number;
|
|
137
153
|
readonly onFailure?: (failure: ProcessDueAlarmsFailure) => Effect.Effect<ProcessDueAlarmsFailureAction | void, OnFailureE, OnFailureR>;
|
|
138
154
|
readonly retryFailedAfter?: Duration.Input;
|
|
@@ -149,8 +165,29 @@ interface AlarmStatus {
|
|
|
149
165
|
readonly runAt: DateTime.Utc;
|
|
150
166
|
readonly retryAt: DateTime.Utc | undefined;
|
|
151
167
|
}
|
|
168
|
+
/** @internal */
|
|
169
|
+
declare const RunAlarm: unique symbol;
|
|
170
|
+
/** @internal */
|
|
171
|
+
declare const DispatchAfterEvent: unique symbol;
|
|
172
|
+
/** @internal */
|
|
173
|
+
declare const HasDueAlarms: unique symbol;
|
|
152
174
|
/** Own `storage.setAlarm()` exclusively: a Durable Object has one platform alarm timestamp. */
|
|
153
175
|
type AlarmScheduler = {
|
|
176
|
+
/** @internal DurableObject.make shares this scoped event across native and post-event dispatch. */
|
|
177
|
+
readonly [RunAlarm]: <R>(event: (beginDispatch: Effect.Effect<void, InvalidScheduleConfigurationError>) => Effect.Effect<void, unknown, R>, native: boolean) => Effect.Effect<void, unknown, R>;
|
|
178
|
+
/** @internal Read the current event's opt-in without acquiring another event layer. */
|
|
179
|
+
readonly [DispatchAfterEvent]: Effect.Effect<boolean>;
|
|
180
|
+
/** @internal Check inside the alarm event so its clock and configuration apply. */
|
|
181
|
+
readonly [HasDueAlarms]: Effect.Effect<boolean, StorageOperationError>;
|
|
182
|
+
/**
|
|
183
|
+
* Keep a native recovery alarm armed while coalescing checkpoint changes across this
|
|
184
|
+
* object's concurrent and nested scopes. Source/checkpoint transactions still commit;
|
|
185
|
+
* the last scope reconciles their current deadlines on success, failure or interruption.
|
|
186
|
+
* Run outside transactions, around bounded maintenance or inline work. The first scope's
|
|
187
|
+
* parkedRetryDelay bounds the shared guard; renew it if it expires and is consumed while
|
|
188
|
+
* scopes remain active. A process loss before exit recovers at that retained alarm.
|
|
189
|
+
*/
|
|
190
|
+
readonly deferWakes: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E | InvalidScheduleConfigurationError | StorageOperationError, R>;
|
|
154
191
|
/**
|
|
155
192
|
* Commits local application storage and logical alarms in one native SQLite
|
|
156
193
|
* Durable Object transaction, reconciling the native alarm before commit.
|
|
@@ -183,11 +220,17 @@ type AlarmFailurePolicy = "retry" | "skip-and-advance-repeat";
|
|
|
183
220
|
interface AlarmRetryPolicy {
|
|
184
221
|
readonly initialDelay?: Duration.Input;
|
|
185
222
|
}
|
|
186
|
-
|
|
187
|
-
readonly failure?: AlarmFailurePolicy;
|
|
223
|
+
type AlarmDefinitionConfig<Payload extends AlarmPayloadSchema = AlarmPayloadSchema> = {
|
|
188
224
|
readonly payload: Payload;
|
|
225
|
+
} & ({
|
|
226
|
+
readonly lifecycle?: "automatic";
|
|
227
|
+
readonly failure?: AlarmFailurePolicy;
|
|
189
228
|
readonly retry?: AlarmRetryPolicy;
|
|
190
|
-
}
|
|
229
|
+
} | {
|
|
230
|
+
readonly lifecycle: "manual";
|
|
231
|
+
readonly failure?: never;
|
|
232
|
+
readonly retry?: never;
|
|
233
|
+
});
|
|
191
234
|
type AlarmDefinitionEntry = AlarmDefinitionConfig | AlarmPayloadSchema;
|
|
192
235
|
type AlarmDefinitions = Readonly<Record<string, AlarmDefinitionEntry>>;
|
|
193
236
|
type AlarmDefinitionSchema<Definition> = Definition extends AlarmDefinitionConfig<infer Payload> ? Payload : Definition;
|
|
@@ -198,9 +241,14 @@ type DefinedAlarmEvent<Tag extends string, Payload> = Omit<DurableObjectAlarmEve
|
|
|
198
241
|
};
|
|
199
242
|
type DefinedAlarmHandlers<Definitions extends AlarmDefinitions, R = never, E = never> = { readonly [Tag in keyof Definitions & string]: (event: DefinedAlarmEvent<Tag, AlarmDefinitionPayload<Definitions[Tag]>>) => Effect.Effect<void, E, R>; };
|
|
200
243
|
/** A discriminated union keeps each tag paired with its decoded payload type. */
|
|
201
|
-
type DefinedScheduleAlarmInput<Definitions extends AlarmDefinitions> = { readonly [Tag in keyof Definitions & string]: Omit<ScheduleAlarmInput<Tag>, "payload"> & {
|
|
244
|
+
type DefinedScheduleAlarmInput<Definitions extends AlarmDefinitions> = { readonly [Tag in keyof Definitions & string]: Omit<ScheduleAlarmInput<Tag>, "payload" | "lifecycle" | "repeatEvery" | "progress"> & {
|
|
202
245
|
readonly payload: AlarmDefinitionPayload<Definitions[Tag]>;
|
|
203
|
-
}
|
|
246
|
+
} & (Definitions[Tag] extends {
|
|
247
|
+
readonly lifecycle: "manual";
|
|
248
|
+
} ? {
|
|
249
|
+
readonly repeatEvery?: never;
|
|
250
|
+
readonly progress?: never;
|
|
251
|
+
} : Pick<ScheduleAlarmInput<Tag>, "repeatEvery" | "progress">); }[keyof Definitions & string];
|
|
204
252
|
interface DefinedAlarmTransaction<Definitions extends AlarmDefinitions> {
|
|
205
253
|
readonly scheduleAlarm: (input: DefinedScheduleAlarmInput<Definitions>) => ReturnType<AlarmScheduler["scheduleAlarm"]>;
|
|
206
254
|
readonly scheduleAlarmEarlier: DefinedAlarmTransaction<Definitions>["scheduleAlarm"];
|
|
@@ -215,14 +263,29 @@ interface AlarmService {
|
|
|
215
263
|
}
|
|
216
264
|
interface DefinedAlarmScheduler<Definitions extends AlarmDefinitions> extends DefinedAlarmTransaction<Definitions> {
|
|
217
265
|
readonly [TypedAlarmSchedulerTypeId]: typeof TypedAlarmSchedulerTypeId;
|
|
266
|
+
readonly deferWakes: AlarmScheduler["deferWakes"];
|
|
218
267
|
readonly getAlarmStatus: (input: AlarmRef<keyof Definitions & string>) => ReturnType<AlarmScheduler["getAlarmStatus"]>;
|
|
219
268
|
readonly transaction: <A, E, R>(closure: (alarms: DefinedAlarmTransaction<Definitions>) => Effect.Effect<A, E, R>) => Effect.Effect<A, E | StorageOperationError, R>;
|
|
220
269
|
}
|
|
221
270
|
/** Registers a dispatcher and the service authorized to schedule its alarms. */
|
|
222
271
|
interface AlarmRegistration<Self, R = never, E = never> {
|
|
223
|
-
readonly layer: Layer.Layer<Self,
|
|
272
|
+
readonly layer: Layer.Layer<Self, InvalidAlarmRegistrationError, DurableObjectAlarm>;
|
|
224
273
|
readonly run: Effect.Effect<ProcessDueAlarmsResult, E | DurableObjectAlarmError, R | DurableObjectAlarm>;
|
|
274
|
+
readonly [RegistrationParts]?: RegistrationParts<R, E>;
|
|
275
|
+
}
|
|
276
|
+
declare const RegistrationParts: unique symbol;
|
|
277
|
+
interface AlarmDispatcher<R, E> {
|
|
278
|
+
readonly tags: readonly string[];
|
|
279
|
+
readonly automatic: boolean;
|
|
280
|
+
readonly run: AlarmRegistration<never, R, E>["run"];
|
|
281
|
+
}
|
|
282
|
+
interface RegistrationParts<R, E> {
|
|
283
|
+
readonly services: readonly string[];
|
|
284
|
+
readonly dispatchers: readonly AlarmDispatcher<R, E>[];
|
|
285
|
+
readonly invalid?: string;
|
|
225
286
|
}
|
|
287
|
+
/** Compose independent typed alarm registrations under one native alarm owner. */
|
|
288
|
+
declare function mergeAll<const Registrations extends readonly [AlarmRegistration<never, unknown, unknown>, ...AlarmRegistration<never, unknown, unknown>[]]>(...registrations: Registrations): AlarmRegistration<Layer.Success<Registrations[number]["layer"]>, Exclude<Effect.Services<Registrations[number]["run"]>, DurableObjectAlarm>, Exclude<Effect.Error<Registrations[number]["run"]>, DurableObjectAlarmError>>;
|
|
226
289
|
interface AlarmTagClass<Self, Id extends string, Definitions extends AlarmDefinitions> extends Context.ServiceClass<Self, Id, DefinedAlarmScheduler<Definitions>> {
|
|
227
290
|
readonly handlers: <R = never, E = never>(handlers: DefinedAlarmHandlers<Definitions, R, E>, options?: ProcessDueAlarmsOptions<R, E>) => AlarmRegistration<Self, R, E>;
|
|
228
291
|
}
|
|
@@ -230,6 +293,8 @@ interface AlarmTagClass<Self, Id extends string, Definitions extends AlarmDefini
|
|
|
230
293
|
declare const define: <const Definitions extends AlarmDefinitions>(definitions: Definitions) => {
|
|
231
294
|
handlers: <R = never, E = never>(handlers: DefinedAlarmHandlers<Definitions, R, E>, options?: ProcessDueAlarmsOptions<R, E> | undefined) => Effect.Effect<ProcessDueAlarmsResult, E | DurableObjectAlarmError, R | DurableObjectAlarm>;
|
|
232
295
|
};
|
|
296
|
+
/** @internal Preserve custom dispatch while recovering retained alarms after deployments. */
|
|
297
|
+
declare const dispatchRawAlarm: <Self, E, R>(rawAlarm: Effect.Effect<void, E, R>, registration?: AlarmRegistration<Self, R, E>) => Effect.Effect<void, E | DurableObjectAlarmError, R | DurableObjectAlarm | DurableObjectState>;
|
|
233
298
|
/** The typed scheduler becomes available when its handlers are registered on a Durable Object. */
|
|
234
299
|
declare const Tag: <Self>() => <const Id extends string, const Definitions extends AlarmDefinitions>(id: Id, definitions: Definitions) => AlarmTagClass<Self, Id, Definitions>;
|
|
235
300
|
declare const DurableObjectAlarm_base: Context.ServiceClass<DurableObjectAlarm, "effect-cf/DurableObjectAlarm", AlarmScheduler>;
|
|
@@ -237,4 +302,4 @@ declare class DurableObjectAlarm extends DurableObjectAlarm_base {
|
|
|
237
302
|
static readonly layer: Layer.Layer<DurableObjectAlarm, never, DurableObjectState>;
|
|
238
303
|
}
|
|
239
304
|
//#endregion
|
|
240
|
-
export { AlarmDefinitionConfig, AlarmDefinitionEntry, AlarmDefinitionPayload, AlarmDefinitions, AlarmFailurePolicy, AlarmParked, AlarmPayload, AlarmPayloadSchema, AlarmRef, AlarmRegistration, AlarmReporter, AlarmRetryPolicy, AlarmScheduler, AlarmService, AlarmStatus, AlarmTagClass, AlarmTransaction, DEFAULT_MIN_REPEAT_INTERVAL_MS, DefinedAlarmEvent, DefinedAlarmHandlers, DefinedAlarmScheduler, DefinedAlarmTransaction, DefinedScheduleAlarmInput, DurableObjectAlarm, DurableObjectAlarmError, DurableObjectAlarmEvent, DurableObjectAlarm_d_exports, InvalidAlarmPayloadError, InvalidAlarmRefError, InvalidProcessDueAlarmsOptionsError, InvalidRepeatEveryError, InvalidScheduleConfigurationError, MIN_REPEAT_INTERVAL_MS, MIN_RETRY_DELAY_MS, PARKED_RETRY_DELAY_MS, ProcessDueAlarmsFailure, ProcessDueAlarmsFailureAction, ProcessDueAlarmsHandler, ProcessDueAlarmsOptions, ProcessDueAlarmsResult, ScheduleAlarmInput, ScheduleConfiguration, StoredAlarmDecodeError, Tag, UNCHANGED_ATTEMPT_BUDGET, define, processDue };
|
|
305
|
+
export { AlarmDefinitionConfig, AlarmDefinitionEntry, AlarmDefinitionPayload, AlarmDefinitions, AlarmFailurePolicy, AlarmLifecycle, AlarmParked, AlarmPayload, AlarmPayloadSchema, AlarmRef, AlarmRegistration, AlarmReporter, AlarmRetryPolicy, AlarmScheduler, AlarmService, AlarmStatus, AlarmTagClass, AlarmTransaction, DEFAULT_MIN_REPEAT_INTERVAL_MS, DefinedAlarmEvent, DefinedAlarmHandlers, DefinedAlarmScheduler, DefinedAlarmTransaction, DefinedScheduleAlarmInput, DispatchAfterEvent, DurableObjectAlarm, DurableObjectAlarmError, DurableObjectAlarmEvent, DurableObjectAlarm_d_exports, HasDueAlarms, InvalidAlarmPayloadError, InvalidAlarmRefError, InvalidAlarmRegistrationError, InvalidProcessDueAlarmsOptionsError, InvalidRepeatEveryError, InvalidScheduleConfigurationError, MIN_REPEAT_INTERVAL_MS, MIN_RETRY_DELAY_MS, PARKED_RETRY_DELAY_MS, ProcessDueAlarmsFailure, ProcessDueAlarmsFailureAction, ProcessDueAlarmsHandler, ProcessDueAlarmsOptions, ProcessDueAlarmsResult, RunAlarm, ScheduleAlarmInput, ScheduleConfiguration, StoredAlarmDecodeError, Tag, UNCHANGED_ATTEMPT_BUDGET, define, dispatchRawAlarm, mergeAll, processDue };
|