@systemfsoftware/effect-daemon-spec 0.1.1 → 0.2.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/dist/index.d.ts +14 -12
- package/dist/index.mjs +25 -15
- package/package.json +7 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Cause, Context, Duration, Effect, Layer, Metric, Option, Schedule, Schema, Scope, Stream } from "effect";
|
|
2
|
-
|
|
3
2
|
//#region src/backoff.d.ts
|
|
4
3
|
declare const cappedBackoff: (base: Duration.DurationInput, cap: Duration.DurationInput) => Schedule.Schedule<Duration.Duration>;
|
|
5
4
|
//#endregion
|
|
@@ -80,12 +79,12 @@ declare const ChildPolicyConfig_base: Schema.Class<ChildPolicyConfig, {
|
|
|
80
79
|
window: typeof Schema.DurationFromSelf;
|
|
81
80
|
}>>;
|
|
82
81
|
}>, never, {
|
|
82
|
+
readonly restart?: "permanent" | "transient" | "temporary" | undefined;
|
|
83
|
+
} & {
|
|
83
84
|
readonly intensity?: {
|
|
84
85
|
readonly restarts: number;
|
|
85
86
|
readonly window: import("effect/Duration").Duration;
|
|
86
87
|
} | undefined;
|
|
87
|
-
} & {
|
|
88
|
-
readonly restart?: "permanent" | "temporary" | "transient" | undefined;
|
|
89
88
|
}, {}, {}>;
|
|
90
89
|
declare class ChildPolicyConfig extends ChildPolicyConfig_base {}
|
|
91
90
|
declare const LockPolicyConfig_base: Schema.Class<LockPolicyConfig, {
|
|
@@ -95,9 +94,9 @@ declare const LockPolicyConfig_base: Schema.Class<LockPolicyConfig, {
|
|
|
95
94
|
mode: Schema.optional<Schema.Literal<["none", "required", "optional"]>>;
|
|
96
95
|
key: Schema.optional<typeof Schema.String>;
|
|
97
96
|
}>, never, {
|
|
98
|
-
readonly
|
|
97
|
+
readonly mode?: "none" | "required" | "optional" | undefined;
|
|
99
98
|
} & {
|
|
100
|
-
readonly
|
|
99
|
+
readonly key?: string | undefined;
|
|
101
100
|
}, {}, {}>;
|
|
102
101
|
declare class LockPolicyConfig extends LockPolicyConfig_base {}
|
|
103
102
|
declare const TickPolicyConfig_base: Schema.Class<TickPolicyConfig, {
|
|
@@ -109,11 +108,11 @@ declare const TickPolicyConfig_base: Schema.Class<TickPolicyConfig, {
|
|
|
109
108
|
tickTimeout: typeof Schema.DurationFromSelf;
|
|
110
109
|
startLogLevel: Schema.optional<Schema.Literal<["debug", "info"]>>;
|
|
111
110
|
}>, never, {
|
|
111
|
+
readonly tickTimeout: import("effect/Duration").Duration;
|
|
112
|
+
} & {
|
|
112
113
|
readonly spanName?: string | undefined;
|
|
113
114
|
} & {
|
|
114
115
|
readonly startLogLevel?: "debug" | "info" | undefined;
|
|
115
|
-
} & {
|
|
116
|
-
readonly tickTimeout: import("effect/Duration").Duration;
|
|
117
116
|
}, {}, {}>;
|
|
118
117
|
declare class TickPolicyConfig extends TickPolicyConfig_base {}
|
|
119
118
|
//#endregion
|
|
@@ -244,9 +243,13 @@ declare const subscription: <A, E, R, L extends LockConfig>(opts: CommonOpts<L>
|
|
|
244
243
|
readonly acquire: Effect.Effect<A, E, R>;
|
|
245
244
|
}) => Worker<E, R, L>;
|
|
246
245
|
declare const Daemon: {
|
|
247
|
-
readonly poll:
|
|
248
|
-
readonly stream:
|
|
249
|
-
|
|
246
|
+
readonly poll: <A, E, R, L extends LockConfig>(opts: PollOpts<A, E, R, L>) => Worker<E, R, L>;
|
|
247
|
+
readonly stream: <A, E, R, L extends LockConfig>(opts: CommonOpts<L> & {
|
|
248
|
+
readonly stream: Stream.Stream<A, E, R>;
|
|
249
|
+
}) => Worker<E, R, L>;
|
|
250
|
+
readonly subscription: <A, E, R, L extends LockConfig>(opts: CommonOpts<L> & {
|
|
251
|
+
readonly acquire: Effect.Effect<A, E, R>;
|
|
252
|
+
}) => Worker<E, R, L>;
|
|
250
253
|
};
|
|
251
254
|
//#endregion
|
|
252
255
|
//#region src/leader-lock.schema.d.ts
|
|
@@ -308,11 +311,10 @@ declare function supervisor<E, R>(s: Supervisor<E, R, {
|
|
|
308
311
|
mode: 'none';
|
|
309
312
|
}>): Effect.Effect<SupervisorHealth, never, R | DaemonReporter | Scope.Scope>;
|
|
310
313
|
declare function supervisor<E, R>(s: Supervisor<E, R, LockConfig>): Effect.Effect<SupervisorHealth, never, R | LeaderLock | DaemonReporter | Scope.Scope>;
|
|
311
|
-
declare const dynamic$1: <E, R, Args>(spec: DynamicSpec<E, R, Args>) => Effect.Effect<DynamicHandle<Args, R | LeaderLock | DaemonReporter | Scope.Scope>, never, R | LeaderLock | DaemonReporter | Scope.Scope>;
|
|
312
314
|
declare const run: {
|
|
313
315
|
readonly worker: typeof worker;
|
|
314
316
|
readonly supervisor: typeof supervisor;
|
|
315
|
-
readonly dynamic:
|
|
317
|
+
readonly dynamic: <E, R, Args>(spec: DynamicSpec<E, R, Args>) => Effect.Effect<DynamicHandle<Args, R | LeaderLock | DaemonReporter | Scope.Scope>, never, R | LeaderLock | DaemonReporter | Scope.Scope>;
|
|
316
318
|
};
|
|
317
319
|
//#endregion
|
|
318
320
|
//#region src/supervisor.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -73,15 +73,19 @@ const make$1 = (common, loop) => ({
|
|
|
73
73
|
lock: common.lock
|
|
74
74
|
});
|
|
75
75
|
const poll = (opts) => {
|
|
76
|
-
if (typeof opts.prereq === "undefined")
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
if (typeof opts.prereq === "undefined") {
|
|
77
|
+
const gate = Effect.succeed(Option.some(Effect.asVoid(opts.work)));
|
|
78
|
+
return make$1(opts, {
|
|
79
|
+
_tag: "Poll",
|
|
80
|
+
gate,
|
|
81
|
+
interval: opts.interval
|
|
82
|
+
});
|
|
83
|
+
}
|
|
81
84
|
const { prereq, work } = opts;
|
|
85
|
+
const gate = Effect.map(prereq, Option.map((data) => work(data)));
|
|
82
86
|
return make$1(opts, {
|
|
83
87
|
_tag: "Poll",
|
|
84
|
-
gate
|
|
88
|
+
gate,
|
|
85
89
|
interval: opts.interval
|
|
86
90
|
});
|
|
87
91
|
};
|
|
@@ -165,10 +169,12 @@ const boundedTracker = (restarts, window) => Effect.gen(function* () {
|
|
|
165
169
|
yield* Ref.update(timestamps, (ts) => recordTimestamp(ts, now, windowMillis));
|
|
166
170
|
}),
|
|
167
171
|
isExceeded: Effect.gen(function* () {
|
|
168
|
-
|
|
172
|
+
const now = yield* Clock.currentTimeMillis;
|
|
173
|
+
return exceedsRestarts((yield* prune(now)).length, restarts);
|
|
169
174
|
}),
|
|
170
175
|
count: Effect.gen(function* () {
|
|
171
|
-
|
|
176
|
+
const now = yield* Clock.currentTimeMillis;
|
|
177
|
+
return (yield* prune(now)).length;
|
|
172
178
|
})
|
|
173
179
|
};
|
|
174
180
|
});
|
|
@@ -284,7 +290,7 @@ const superviseChild = (ctx, child, idx) => Effect.gen(function* () {
|
|
|
284
290
|
});
|
|
285
291
|
const loop = () => Effect.gen(function* () {
|
|
286
292
|
const supIntensity = yield* make(ctx.policy.intensity);
|
|
287
|
-
const
|
|
293
|
+
const attempt = Effect.gen(function* () {
|
|
288
294
|
yield* ctx.health.paused.await;
|
|
289
295
|
const fiber = yield* Effect.forkScoped(child.run);
|
|
290
296
|
const exit = yield* Fiber.await(fiber);
|
|
@@ -308,7 +314,8 @@ const superviseChild = (ctx, child, idx) => Effect.gen(function* () {
|
|
|
308
314
|
return yield* Match.value(decision).pipe(Match.tag("Continue", () => Effect.succeed(new StopEpoch())), Match.tag("Exhausted", () => handleExhausted(ctx, exit.cause)), Match.tag("Restart", () => handleRestart(ctx, exit.cause, Effect.void)), Match.exhaustive);
|
|
309
315
|
}
|
|
310
316
|
return new StopEpoch();
|
|
311
|
-
})
|
|
317
|
+
});
|
|
318
|
+
const epochResult = yield* runSupervisionEpochWithBackoff(attempt, ctx);
|
|
312
319
|
return yield* Match.value(epochResult).pipe(Match.tag("ContinueSupervision", () => loop()), Match.tag("StopSupervision", () => Effect.void), Match.exhaustive);
|
|
313
320
|
});
|
|
314
321
|
return yield* loop();
|
|
@@ -327,7 +334,7 @@ const runGroup = (strategy, ctx) => Effect.gen(function* () {
|
|
|
327
334
|
onSome: (cfg) => Effect.map(make(new BoundedIntensity(cfg)), Option.some)
|
|
328
335
|
}));
|
|
329
336
|
const cursor = yield* Ref.make(0);
|
|
330
|
-
const
|
|
337
|
+
const attempt = Effect.gen(function* () {
|
|
331
338
|
yield* ctx.health.paused.await;
|
|
332
339
|
const startIdx = yield* Ref.get(cursor);
|
|
333
340
|
const slice = ctx.booted.slice(startIdx);
|
|
@@ -359,7 +366,8 @@ const runGroup = (strategy, ctx) => Effect.gen(function* () {
|
|
|
359
366
|
return yield* Match.value(decision).pipe(Match.tag("Continue", () => Effect.succeed(new StopEpoch())), Match.tag("Exhausted", () => handleExhausted(ctx, firstExit.cause)), Match.tag("Restart", (restartDecision) => handleRestart(ctx, firstExit.cause, Ref.set(cursor, restartDecision.indices[0]))), Match.exhaustive);
|
|
360
367
|
}
|
|
361
368
|
return new StopEpoch();
|
|
362
|
-
})
|
|
369
|
+
});
|
|
370
|
+
const epochResult = yield* runSupervisionEpochWithBackoff(attempt, ctx);
|
|
363
371
|
return yield* Match.value(epochResult).pipe(Match.tag("ContinueSupervision", () => loop()), Match.tag("StopSupervision", () => Effect.void), Match.exhaustive);
|
|
364
372
|
});
|
|
365
373
|
return yield* loop();
|
|
@@ -463,15 +471,17 @@ const buildStreamLoop = (worker, loop, health) => {
|
|
|
463
471
|
yield* Effect.raceFirst(ready, Fiber.join(fiber));
|
|
464
472
|
yield* Fiber.join(fiber);
|
|
465
473
|
});
|
|
466
|
-
|
|
474
|
+
const retried = applyInnerRetry(worker.tickHooks)(body);
|
|
475
|
+
return wrapSpan(worker, retried.pipe(Effect.asVoid));
|
|
467
476
|
};
|
|
468
477
|
const buildSubscriptionLoop = (worker, loop, health) => {
|
|
469
|
-
|
|
478
|
+
const body = Effect.gen(function* () {
|
|
470
479
|
yield* health.paused.await;
|
|
471
480
|
yield* applyTimeout(worker.tick)(loop.acquire);
|
|
472
481
|
yield* Effect.zipRight(health.ready.open, Metric.set(Metric.tagged(Metric.tagged(healthStateGauge, "daemon", health.name), "latch", "ready"), 1));
|
|
473
482
|
return yield* Effect.never;
|
|
474
|
-
})
|
|
483
|
+
});
|
|
484
|
+
return wrapSpan(worker, body.pipe(Effect.asVoid));
|
|
475
485
|
};
|
|
476
486
|
const buildWorkerLoop = (worker, health) => Match.value(worker.loop).pipe(Match.tag("Poll", (loop) => buildPollLoop(worker, loop, health)), Match.tag("Stream", (loop) => buildStreamLoop(worker, loop, health)), Match.tag("Subscription", (loop) => buildSubscriptionLoop(worker, loop, health)), Match.exhaustive);
|
|
477
487
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/effect-daemon-spec",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"author": "Ryan Lee <drdgvhbh@gmail.com>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -37,23 +37,22 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@effect/vitest": "0.
|
|
40
|
+
"@effect/vitest": "0.30.0",
|
|
41
41
|
"@microsoft/api-extractor": "^7.58.7",
|
|
42
|
-
"@stryker-mutator/core": "^9.6.1",
|
|
43
|
-
"@stryker-mutator/typescript-checker": "^9.6.1",
|
|
44
42
|
"@stryker-mutator/vitest-runner": "^9.6.1",
|
|
45
43
|
"@types/node": "^24",
|
|
46
44
|
"@vitest/coverage-v8": "^4",
|
|
47
|
-
"effect": "^3.
|
|
45
|
+
"effect": "^3.22.0",
|
|
48
46
|
"fast-check": "^3",
|
|
49
47
|
"rimraf": "^6.1.3",
|
|
50
|
-
"tsdown": "^0.22.
|
|
51
|
-
"typescript": "^7",
|
|
48
|
+
"tsdown": "^0.22.9",
|
|
52
49
|
"vite-tsconfig-paths": "^6.1.1",
|
|
53
50
|
"vitest": "^4",
|
|
54
|
-
"@systemfsoftware/effect-gherkin-spec": "^0.1.0",
|
|
55
51
|
"@systemfsoftware/effect-schema-law": "^0.1.0",
|
|
52
|
+
"@systemfsoftware/stryker-js-core": "^0.1.0",
|
|
56
53
|
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
54
|
+
"@systemfsoftware/stryker-js-typescript-checker": "^0.1.0",
|
|
55
|
+
"@systemfsoftware/effect-gherkin-spec": "^0.1.0",
|
|
57
56
|
"@systemfsoftware/stryker-plugins": "^0.1.0",
|
|
58
57
|
"@systemfsoftware/tsconfig": "^1.0.0",
|
|
59
58
|
"@systemfsoftware/vitest-config": "^0.1.0"
|