@rotorsoft/act 1.33.0 → 1.33.1
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/.tsbuildinfo +1 -1
- package/dist/@types/act.d.ts +59 -156
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/types/act.d.ts +4 -6
- package/dist/@types/types/act.d.ts.map +1 -1
- package/dist/@types/types/action.d.ts +2 -2
- package/dist/@types/types/builders.d.ts +2 -3
- package/dist/@types/types/builders.d.ts.map +1 -1
- package/dist/@types/types/ports.d.ts +5 -9
- package/dist/@types/types/ports.d.ts.map +1 -1
- package/dist/{chunk-HF433MAF.cjs → chunk-NNWP65YM.cjs} +1 -1
- package/dist/chunk-NNWP65YM.cjs.map +1 -0
- package/dist/{chunk-JABYJGT7.js → chunk-NYH6FNTM.js} +2 -2
- package/dist/{chunk-2PMUONGF.js → chunk-TJ4JRRUR.js} +1 -1
- package/dist/chunk-TJ4JRRUR.js.map +1 -0
- package/dist/{chunk-VE3MTY4A.cjs → chunk-YKL44PYX.cjs} +14 -14
- package/dist/{chunk-VE3MTY4A.cjs.map → chunk-YKL44PYX.cjs.map} +1 -1
- package/dist/index.cjs +197 -287
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +57 -147
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs +4 -4
- package/dist/test/index.js +2 -2
- package/dist/types/index.cjs +2 -2
- package/dist/types/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-2PMUONGF.js.map +0 -1
- package/dist/chunk-HF433MAF.cjs.map +0 -1
- /package/dist/{chunk-JABYJGT7.js.map → chunk-NYH6FNTM.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
sleep,
|
|
41
41
|
store,
|
|
42
42
|
validate
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-NYH6FNTM.js";
|
|
44
44
|
import {
|
|
45
45
|
ActorSchema,
|
|
46
46
|
CausationEventSchema,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
pii_fields,
|
|
71
71
|
pii_schemas,
|
|
72
72
|
sensitive
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-TJ4JRRUR.js";
|
|
74
74
|
|
|
75
75
|
// src/signals.ts
|
|
76
76
|
process.once("SIGINT", async (arg) => {
|
|
@@ -3187,21 +3187,14 @@ var Act = class {
|
|
|
3187
3187
|
}
|
|
3188
3188
|
_shutdown_promise;
|
|
3189
3189
|
/**
|
|
3190
|
-
* Per-instance teardown:
|
|
3191
|
-
*
|
|
3192
|
-
* listeners and
|
|
3190
|
+
* Per-instance teardown: stops scheduling, gives the cycles in flight up
|
|
3191
|
+
* to `graceMs` to reach their `ack` (an abandoned handler holds its lease
|
|
3192
|
+
* until it expires), then removes listeners and the notify subscription.
|
|
3193
|
+
* The budget is a ceiling, not a delay.
|
|
3193
3194
|
*
|
|
3194
|
-
*
|
|
3195
|
-
*
|
|
3196
|
-
*
|
|
3197
|
-
* finished during it. The budget is a ceiling, not a delay; when it runs
|
|
3198
|
-
* out, teardown proceeds anyway.
|
|
3199
|
-
*
|
|
3200
|
-
* Idempotent — repeated calls return the same promise, and the first
|
|
3201
|
-
* call's `graceMs` is the one that applies. Registered automatically with
|
|
3202
|
-
* the global `dispose()` registry at construction, so process-wide
|
|
3203
|
-
* `dispose()()` covers it; test helpers (or operators that mint
|
|
3204
|
-
* short-lived Acts) call it explicitly for prompt cleanup.
|
|
3195
|
+
* Idempotent: repeated calls return the same promise, with the first
|
|
3196
|
+
* call's `graceMs`. Registered with the global `dispose()` registry, so
|
|
3197
|
+
* `dispose()()` covers it; call it directly for prompt cleanup.
|
|
3205
3198
|
*
|
|
3206
3199
|
* @param options - See {@link ShutdownOptions}. Defaults the grace budget
|
|
3207
3200
|
* to the largest lane `leaseMillis` (capped at 30s).
|
|
@@ -3279,15 +3272,10 @@ var Act = class {
|
|
|
3279
3272
|
}
|
|
3280
3273
|
}
|
|
3281
3274
|
/**
|
|
3282
|
-
* Executes an action
|
|
3283
|
-
*
|
|
3284
|
-
*
|
|
3285
|
-
*
|
|
3286
|
-
* 2. Loads the current state snapshot
|
|
3287
|
-
* 3. Checks invariants (business rules)
|
|
3288
|
-
* 4. Executes the action handler to generate events
|
|
3289
|
-
* 5. Applies events to create new state
|
|
3290
|
-
* 6. Commits events to the store with optimistic concurrency control
|
|
3275
|
+
* Executes an action: validates the payload, loads the state, checks its
|
|
3276
|
+
* invariants, and commits the events its handler emits, with optimistic
|
|
3277
|
+
* concurrency on the stream. The reactions to those events settle on
|
|
3278
|
+
* their own (unless `autoSettle: false`).
|
|
3291
3279
|
*
|
|
3292
3280
|
* @template TKey - Action name from registered actions
|
|
3293
3281
|
* @param action - The name of the action to execute
|
|
@@ -3366,9 +3354,7 @@ var Act = class {
|
|
|
3366
3354
|
*
|
|
3367
3355
|
* For small result sets, consider using {@link query_array} instead.
|
|
3368
3356
|
*
|
|
3369
|
-
* @param query - Filter criteria
|
|
3370
|
-
* (`stream`, `name`, `after`, `before`, `created_after`, `created_before`,
|
|
3371
|
-
* `limit`, `with_snaps`, `stream_exact`)
|
|
3357
|
+
* @param query - Filter criteria; see {@link Query} for the fields
|
|
3372
3358
|
* @param callback - Optional callback invoked for each matching event
|
|
3373
3359
|
* @returns Object with first event, last event, and total count
|
|
3374
3360
|
*
|
|
@@ -3452,31 +3438,23 @@ var Act = class {
|
|
|
3452
3438
|
});
|
|
3453
3439
|
}
|
|
3454
3440
|
/**
|
|
3455
|
-
*
|
|
3456
|
-
*
|
|
3457
|
-
*
|
|
3458
|
-
* 1. Polls the store for streams with uncommitted events
|
|
3459
|
-
* 2. Leases streams to prevent concurrent processing
|
|
3460
|
-
* 3. Fetches events for each leased stream
|
|
3461
|
-
* 4. Executes matching reaction handlers
|
|
3462
|
-
* 5. Acknowledges successful reactions or blocks failing ones
|
|
3441
|
+
* Runs one drain cycle: claims streams with marked work (leasing them),
|
|
3442
|
+
* fetches their events, runs the matching reactions, and acks or blocks
|
|
3443
|
+
* each stream.
|
|
3463
3444
|
*
|
|
3464
|
-
*
|
|
3465
|
-
*
|
|
3466
|
-
*
|
|
3467
|
-
*
|
|
3468
|
-
*
|
|
3469
|
-
* `correlate` is the only component that raises that mark, so a
|
|
3470
|
-
* commit no correlate has seen is not drainable, static targets included. For a
|
|
3471
|
-
* higher-level API that handles debouncing, correlation, and signaling
|
|
3472
|
-
* automatically, use {@link settle}.
|
|
3445
|
+
* A stream is claimable only once `correlate()` has marked it, static
|
|
3446
|
+
* targets included, so a commit no correlate has seen is not drainable.
|
|
3447
|
+
* Apps rarely call this: each commit settles its reactions on its own.
|
|
3448
|
+
* With `autoSettle: false`, tests walk the pipeline with `correlate()`
|
|
3449
|
+
* then `drain()` (see the testing guide).
|
|
3473
3450
|
*
|
|
3474
3451
|
* @param options - Drain configuration — see {@link DrainOptions} for fields
|
|
3475
3452
|
* (`streamLimit`, `eventLimit`, `leaseMillis`).
|
|
3476
3453
|
* @returns Drain statistics with fetched, leased, acked, and blocked counts
|
|
3477
3454
|
*
|
|
3478
|
-
* @example
|
|
3455
|
+
* @example Walking the pipeline in a test
|
|
3479
3456
|
* ```typescript
|
|
3457
|
+
* const app = act().withState(User).withProjection(Users).build({ autoSettle: false });
|
|
3480
3458
|
* await app.do("createUser", target, payload);
|
|
3481
3459
|
* await app.correlate();
|
|
3482
3460
|
* await app.drain();
|
|
@@ -3484,7 +3462,6 @@ var Act = class {
|
|
|
3484
3462
|
*
|
|
3485
3463
|
* @see {@link settle} for debounced correlate→drain with lifecycle events
|
|
3486
3464
|
* @see {@link correlate} for dynamic stream discovery
|
|
3487
|
-
* @see {@link start_correlations} for automatic correlation
|
|
3488
3465
|
*/
|
|
3489
3466
|
async drain(options = {}) {
|
|
3490
3467
|
resolveDrainConfig(options);
|
|
@@ -3551,32 +3528,20 @@ var Act = class {
|
|
|
3551
3528
|
return { fetched, leased, acked, blocked };
|
|
3552
3529
|
}
|
|
3553
3530
|
/**
|
|
3554
|
-
*
|
|
3555
|
-
*
|
|
3556
|
-
*
|
|
3557
|
-
* based on event content. For example, you might create a stats stream for each user
|
|
3558
|
-
* when they perform certain actions.
|
|
3559
|
-
*
|
|
3560
|
-
* This method scans events matching the query and identifies new target streams based
|
|
3561
|
-
* on reaction resolvers. It then registers these streams so they'll be picked up by
|
|
3562
|
-
* the next drain cycle.
|
|
3531
|
+
* Scans committed events from the correlation checkpoint, subscribes the
|
|
3532
|
+
* target streams their reactions resolve to (static or computed from
|
|
3533
|
+
* the event), and marks their work so the next drain can claim it.
|
|
3563
3534
|
*
|
|
3564
3535
|
* @param query - Scan filter — see {@link Query} for fields (typically
|
|
3565
|
-
* `{
|
|
3536
|
+
* `{ limit: <count> }`; the scan starts at the checkpoint)
|
|
3566
3537
|
* @returns The number of newly subscribed streams and the last scanned event id
|
|
3567
3538
|
*
|
|
3568
3539
|
* @example Manual correlation
|
|
3569
3540
|
* ```typescript
|
|
3570
|
-
*
|
|
3571
|
-
* const { subscribed, last_id } = await app.correlate({ after: 0, limit: 100 });
|
|
3572
|
-
* console.log(`Subscribed ${subscribed} new streams`);
|
|
3573
|
-
*
|
|
3574
|
-
* // Save last_id for next scan
|
|
3575
|
-
* await saveCheckpoint(last_id);
|
|
3541
|
+
* const { subscribed } = await app.correlate({ limit: 100 });
|
|
3576
3542
|
* ```
|
|
3577
3543
|
*
|
|
3578
3544
|
* @see {@link start_correlations} for automatic periodic correlation
|
|
3579
|
-
* @see {@link stop_correlations} to stop automatic correlation
|
|
3580
3545
|
*/
|
|
3581
3546
|
async correlate(query = { after: -1, limit: 10 }) {
|
|
3582
3547
|
const { subscribed, last_id } = await this._correlate_scanned(query);
|
|
@@ -3656,15 +3621,13 @@ var Act = class {
|
|
|
3656
3621
|
* events through their reactions.
|
|
3657
3622
|
*
|
|
3658
3623
|
* Use this to replay events through projections (or other reaction targets)
|
|
3659
|
-
* after changing handler logic.
|
|
3660
|
-
*
|
|
3661
|
-
*
|
|
3662
|
-
*
|
|
3663
|
-
*
|
|
3664
|
-
*
|
|
3665
|
-
*
|
|
3666
|
-
* give that pass batch options, or
|
|
3667
|
-
* `correlate()` / `drain()` to drive the replay by hand.
|
|
3624
|
+
* after changing handler logic. It rewinds the same watermarks as
|
|
3625
|
+
* `store().reset(streams)`, and also wakes the drain and schedules a
|
|
3626
|
+
* settle, which loops correlate→drain until the replay catches up;
|
|
3627
|
+
* `store().reset(...)` alone leaves a settled app idle. Call
|
|
3628
|
+
* `app.settle(options)` right after to give that pass batch options, or,
|
|
3629
|
+
* with `autoSettle: false`, `correlate()` / `drain()` to drive the replay
|
|
3630
|
+
* by hand.
|
|
3668
3631
|
*
|
|
3669
3632
|
* @param input - Reaction target streams (e.g., projection names) to reset, or a {@link StreamFilter} for bulk operations
|
|
3670
3633
|
* @returns Count of streams that were actually reset
|
|
@@ -3823,45 +3786,20 @@ var Act = class {
|
|
|
3823
3786
|
});
|
|
3824
3787
|
}
|
|
3825
3788
|
/**
|
|
3826
|
-
* Operator-driven store audit
|
|
3827
|
-
*
|
|
3828
|
-
*
|
|
3829
|
-
*
|
|
3830
|
-
* driven category as `app.close()` / `app.reset()` /
|
|
3831
|
-
* `app.unblock()` / `app.blocked_streams()`: never auto-invoked by
|
|
3832
|
-
* the framework; the operator decides when to run it (CI gate,
|
|
3833
|
-
* scheduled job, ad-hoc forensics) and what to do with the
|
|
3834
|
-
* findings.
|
|
3789
|
+
* Operator-driven store audit: walks the store and yields findings per
|
|
3790
|
+
* category, each with the remediation it suggests. Never run by the
|
|
3791
|
+
* framework. Pass a subset of categories to scope the work; the iterable
|
|
3792
|
+
* can be broken early, and findings stream without buffering the report.
|
|
3835
3793
|
*
|
|
3836
|
-
*
|
|
3837
|
-
*
|
|
3794
|
+
* @param categories - Subset of categories to run (default: all).
|
|
3795
|
+
* @param options - Query window + per-category thresholds.
|
|
3796
|
+
* @returns Async iterable of {@link AuditFinding}.
|
|
3838
3797
|
*
|
|
3798
|
+
* @example Schema drift since the last scan
|
|
3839
3799
|
* ```typescript
|
|
3840
|
-
*
|
|
3841
|
-
* for await (const f of app.audit(["schema", "deprecated-load"], {
|
|
3842
|
-
* query: { created_after: lastScan },
|
|
3843
|
-
* thresholds: { deprecatedLoadShareMin: 0.10 },
|
|
3844
|
-
* })) {
|
|
3800
|
+
* for await (const f of app.audit(["schema"], { query: { created_after: lastScan } }))
|
|
3845
3801
|
* await escalate(f);
|
|
3846
|
-
* }
|
|
3847
|
-
*
|
|
3848
|
-
* // Full audit, default thresholds
|
|
3849
|
-
* for await (const f of app.audit()) console.log(f);
|
|
3850
3802
|
* ```
|
|
3851
|
-
*
|
|
3852
|
-
* Returns an `AsyncIterable` so callers can `break` early — the
|
|
3853
|
-
* underlying store paginations respect the iterator protocol and
|
|
3854
|
-
* stop cleanly. Each finding is emitted independently, so
|
|
3855
|
-
* pipelining into Slack / persistence / further analysis works
|
|
3856
|
-
* without buffering the full report in memory.
|
|
3857
|
-
*
|
|
3858
|
-
* Findings shape — see {@link AuditFinding}. The discriminated
|
|
3859
|
-
* union carries enough context for the operator to act on each
|
|
3860
|
-
* finding directly: stream id, event id, recommendation hints.
|
|
3861
|
-
*
|
|
3862
|
-
* @param categories - Subset of categories to run (default: all).
|
|
3863
|
-
* @param options - Query window + per-category thresholds.
|
|
3864
|
-
* @returns Async iterable of {@link AuditFinding}.
|
|
3865
3803
|
*/
|
|
3866
3804
|
async *audit(categories, options) {
|
|
3867
3805
|
const it = audit(this._audit_deps, categories, options)[Symbol.asyncIterator]();
|
|
@@ -3872,22 +3810,13 @@ var Act = class {
|
|
|
3872
3810
|
}
|
|
3873
3811
|
}
|
|
3874
3812
|
/**
|
|
3875
|
-
*
|
|
3876
|
-
*
|
|
3877
|
-
*
|
|
3878
|
-
*
|
|
3879
|
-
*
|
|
3880
|
-
* job should yield slots back to the rest. Build-time priorities
|
|
3881
|
-
* (set via the resolver's `priority` field) are subject to a
|
|
3882
|
-
* `max()` invariant across reactions; this API ignores that and
|
|
3883
|
-
* sets the priority outright on every matching row.
|
|
3884
|
-
*
|
|
3885
|
-
* Filter shape mirrors {@link query} / {@link Store.query_streams}:
|
|
3886
|
-
* `stream` / `source` are regex by default, exact with the
|
|
3887
|
-
* `*_exact` flags; `blocked` restricts to blocked or unblocked
|
|
3888
|
-
* rows. **An empty filter (`{}`) updates every registered stream.**
|
|
3813
|
+
* Sets the scheduling priority of every stream matching `filter`, as-is:
|
|
3814
|
+
* unlike build-time priorities (the highest across reactions wins), this
|
|
3815
|
+
* overrides them. Useful to let a long replay jump ahead of other lagging
|
|
3816
|
+
* streams, or to yield slots back. **An empty filter (`{}`) updates every
|
|
3817
|
+
* registered stream.**
|
|
3889
3818
|
*
|
|
3890
|
-
* @param filter - Selection criteria (regex by default).
|
|
3819
|
+
* @param filter - Selection criteria (regex by default, like {@link query}).
|
|
3891
3820
|
* @param priority - New priority value. Set as-is — no clamp.
|
|
3892
3821
|
* @returns Count of streams whose priority changed.
|
|
3893
3822
|
*
|
|
@@ -3897,7 +3826,6 @@ var Act = class {
|
|
|
3897
3826
|
* ```
|
|
3898
3827
|
*
|
|
3899
3828
|
* @see {@link Store.prioritize} for the underlying primitive
|
|
3900
|
-
* @see {@link claim} for how priority biases scheduling
|
|
3901
3829
|
*/
|
|
3902
3830
|
async prioritize(filter, priority) {
|
|
3903
3831
|
return this._scoped(() => store().prioritize(filter, priority));
|
|
@@ -3924,30 +3852,12 @@ var Act = class {
|
|
|
3924
3852
|
return result;
|
|
3925
3853
|
}
|
|
3926
3854
|
/**
|
|
3927
|
-
* Close the books
|
|
3928
|
-
*
|
|
3929
|
-
*
|
|
3930
|
-
*
|
|
3931
|
-
*
|
|
3932
|
-
*
|
|
3933
|
-
* 3. **Guard** — commit `__tombstone__` with `expectedVersion` to block concurrent writes
|
|
3934
|
-
* 4. **Load state** — for streams in `snapshots`, load final state while guarded (no races)
|
|
3935
|
-
* 5. **Archive** — user callback per stream (abort-all on failure, streams are guarded)
|
|
3936
|
-
* 6. **Truncate + seed** — atomic: delete all events, insert `__snapshot__` or `__tombstone__`
|
|
3937
|
-
* 7. **Cache** — invalidate (tombstoned) or warm (restarted)
|
|
3938
|
-
* 8. **Emit "closed"** — lifecycle event with results
|
|
3939
|
-
*
|
|
3940
|
-
* Targets carrying `before` take the **windowed** branch instead —
|
|
3941
|
-
* close the books on a rolling window: probe the min consumer
|
|
3942
|
-
* watermark (so the boundary never rises past a lagging reaction),
|
|
3943
|
-
* run the archive callback against the cutoff, then prune the prefix
|
|
3944
|
-
* below the closest safe `__snapshot__`. No tombstone guard (the
|
|
3945
|
-
* pre-cutoff prefix is immutable), no seed, cache untouched — the
|
|
3946
|
-
* stream stays live and keeps accepting actions. Requires the state
|
|
3947
|
-
* to snapshot via `.snap(...)`; no qualifying snapshot ⇒ the stream
|
|
3948
|
-
* lands in `skipped` (retry after the next snapshot). Windowed
|
|
3949
|
-
* entries in the result echo `before` and carry the surviving
|
|
3950
|
-
* boundary snapshot as `committed`.
|
|
3855
|
+
* Close the books: guard, archive, truncate, and optionally restart
|
|
3856
|
+
* streams. A stream with pending reactions is skipped; an archive
|
|
3857
|
+
* failure aborts the whole close while the streams are still guarded.
|
|
3858
|
+
* Targets carrying `before` prune a rolling window instead and leave the
|
|
3859
|
+
* stream live (needs `.snap(...)`). The phases and their failure
|
|
3860
|
+
* semantics are in the close-cycle architecture page.
|
|
3951
3861
|
*
|
|
3952
3862
|
* @param targets - Per-stream close options (stream, restart?, archive?, before?)
|
|
3953
3863
|
* @returns `{ truncated: TruncateResult, skipped: string[] }`
|