effect-machine 0.6.0 → 0.7.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/actor.d.ts +2 -2
- package/dist/actor.js +12 -14
- package/dist/cluster/entity-machine.d.ts +2 -2
- package/dist/cluster/entity-machine.js +1 -1
- package/dist/cluster/to-entity.d.ts +5 -5
- package/dist/cluster/to-entity.js +2 -2
- package/dist/errors.d.ts +25 -40
- package/dist/errors.js +10 -10
- package/dist/inspection.d.ts +3 -3
- package/dist/inspection.js +2 -2
- package/dist/internal/brands.d.ts +3 -6
- package/dist/internal/inspection.js +5 -1
- package/dist/internal/transition.d.ts +2 -2
- package/dist/internal/transition.js +6 -6
- package/dist/internal/utils.js +5 -1
- package/dist/machine.d.ts +5 -5
- package/dist/machine.js +9 -5
- package/dist/persistence/adapter.d.ts +18 -21
- package/dist/persistence/adapter.js +4 -4
- package/dist/persistence/adapters/in-memory.js +4 -4
- package/dist/persistence/persistent-actor.js +9 -9
- package/dist/persistence/persistent-machine.d.ts +3 -3
- package/dist/schema.d.ts +4 -4
- package/dist/schema.js +2 -2
- package/dist/slot.d.ts +3 -3
- package/dist/slot.js +2 -2
- package/dist-v3/_virtual/_rolldown/runtime.js +18 -0
- package/dist-v3/actor.d.ts +291 -0
- package/dist-v3/actor.js +459 -0
- package/dist-v3/cluster/entity-machine.d.ts +90 -0
- package/dist-v3/cluster/entity-machine.js +80 -0
- package/dist-v3/cluster/index.d.ts +3 -0
- package/dist-v3/cluster/index.js +4 -0
- package/dist-v3/cluster/to-entity.d.ts +61 -0
- package/dist-v3/cluster/to-entity.js +53 -0
- package/dist-v3/errors.d.ts +27 -0
- package/dist-v3/errors.js +38 -0
- package/dist-v3/index.d.ts +13 -0
- package/dist-v3/index.js +14 -0
- package/dist-v3/inspection.d.ts +125 -0
- package/dist-v3/inspection.js +50 -0
- package/dist-v3/internal/brands.d.ts +40 -0
- package/dist-v3/internal/brands.js +0 -0
- package/dist-v3/internal/inspection.d.ts +11 -0
- package/dist-v3/internal/inspection.js +15 -0
- package/dist-v3/internal/transition.d.ts +160 -0
- package/dist-v3/internal/transition.js +238 -0
- package/dist-v3/internal/utils.d.ts +60 -0
- package/dist-v3/internal/utils.js +51 -0
- package/dist-v3/machine.d.ts +278 -0
- package/dist-v3/machine.js +317 -0
- package/dist-v3/persistence/adapter.d.ts +125 -0
- package/dist-v3/persistence/adapter.js +27 -0
- package/dist-v3/persistence/adapters/in-memory.d.ts +32 -0
- package/dist-v3/persistence/adapters/in-memory.js +176 -0
- package/dist-v3/persistence/index.d.ts +5 -0
- package/dist-v3/persistence/index.js +6 -0
- package/dist-v3/persistence/persistent-actor.d.ts +49 -0
- package/dist-v3/persistence/persistent-actor.js +367 -0
- package/dist-v3/persistence/persistent-machine.d.ts +105 -0
- package/dist-v3/persistence/persistent-machine.js +24 -0
- package/dist-v3/schema.d.ts +141 -0
- package/dist-v3/schema.js +165 -0
- package/dist-v3/slot.d.ts +130 -0
- package/dist-v3/slot.js +99 -0
- package/dist-v3/testing.d.ts +136 -0
- package/dist-v3/testing.js +138 -0
- package/package.json +29 -21
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema, ServiceMap } from "effect";
|
|
2
2
|
|
|
3
3
|
//#region src/persistence/adapter.ts
|
|
4
4
|
/**
|
|
5
5
|
* Error type for persistence operations
|
|
6
6
|
*/
|
|
7
|
-
var PersistenceError = class extends Schema.
|
|
7
|
+
var PersistenceError = class extends Schema.TaggedErrorClass()("PersistenceError", {
|
|
8
8
|
operation: Schema.String,
|
|
9
9
|
actorId: Schema.String,
|
|
10
10
|
cause: Schema.optional(Schema.Unknown),
|
|
@@ -13,7 +13,7 @@ var PersistenceError = class extends Schema.TaggedError()("PersistenceError", {
|
|
|
13
13
|
/**
|
|
14
14
|
* Version conflict error — snapshot version doesn't match expected
|
|
15
15
|
*/
|
|
16
|
-
var VersionConflictError = class extends Schema.
|
|
16
|
+
var VersionConflictError = class extends Schema.TaggedErrorClass()("VersionConflictError", {
|
|
17
17
|
actorId: Schema.String,
|
|
18
18
|
expectedVersion: Schema.Number,
|
|
19
19
|
actualVersion: Schema.Number
|
|
@@ -21,7 +21,7 @@ var VersionConflictError = class extends Schema.TaggedError()("VersionConflictEr
|
|
|
21
21
|
/**
|
|
22
22
|
* PersistenceAdapter service tag
|
|
23
23
|
*/
|
|
24
|
-
var PersistenceAdapterTag = class extends
|
|
24
|
+
var PersistenceAdapterTag = class extends ServiceMap.Service()("effect-machine/src/persistence/adapter/PersistenceAdapterTag") {};
|
|
25
25
|
|
|
26
26
|
//#endregion
|
|
27
27
|
export { PersistenceAdapterTag, PersistenceError, VersionConflictError };
|
|
@@ -42,7 +42,7 @@ const make = Effect.gen(function* () {
|
|
|
42
42
|
actualVersion: snapshot.version
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
const encoded = yield* Schema.
|
|
45
|
+
const encoded = yield* Schema.encodeEffect(schema)(snapshot.state).pipe(Effect.mapError((cause) => new PersistenceError({
|
|
46
46
|
operation: "saveSnapshot",
|
|
47
47
|
actorId: id,
|
|
48
48
|
cause,
|
|
@@ -61,7 +61,7 @@ const make = Effect.gen(function* () {
|
|
|
61
61
|
const actorStorage = yield* getOrCreateStorage(id);
|
|
62
62
|
if (Option.isNone(actorStorage.snapshot)) return Option.none();
|
|
63
63
|
const stored = actorStorage.snapshot.value;
|
|
64
|
-
const decoded = yield* Schema.
|
|
64
|
+
const decoded = yield* Schema.decodeEffect(schema)(stored.data).pipe(Effect.mapError((cause) => new PersistenceError({
|
|
65
65
|
operation: "loadSnapshot",
|
|
66
66
|
actorId: id,
|
|
67
67
|
cause,
|
|
@@ -75,7 +75,7 @@ const make = Effect.gen(function* () {
|
|
|
75
75
|
}),
|
|
76
76
|
appendEvent: Effect.fn("effect-machine.persistence.inMemory.appendEvent")(function* (id, event, schema) {
|
|
77
77
|
yield* getOrCreateStorage(id);
|
|
78
|
-
const encoded = yield* Schema.
|
|
78
|
+
const encoded = yield* Schema.encodeEffect(schema)(event.event).pipe(Effect.mapError((cause) => new PersistenceError({
|
|
79
79
|
operation: "appendEvent",
|
|
80
80
|
actorId: id,
|
|
81
81
|
cause,
|
|
@@ -95,7 +95,7 @@ const make = Effect.gen(function* () {
|
|
|
95
95
|
const decoded = [];
|
|
96
96
|
for (const stored of actorStorage.events) {
|
|
97
97
|
if (afterVersion !== void 0 && stored.version <= afterVersion) continue;
|
|
98
|
-
const event = yield* Schema.
|
|
98
|
+
const event = yield* Schema.decodeEffect(schema)(stored.data).pipe(Effect.mapError((cause) => new PersistenceError({
|
|
99
99
|
operation: "loadEvents",
|
|
100
100
|
actorId: id,
|
|
101
101
|
cause,
|
|
@@ -139,10 +139,10 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
|
|
|
139
139
|
}));
|
|
140
140
|
const snapshotEnabledRef = yield* Ref.make(true);
|
|
141
141
|
const persistenceQueue = yield* Queue.unbounded();
|
|
142
|
-
const persistenceFiber = yield* Effect.
|
|
142
|
+
const persistenceFiber = yield* Effect.forkDetach(persistenceWorker(persistenceQueue));
|
|
143
143
|
yield* Queue.offer(persistenceQueue, saveMetadata(id, resolvedInitial, initialVersion, createdAt, persistence, adapter));
|
|
144
144
|
const snapshotQueue = yield* Queue.unbounded();
|
|
145
|
-
const snapshotFiber = yield* Effect.
|
|
145
|
+
const snapshotFiber = yield* Effect.forkDetach(snapshotWorker(id, persistence, adapter, snapshotQueue, snapshotEnabledRef));
|
|
146
146
|
const backgroundFibers = [];
|
|
147
147
|
const initEvent = { _tag: INTERNAL_INIT_EVENT };
|
|
148
148
|
const initCtx = {
|
|
@@ -153,7 +153,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
|
|
|
153
153
|
};
|
|
154
154
|
const { effects: effectSlots } = typedMachine._slots;
|
|
155
155
|
for (const bg of typedMachine.backgroundEffects) {
|
|
156
|
-
const fiber = yield* Effect.
|
|
156
|
+
const fiber = yield* Effect.forkDetach(bg.handler({
|
|
157
157
|
state: resolvedInitial,
|
|
158
158
|
event: initEvent,
|
|
159
159
|
self,
|
|
@@ -178,7 +178,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
|
|
|
178
178
|
}));
|
|
179
179
|
return buildPersistentActorRef(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, Ref.set(stoppedRef, true).pipe(Effect.withSpan("effect-machine.persistentActor.stop"), Effect.asVoid), adapter, system, childrenMap);
|
|
180
180
|
}
|
|
181
|
-
const loopFiber = yield* Effect.
|
|
181
|
+
const loopFiber = yield* Effect.forkDetach(persistentEventLoop(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, self, listeners, adapter, createdAt, stateScopeRef, backgroundFibers, snapshotQueue, snapshotEnabledRef, persistenceQueue, snapshotFiber, persistenceFiber, inspector, system));
|
|
182
182
|
return buildPersistentActorRef(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, Effect.gen(function* () {
|
|
183
183
|
const finalState = yield* SubscriptionRef.get(stateRef);
|
|
184
184
|
yield* emitWithTimestamp(inspector, (timestamp) => ({
|
|
@@ -250,7 +250,7 @@ const persistentEventLoop = Effect.fn("effect-machine.persistentActor.eventLoop"
|
|
|
250
250
|
version: newVersion,
|
|
251
251
|
timestamp: yield* now
|
|
252
252
|
};
|
|
253
|
-
const journalTask = adapter.appendEvent(id, persistedEvent, persistence.eventSchema).pipe(Effect.
|
|
253
|
+
const journalTask = adapter.appendEvent(id, persistedEvent, persistence.eventSchema).pipe(Effect.catchEager((e) => Effect.logWarning(`Failed to journal event for actor ${id}`, e)), Effect.asVoid);
|
|
254
254
|
yield* Queue.offer(persistenceQueue, journalTask);
|
|
255
255
|
}
|
|
256
256
|
yield* Queue.offer(persistenceQueue, saveMetadata(id, result.newState, newVersion, createdAt, persistence, adapter));
|
|
@@ -306,11 +306,11 @@ const persistenceWorker = Effect.fn("effect-machine.persistentActor.persistenceW
|
|
|
306
306
|
* Snapshot scheduler worker (runs in background).
|
|
307
307
|
*/
|
|
308
308
|
const snapshotWorker = Effect.fn("effect-machine.persistentActor.snapshotWorker")(function* (id, persistence, adapter, queue, enabledRef) {
|
|
309
|
-
const
|
|
309
|
+
const step = yield* Schedule.toStep(persistence.snapshotSchedule);
|
|
310
310
|
while (true) {
|
|
311
311
|
const { state, version } = yield* Queue.take(queue);
|
|
312
312
|
if (!(yield* Ref.get(enabledRef))) continue;
|
|
313
|
-
if (!(yield*
|
|
313
|
+
if (!(yield* step(yield* Clock.currentTimeMillis, state).pipe(Effect.match({
|
|
314
314
|
onFailure: () => false,
|
|
315
315
|
onSuccess: () => true
|
|
316
316
|
})))) {
|
|
@@ -330,7 +330,7 @@ const saveSnapshot = Effect.fn("effect-machine.persistentActor.saveSnapshot")(fu
|
|
|
330
330
|
version,
|
|
331
331
|
timestamp: yield* now
|
|
332
332
|
};
|
|
333
|
-
yield* adapter.saveSnapshot(id, snapshot, persistence.stateSchema).pipe(Effect.
|
|
333
|
+
yield* adapter.saveSnapshot(id, snapshot, persistence.stateSchema).pipe(Effect.catchEager((e) => Effect.logWarning(`Failed to save snapshot for actor ${id}`, e)));
|
|
334
334
|
});
|
|
335
335
|
/**
|
|
336
336
|
* Save or update actor metadata if adapter supports registry.
|
|
@@ -347,7 +347,7 @@ const saveMetadata = Effect.fn("effect-machine.persistentActor.saveMetadata")(fu
|
|
|
347
347
|
lastActivityAt,
|
|
348
348
|
version,
|
|
349
349
|
stateTag: state._tag
|
|
350
|
-
}).pipe(Effect.
|
|
350
|
+
}).pipe(Effect.catchEager((e) => Effect.logWarning(`Failed to save metadata for actor ${id}`, e)));
|
|
351
351
|
});
|
|
352
352
|
/**
|
|
353
353
|
* Restore an actor from persistence.
|
|
@@ -16,7 +16,7 @@ type BrandedEvent = {
|
|
|
16
16
|
* Note: Schema types S and E should match the structural shape of the machine's
|
|
17
17
|
* state and event types (without brands). The schemas don't know about brands.
|
|
18
18
|
*/
|
|
19
|
-
interface PersistenceConfig<S, E
|
|
19
|
+
interface PersistenceConfig<S, E> {
|
|
20
20
|
/**
|
|
21
21
|
* Schedule controlling when snapshots are taken.
|
|
22
22
|
* Input is the new state after each transition.
|
|
@@ -36,12 +36,12 @@ interface PersistenceConfig<S, E, SSI = unknown, ESI = unknown> {
|
|
|
36
36
|
* Schema for serializing/deserializing state.
|
|
37
37
|
* Always present at runtime (resolved from config or machine).
|
|
38
38
|
*/
|
|
39
|
-
readonly stateSchema: Schema.
|
|
39
|
+
readonly stateSchema: Schema.Codec<S, unknown, never, never>;
|
|
40
40
|
/**
|
|
41
41
|
* Schema for serializing/deserializing events.
|
|
42
42
|
* Always present at runtime (resolved from config or machine).
|
|
43
43
|
*/
|
|
44
|
-
readonly eventSchema: Schema.
|
|
44
|
+
readonly eventSchema: Schema.Codec<E, unknown, never, never>;
|
|
45
45
|
/**
|
|
46
46
|
* User-provided identifier for the machine type.
|
|
47
47
|
* Used for filtering actors in restoreAll.
|
package/dist/schema.d.ts
CHANGED
|
@@ -36,8 +36,8 @@ type IsEmptyFields<Fields extends Schema.Struct.Fields> = keyof Fields extends n
|
|
|
36
36
|
*/
|
|
37
37
|
type VariantConstructors<D extends Record<string, Schema.Struct.Fields>, Brand> = { readonly [K in keyof D & string]: IsEmptyFields<D[K]> extends true ? TaggedStructType<K, D[K]> & Brand & {
|
|
38
38
|
readonly derive: (source: object) => TaggedStructType<K, D[K]> & Brand;
|
|
39
|
-
} : ((args: Schema.Struct.
|
|
40
|
-
readonly derive: (source: object, partial?: Partial<Schema.Struct.
|
|
39
|
+
} : ((args: Schema.Struct.Type<D[K]>) => TaggedStructType<K, D[K]> & Brand) & {
|
|
40
|
+
readonly derive: (source: object, partial?: Partial<Schema.Struct.Type<D[K]>>) => TaggedStructType<K, D[K]> & Brand;
|
|
41
41
|
readonly _tag: K;
|
|
42
42
|
} };
|
|
43
43
|
/**
|
|
@@ -78,14 +78,14 @@ interface MachineSchemaBase<D extends Record<string, Schema.Struct.Fields>, Bran
|
|
|
78
78
|
* The D type parameter captures the definition, creating a unique brand
|
|
79
79
|
* per distinct schema definition shape.
|
|
80
80
|
*/
|
|
81
|
-
type MachineStateSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.
|
|
81
|
+
type MachineStateSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Codec<VariantsUnion<D> & FullStateBrand<D>, unknown, never, never> & MachineSchemaBase<D, FullStateBrand<D>> & VariantConstructors<D, FullStateBrand<D>>;
|
|
82
82
|
/**
|
|
83
83
|
* Schema-first event definition (same structure as state, different brand)
|
|
84
84
|
*
|
|
85
85
|
* The D type parameter captures the definition, creating a unique brand
|
|
86
86
|
* per distinct schema definition shape.
|
|
87
87
|
*/
|
|
88
|
-
type MachineEventSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.
|
|
88
|
+
type MachineEventSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Codec<VariantsUnion<D> & FullEventBrand<D>, unknown, never, never> & MachineSchemaBase<D, FullEventBrand<D>> & VariantConstructors<D, FullEventBrand<D>>;
|
|
89
89
|
/**
|
|
90
90
|
* Create a schema-first State definition.
|
|
91
91
|
*
|
package/dist/schema.js
CHANGED
|
@@ -69,8 +69,8 @@ const buildMachineSchema = (definition) => {
|
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
const variantArray = Object.values(variants);
|
|
72
|
-
if (variantArray.length === 0) throw new InvalidSchemaError();
|
|
73
|
-
const unionSchema = variantArray.length === 1 ? variantArray[0] : Schema.Union(
|
|
72
|
+
if (variantArray.length === 0) throw new InvalidSchemaError({});
|
|
73
|
+
const unionSchema = variantArray.length === 1 ? variantArray[0] : Schema.Union(variantArray);
|
|
74
74
|
const $is = (tag) => (u) => typeof u === "object" && u !== null && "_tag" in u && u._tag === tag;
|
|
75
75
|
const $match = (valueOrCases, maybeCases) => {
|
|
76
76
|
if (maybeCases !== void 0) {
|
package/dist/slot.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ActorSystem } from "./actor.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Effect, Schema, ServiceMap } from "effect";
|
|
3
3
|
|
|
4
4
|
//#region src/slot.d.ts
|
|
5
5
|
/** Schema fields definition (like Schema.Struct.Fields) */
|
|
6
|
-
type Fields = Record<string, Schema.
|
|
6
|
+
type Fields = Record<string, Schema.Top>;
|
|
7
7
|
/** Extract the encoded type from schema fields (used for parameters) */
|
|
8
8
|
type FieldsToParams<F extends Fields> = keyof F extends never ? void : Schema.Schema.Type<Schema.Struct<F>>;
|
|
9
9
|
/**
|
|
@@ -53,7 +53,7 @@ interface MachineContext<State, Event, Self> {
|
|
|
53
53
|
* Single module-level tag instead of per-machine allocation.
|
|
54
54
|
* @internal
|
|
55
55
|
*/
|
|
56
|
-
declare const MachineContextTag:
|
|
56
|
+
declare const MachineContextTag: ServiceMap.Service<MachineContext<any, any, any>, MachineContext<any, any, any>>;
|
|
57
57
|
/**
|
|
58
58
|
* Guard handler implementation.
|
|
59
59
|
* Receives params and context, returns Effect<boolean>.
|
package/dist/slot.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ServiceMap } from "effect";
|
|
2
2
|
|
|
3
3
|
//#region src/slot.ts
|
|
4
4
|
/**
|
|
@@ -41,7 +41,7 @@ import { Context } from "effect";
|
|
|
41
41
|
* Single module-level tag instead of per-machine allocation.
|
|
42
42
|
* @internal
|
|
43
43
|
*/
|
|
44
|
-
const MachineContextTag =
|
|
44
|
+
const MachineContextTag = ServiceMap.Service("@effect-machine/Context");
|
|
45
45
|
/**
|
|
46
46
|
* Generic slot schema factory. Used internally by Guards() and Effects().
|
|
47
47
|
* @internal
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) {
|
|
6
|
+
__defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
if (!no_symbols) {
|
|
12
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
13
|
+
}
|
|
14
|
+
return target;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { __exportAll };
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { PersistentMachine } from "./persistence/persistent-machine.js";
|
|
2
|
+
import { DuplicateActorError } from "./errors.js";
|
|
3
|
+
import { EffectsDef, GuardsDef } from "./slot.js";
|
|
4
|
+
import { ProcessEventError, ProcessEventHooks, ProcessEventResult, processEventCore, resolveTransition, runSpawnEffects } from "./internal/transition.js";
|
|
5
|
+
import { PersistentActorRef } from "./persistence/persistent-actor.js";
|
|
6
|
+
import { ActorMetadata, PersistenceAdapterTag, PersistenceError, RestoreResult, VersionConflictError } from "./persistence/adapter.js";
|
|
7
|
+
import { BuiltMachine, Machine } from "./machine.js";
|
|
8
|
+
import { Effect, Option, Queue, Ref, Stream, SubscriptionRef } from "effect";
|
|
9
|
+
|
|
10
|
+
//#region src-v3/actor.d.ts
|
|
11
|
+
/**
|
|
12
|
+
* Reference to a running actor.
|
|
13
|
+
*/
|
|
14
|
+
interface ActorRef<State extends {
|
|
15
|
+
readonly _tag: string;
|
|
16
|
+
}, Event> {
|
|
17
|
+
/**
|
|
18
|
+
* Unique identifier for this actor
|
|
19
|
+
*/
|
|
20
|
+
readonly id: string;
|
|
21
|
+
/**
|
|
22
|
+
* Send an event to the actor
|
|
23
|
+
*/
|
|
24
|
+
readonly send: (event: Event) => Effect.Effect<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Observable state of the actor
|
|
27
|
+
*/
|
|
28
|
+
readonly state: SubscriptionRef.SubscriptionRef<State>;
|
|
29
|
+
/**
|
|
30
|
+
* Stop the actor gracefully
|
|
31
|
+
*/
|
|
32
|
+
readonly stop: Effect.Effect<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Stop the actor (fire-and-forget).
|
|
35
|
+
* Signals graceful shutdown without waiting for completion.
|
|
36
|
+
* Use when stopping from sync contexts (e.g. framework cleanup hooks).
|
|
37
|
+
*/
|
|
38
|
+
readonly stopSync: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Get current state snapshot (Effect)
|
|
41
|
+
*/
|
|
42
|
+
readonly snapshot: Effect.Effect<State>;
|
|
43
|
+
/**
|
|
44
|
+
* Get current state snapshot (sync)
|
|
45
|
+
*/
|
|
46
|
+
readonly snapshotSync: () => State;
|
|
47
|
+
/**
|
|
48
|
+
* Check if current state matches tag (Effect)
|
|
49
|
+
*/
|
|
50
|
+
readonly matches: (tag: State["_tag"]) => Effect.Effect<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if current state matches tag (sync)
|
|
53
|
+
*/
|
|
54
|
+
readonly matchesSync: (tag: State["_tag"]) => boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Check if event can be handled in current state (Effect)
|
|
57
|
+
*/
|
|
58
|
+
readonly can: (event: Event) => Effect.Effect<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if event can be handled in current state (sync)
|
|
61
|
+
*/
|
|
62
|
+
readonly canSync: (event: Event) => boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Stream of state changes
|
|
65
|
+
*/
|
|
66
|
+
readonly changes: Stream.Stream<State>;
|
|
67
|
+
/**
|
|
68
|
+
* Wait for a state that matches predicate or state variant (includes current snapshot).
|
|
69
|
+
* Accepts a predicate function or a state constructor/value (e.g. `State.Active`).
|
|
70
|
+
*/
|
|
71
|
+
readonly waitFor: {
|
|
72
|
+
(predicate: (state: State) => boolean): Effect.Effect<State>;
|
|
73
|
+
(state: {
|
|
74
|
+
readonly _tag: State["_tag"];
|
|
75
|
+
}): Effect.Effect<State>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Wait for a final state (includes current snapshot)
|
|
79
|
+
*/
|
|
80
|
+
readonly awaitFinal: Effect.Effect<State>;
|
|
81
|
+
/**
|
|
82
|
+
* Send event and wait for predicate, state variant, or final state.
|
|
83
|
+
* Accepts a predicate function or a state constructor/value (e.g. `State.Active`).
|
|
84
|
+
*/
|
|
85
|
+
readonly sendAndWait: {
|
|
86
|
+
(event: Event, predicate: (state: State) => boolean): Effect.Effect<State>;
|
|
87
|
+
(event: Event, state: {
|
|
88
|
+
readonly _tag: State["_tag"];
|
|
89
|
+
}): Effect.Effect<State>;
|
|
90
|
+
(event: Event): Effect.Effect<State>;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Send event synchronously (fire-and-forget).
|
|
94
|
+
* No-op on stopped actors. Use when you need to send from sync contexts
|
|
95
|
+
* (e.g. framework hooks, event handlers).
|
|
96
|
+
*/
|
|
97
|
+
readonly sendSync: (event: Event) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Subscribe to state changes (sync callback)
|
|
100
|
+
* Returns unsubscribe function
|
|
101
|
+
*/
|
|
102
|
+
readonly subscribe: (fn: (state: State) => void) => () => void;
|
|
103
|
+
/**
|
|
104
|
+
* The actor system this actor belongs to.
|
|
105
|
+
* Every actor always has a system — either inherited from context or implicitly created.
|
|
106
|
+
*/
|
|
107
|
+
readonly system: ActorSystem;
|
|
108
|
+
/**
|
|
109
|
+
* Child actors spawned via `self.spawn` in this actor's handlers.
|
|
110
|
+
* State-scoped children are auto-removed on state exit.
|
|
111
|
+
*/
|
|
112
|
+
readonly children: ReadonlyMap<string, ActorRef<AnyState, unknown>>;
|
|
113
|
+
}
|
|
114
|
+
/** Base type for stored actors (internal) */
|
|
115
|
+
type AnyState = {
|
|
116
|
+
readonly _tag: string;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Events emitted by the ActorSystem when actors are spawned or stopped.
|
|
120
|
+
*/
|
|
121
|
+
type SystemEvent = {
|
|
122
|
+
readonly _tag: "ActorSpawned";
|
|
123
|
+
readonly id: string;
|
|
124
|
+
readonly actor: ActorRef<AnyState, unknown>;
|
|
125
|
+
} | {
|
|
126
|
+
readonly _tag: "ActorStopped";
|
|
127
|
+
readonly id: string;
|
|
128
|
+
readonly actor: ActorRef<AnyState, unknown>;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Listener callback for system events.
|
|
132
|
+
*/
|
|
133
|
+
type SystemEventListener = (event: SystemEvent) => void;
|
|
134
|
+
/**
|
|
135
|
+
* Actor system for managing actor lifecycles
|
|
136
|
+
*/
|
|
137
|
+
interface ActorSystem {
|
|
138
|
+
/**
|
|
139
|
+
* Spawn a new actor with the given machine.
|
|
140
|
+
*
|
|
141
|
+
* For regular machines, returns ActorRef.
|
|
142
|
+
* For persistent machines (created with Machine.persist), returns PersistentActorRef.
|
|
143
|
+
*
|
|
144
|
+
* All effect slots must be provided via `.build()` before spawning.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* // Regular machine (built)
|
|
149
|
+
* const built = machine.build({ fetchData: ... })
|
|
150
|
+
* const actor = yield* system.spawn("my-actor", built);
|
|
151
|
+
*
|
|
152
|
+
* // Persistent machine (auto-detected)
|
|
153
|
+
* const persistentActor = yield* system.spawn("my-actor", persistentMachine);
|
|
154
|
+
* persistentActor.persist; // available
|
|
155
|
+
* persistentActor.version; // available
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
readonly spawn: {
|
|
159
|
+
<S extends {
|
|
160
|
+
readonly _tag: string;
|
|
161
|
+
}, E extends {
|
|
162
|
+
readonly _tag: string;
|
|
163
|
+
}, R>(id: string, machine: BuiltMachine<S, E, R>): Effect.Effect<ActorRef<S, E>, DuplicateActorError, R>;
|
|
164
|
+
<S extends {
|
|
165
|
+
readonly _tag: string;
|
|
166
|
+
}, E extends {
|
|
167
|
+
readonly _tag: string;
|
|
168
|
+
}, R>(id: string, machine: PersistentMachine<S, E, R>): Effect.Effect<PersistentActorRef<S, E, R>, PersistenceError | VersionConflictError | DuplicateActorError, R | PersistenceAdapterTag>;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Restore an actor from persistence.
|
|
172
|
+
* Returns None if no persisted state exists for the given ID.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* const maybeActor = yield* system.restore("order-1", persistentMachine);
|
|
177
|
+
* if (Option.isSome(maybeActor)) {
|
|
178
|
+
* const actor = maybeActor.value;
|
|
179
|
+
* const state = yield* actor.snapshot;
|
|
180
|
+
* console.log(`Restored to state: ${state._tag}`);
|
|
181
|
+
* }
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
readonly restore: <S extends {
|
|
185
|
+
readonly _tag: string;
|
|
186
|
+
}, E extends {
|
|
187
|
+
readonly _tag: string;
|
|
188
|
+
}, R>(id: string, machine: PersistentMachine<S, E, R>) => Effect.Effect<Option.Option<PersistentActorRef<S, E, R>>, PersistenceError | DuplicateActorError, R | PersistenceAdapterTag>;
|
|
189
|
+
/**
|
|
190
|
+
* Get an existing actor by ID
|
|
191
|
+
*/
|
|
192
|
+
readonly get: (id: string) => Effect.Effect<Option.Option<ActorRef<AnyState, unknown>>>;
|
|
193
|
+
/**
|
|
194
|
+
* Stop an actor by ID
|
|
195
|
+
*/
|
|
196
|
+
readonly stop: (id: string) => Effect.Effect<boolean>;
|
|
197
|
+
/**
|
|
198
|
+
* Async stream of system events (actor spawned/stopped).
|
|
199
|
+
* Each subscriber gets their own queue — late subscribers miss prior events.
|
|
200
|
+
*/
|
|
201
|
+
readonly events: Stream.Stream<SystemEvent>;
|
|
202
|
+
/**
|
|
203
|
+
* Sync snapshot of all currently registered actors.
|
|
204
|
+
* Returns a new Map on each access (not live).
|
|
205
|
+
*/
|
|
206
|
+
readonly actors: ReadonlyMap<string, ActorRef<AnyState, unknown>>;
|
|
207
|
+
/**
|
|
208
|
+
* Subscribe to system events synchronously.
|
|
209
|
+
* Returns an unsubscribe function.
|
|
210
|
+
*/
|
|
211
|
+
readonly subscribe: (fn: SystemEventListener) => () => void;
|
|
212
|
+
/**
|
|
213
|
+
* List all persisted actor metadata.
|
|
214
|
+
* Returns empty array if adapter doesn't support registry.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* const actors = yield* system.listPersisted();
|
|
219
|
+
* for (const meta of actors) {
|
|
220
|
+
* console.log(`${meta.id}: ${meta.stateTag} (v${meta.version})`);
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
readonly listPersisted: () => Effect.Effect<ReadonlyArray<ActorMetadata>, PersistenceError, PersistenceAdapterTag>;
|
|
225
|
+
/**
|
|
226
|
+
* Restore multiple actors by ID.
|
|
227
|
+
* Returns both successfully restored actors and failures.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts
|
|
231
|
+
* const result = yield* system.restoreMany(["order-1", "order-2"], orderMachine);
|
|
232
|
+
* console.log(`Restored: ${result.restored.length}, Failed: ${result.failed.length}`);
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
readonly restoreMany: <S extends {
|
|
236
|
+
readonly _tag: string;
|
|
237
|
+
}, E extends {
|
|
238
|
+
readonly _tag: string;
|
|
239
|
+
}, R>(ids: ReadonlyArray<string>, machine: PersistentMachine<S, E, R>) => Effect.Effect<RestoreResult<S, E, R>, never, R | PersistenceAdapterTag>;
|
|
240
|
+
/**
|
|
241
|
+
* Restore all persisted actors for a machine type.
|
|
242
|
+
* Uses adapter registry if available, otherwise returns empty result.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* const result = yield* system.restoreAll(orderMachine, {
|
|
247
|
+
* filter: (meta) => meta.stateTag !== "Done"
|
|
248
|
+
* });
|
|
249
|
+
* console.log(`Restored ${result.restored.length} active orders`);
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
readonly restoreAll: <S extends {
|
|
253
|
+
readonly _tag: string;
|
|
254
|
+
}, E extends {
|
|
255
|
+
readonly _tag: string;
|
|
256
|
+
}, R>(machine: PersistentMachine<S, E, R>, options?: {
|
|
257
|
+
filter?: (meta: ActorMetadata) => boolean;
|
|
258
|
+
}) => Effect.Effect<RestoreResult<S, E, R>, PersistenceError, R | PersistenceAdapterTag>;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* ActorSystem service tag
|
|
262
|
+
*/
|
|
263
|
+
declare const ActorSystem: any;
|
|
264
|
+
/** Listener set for sync subscriptions */
|
|
265
|
+
type Listeners<S> = Set<(state: S) => void>;
|
|
266
|
+
/**
|
|
267
|
+
* Notify all listeners of state change.
|
|
268
|
+
*/
|
|
269
|
+
declare const notifyListeners: <S>(listeners: Listeners<S>, state: S) => void;
|
|
270
|
+
/**
|
|
271
|
+
* Build core ActorRef methods shared between regular and persistent actors.
|
|
272
|
+
*/
|
|
273
|
+
declare const buildActorRefCore: <S extends {
|
|
274
|
+
readonly _tag: string;
|
|
275
|
+
}, E extends {
|
|
276
|
+
readonly _tag: string;
|
|
277
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(id: string, machine: Machine<S, E, R, any, any, GD, EFD>, stateRef: SubscriptionRef.SubscriptionRef<S>, eventQueue: Queue.Queue<E>, stoppedRef: Ref.Ref<boolean>, listeners: Listeners<S>, stop: Effect.Effect<void>, system: ActorSystem, childrenMap: ReadonlyMap<string, ActorRef<AnyState, unknown>>) => ActorRef<S, E>;
|
|
278
|
+
/**
|
|
279
|
+
* Create and start an actor for a machine
|
|
280
|
+
*/
|
|
281
|
+
declare const createActor: <S extends {
|
|
282
|
+
readonly _tag: string;
|
|
283
|
+
}, E extends {
|
|
284
|
+
readonly _tag: string;
|
|
285
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(id: string, machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>) => Effect.Effect<ActorRef<S, E>, unknown, unknown>;
|
|
286
|
+
/**
|
|
287
|
+
* Default ActorSystem layer
|
|
288
|
+
*/
|
|
289
|
+
declare const Default: any;
|
|
290
|
+
//#endregion
|
|
291
|
+
export { ActorRef, ActorSystem, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, SystemEvent, SystemEventListener, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects };
|