@voltro/runtime 0.9.0 → 0.11.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 +394 -7
- package/dist/index.d.ts +96 -5
- package/dist/index.js +1048 -1037
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1662,6 +1662,17 @@ export declare class DeleteBuilder {
|
|
|
1662
1662
|
hard(): Promise<number>;
|
|
1663
1663
|
}
|
|
1664
1664
|
|
|
1665
|
+
/** Row count for a delivered payload, for the trace/metric tap.
|
|
1666
|
+
*
|
|
1667
|
+
* A computed query's value is arbitrary — a scalar, an object, an array, or
|
|
1668
|
+
* nothing at all. Reporting a fixed 1 for all of them (which this used to do)
|
|
1669
|
+
* turned the `rows` attribute into a liveness signal that reads like a data
|
|
1670
|
+
* signal: an `employees.me` that resolved to `null` still traced `rows=1`, and
|
|
1671
|
+
* a downstream consumer used exactly that span to conclude the server had
|
|
1672
|
+
* produced a value when it had not. Absent is 0, a single value is 1, an array
|
|
1673
|
+
* is its length. */
|
|
1674
|
+
export declare const deliveredRowCount: (value: unknown) => number;
|
|
1675
|
+
|
|
1665
1676
|
/**
|
|
1666
1677
|
* Derive a 32-byte AES-256 key from a passphrase via scrypt. A fixed
|
|
1667
1678
|
* salt keeps derivation deterministic across processes (the passphrase
|
|
@@ -1798,6 +1809,15 @@ export declare interface DispatcherDependencies {
|
|
|
1798
1809
|
readonly cache?: SnapshotCache;
|
|
1799
1810
|
}
|
|
1800
1811
|
|
|
1812
|
+
/** Bookkeeping tenant key for the `_voltro_wakeups` rows that dormant schedules
|
|
1813
|
+
* and dormant workflow waits register when their subject carries no tenant.
|
|
1814
|
+
*
|
|
1815
|
+
* NOT a security scope — but it drifted exactly like the subject did: dev keyed
|
|
1816
|
+
* these rows under `$TENANT ?? 'acme'` and serve under `'default'`, in BOTH the
|
|
1817
|
+
* schedule and the workflow wiring, so a wakeup written by one boot path was
|
|
1818
|
+
* invisible to a waker looking under the other's key. */
|
|
1819
|
+
export declare const DORMANCY_WAKEUP_TENANT = "default";
|
|
1820
|
+
|
|
1801
1821
|
export declare interface DrainDeps {
|
|
1802
1822
|
readonly store: Pick<DataStore, 'query' | 'update' | 'insert' | 'delete'>;
|
|
1803
1823
|
readonly handlers: ReadonlyMap<string, OutboxHandlerDefinition>;
|
|
@@ -2752,7 +2772,7 @@ export declare const makeWorkflowFacadeWithCallerContext: (base: WorkflowsAppCon
|
|
|
2752
2772
|
|
|
2753
2773
|
export declare const makeWorkflowHandlers: (workflows: ReadonlyArray<DiscoveredWorkflowLike>, facade?: WorkflowsAppContext) => Record<string, (input: unknown) => Effect.Effect<WorkflowRunHandle, unknown, unknown>>;
|
|
2754
2774
|
|
|
2755
|
-
export declare const makeWorkflowLayers: <Context>(workflows: ReadonlyArray<DiscoveredWorkflowLike<Context>>, options: WorkflowLayerOptions<Context>, wrapExecute?: (workflow: DiscoveredWorkflowLike<Context>, execute: (payload: never, executionId: string) => Effect.Effect<unknown, unknown, unknown>, callerContext:
|
|
2775
|
+
export declare const makeWorkflowLayers: <Context>(workflows: ReadonlyArray<DiscoveredWorkflowLike<Context>>, options: WorkflowLayerOptions<Context>, wrapExecute?: (workflow: DiscoveredWorkflowLike<Context>, execute: (payload: never, executionId: string) => Effect.Effect<unknown, unknown, unknown>, callerContext: ResolvedWorkflowCallerContext) => (payload: never, executionId: string) => Effect.Effect<unknown, unknown, unknown>) => ReadonlyArray<Layer.Layer<unknown, unknown, unknown>>;
|
|
2756
2776
|
|
|
2757
2777
|
export declare const makeWorkflowRunHandle: (workflowName: string, executionId: string) => WorkflowRunHandle;
|
|
2758
2778
|
|
|
@@ -3972,6 +3992,28 @@ export declare interface ResolvedConnection {
|
|
|
3972
3992
|
*/
|
|
3973
3993
|
export declare const resolveDependentTables: (descriptor: QueryDescriptor) => ReadonlySet<string>;
|
|
3974
3994
|
|
|
3995
|
+
/**
|
|
3996
|
+
* A `WorkflowCallerContext` after the engine has filled in what a workflow
|
|
3997
|
+
* always needs. A run started by a request carries the caller's subject; a
|
|
3998
|
+
* BOOTSTRAP run — one resumed after a restart with no recorded start context —
|
|
3999
|
+
* carries `SYSTEM_SUBJECT`.
|
|
4000
|
+
*
|
|
4001
|
+
* The engine resolves this so `buildContext` never has to. When each boot path
|
|
4002
|
+
* supplied its own fallback, `voltro dev` used the dev REQUEST fallback
|
|
4003
|
+
* (`anonymousSubject($TENANT ?? 'acme')`) and `voltro serve` used a tenant-less
|
|
4004
|
+
* subject — the same resumed workflow read one tenant's rows in dev and every
|
|
4005
|
+
* tenant's in production, with no error on either side. Same defect as the
|
|
4006
|
+
* schedule path; found while fixing it.
|
|
4007
|
+
*/
|
|
4008
|
+
export declare interface ResolvedWorkflowCallerContext extends WorkflowCallerContext {
|
|
4009
|
+
/** Never absent — the caller's subject, or `SYSTEM_SUBJECT` for a bootstrap
|
|
4010
|
+
* run. Typed `unknown` to match `WorkflowCallerContext.subject`; the CLI
|
|
4011
|
+
* narrows it to `Subject` at the one place it builds the AppContext. */
|
|
4012
|
+
readonly subject: unknown;
|
|
4013
|
+
/** Never absent — the caller's trace id, or `'workflow-bootstrap'`. */
|
|
4014
|
+
readonly traceId: string;
|
|
4015
|
+
}
|
|
4016
|
+
|
|
3975
4017
|
export declare const resolveRedirectUri: (definition: OAuth2ConnectionDefinition, publicUrl: string) => string;
|
|
3976
4018
|
|
|
3977
4019
|
/** Rebuild the flagged groups from the (already-committed) base rows + merge —
|
|
@@ -4456,6 +4498,19 @@ export declare const sanitizeRedirectTo: (value: string | undefined) => string;
|
|
|
4456
4498
|
* default export without importing the concrete class. */
|
|
4457
4499
|
declare const SCHEDULE_BRAND: unique symbol;
|
|
4458
4500
|
|
|
4501
|
+
/**
|
|
4502
|
+
* Who a schedule runs as — the shared `SYSTEM_SUBJECT` (see its doc comment for
|
|
4503
|
+
* why one definition exists at all).
|
|
4504
|
+
*
|
|
4505
|
+
* What matters HERE is that the ENGINE owns it, not whoever wires the engine.
|
|
4506
|
+
* The two callers owning it separately is exactly what went wrong: `voltro
|
|
4507
|
+
* serve` passed a tenant-less subject while `voltro dev` passed the dev REQUEST
|
|
4508
|
+
* fallback (`anonymousSubject($TENANT ?? 'acme')`) — a value meant for a
|
|
4509
|
+
* login-less HTTP call, which a schedule never is. A `buildContext` that
|
|
4510
|
+
* RECEIVES the subject cannot make that mistake; one that invents it can.
|
|
4511
|
+
*/
|
|
4512
|
+
export declare const SCHEDULE_SUBJECT: Subject;
|
|
4513
|
+
|
|
4459
4514
|
/** What happens to firings missed during downtime (computed on boot
|
|
4460
4515
|
* from the last-fired-at row). */
|
|
4461
4516
|
export declare type ScheduleBackfillPolicy = 'skip' | 'latest' | 'all';
|
|
@@ -4575,14 +4630,17 @@ export declare interface SchedulerDeps {
|
|
|
4575
4630
|
* whose effective trigger is `external` are NOT armed by the timer
|
|
4576
4631
|
* loop — they fire via the HTTP endpoint. */
|
|
4577
4632
|
readonly defaultTrigger: ScheduleTrigger;
|
|
4578
|
-
/** Builds the per-firing AppContext (store +
|
|
4579
|
-
*
|
|
4580
|
-
*
|
|
4633
|
+
/** Builds the per-firing AppContext (store + webhooks). The CLI supplies
|
|
4634
|
+
* this — it knows how to wrap the store with mixin behaviour — but it does
|
|
4635
|
+
* NOT choose the subject: `SCHEDULE_SUBJECT` is handed in, so `voltro dev`
|
|
4636
|
+
* and `voltro serve` cannot disagree about who a cron runs as. */
|
|
4581
4637
|
readonly buildContext: (input: {
|
|
4582
4638
|
readonly traceId: string;
|
|
4583
4639
|
readonly scheduleName: string;
|
|
4584
4640
|
readonly trigger: ScheduleTrigger | 'manual';
|
|
4585
4641
|
readonly runId: string | undefined;
|
|
4642
|
+
/** Always `SCHEDULE_SUBJECT`. Forward it — do not construct one. */
|
|
4643
|
+
readonly subject: Subject;
|
|
4586
4644
|
}) => ScheduleContext['app'];
|
|
4587
4645
|
/** Stable id of this process/replica (pod name, pid, …) recorded on
|
|
4588
4646
|
* every run row for debugging "which instance fired this." */
|
|
@@ -5074,6 +5132,26 @@ export declare interface SubscribeContext {
|
|
|
5074
5132
|
readonly log: SyncLogger;
|
|
5075
5133
|
/** Stable id derived from the file name (no `.subscribe.ts` suffix). */
|
|
5076
5134
|
readonly id: string;
|
|
5135
|
+
/**
|
|
5136
|
+
* The framework's store, for reading or writing in reaction to the commit.
|
|
5137
|
+
*
|
|
5138
|
+
* **Runs as `SYSTEM_SUBJECT` — it is NOT tenant-scoped.** A subscriber fires
|
|
5139
|
+
* from the change stream, not from a request, so there is no subject to scope
|
|
5140
|
+
* to and no tenant to infer; queries see every tenant's rows. When the
|
|
5141
|
+
* reaction is per-tenant, take the tenant from the row that changed
|
|
5142
|
+
* (`event.new?.tenantId ?? event.old?.tenantId`) and filter on it explicitly.
|
|
5143
|
+
* Writes are mixin-stamped exactly as a request-path write is, so `tenantId`
|
|
5144
|
+
* on an inserted row is yours to set — nothing fills it in for you.
|
|
5145
|
+
*
|
|
5146
|
+
* This is the same posture a `*.cron.tsx` handler's `ctx.app.store` has, on
|
|
5147
|
+
* purpose: both are post-request system work, and having them differ is how
|
|
5148
|
+
* the schedule path drifted between `voltro dev` and `voltro serve`.
|
|
5149
|
+
*
|
|
5150
|
+
* Still absent, still deliberate: there is no workflow handle here. A
|
|
5151
|
+
* subscriber is best-effort and non-durable, so "a row changed → start a
|
|
5152
|
+
* workflow" belongs in a `*.reaction.tsx`, whose `act` is crash-safe.
|
|
5153
|
+
*/
|
|
5154
|
+
readonly store: FluentStore;
|
|
5077
5155
|
}
|
|
5078
5156
|
|
|
5079
5157
|
/** Event shape passed to a subscriber handler. Same as the
|
|
@@ -5113,6 +5191,12 @@ export declare interface SubscriptionDelivery {
|
|
|
5113
5191
|
readonly startMs: number;
|
|
5114
5192
|
readonly endMs: number;
|
|
5115
5193
|
readonly durationMs: number;
|
|
5194
|
+
/** How many rows this delivery carried. A row-set subscription reports its
|
|
5195
|
+
* real length; a COMPUTED query has no row set, so it reports 1 for a
|
|
5196
|
+
* delivered value and **0 for `null`/`undefined`** — see `deliveredRowCount`.
|
|
5197
|
+
* It must never be a constant: this number is both the `rows` span attribute
|
|
5198
|
+
* and the Prometheus row histogram, and a hardcoded 1 makes "the handler
|
|
5199
|
+
* returned null" look identical to "the handler returned a value". */
|
|
5116
5200
|
readonly rowCount: number;
|
|
5117
5201
|
}
|
|
5118
5202
|
|
|
@@ -5198,6 +5282,13 @@ export { sweepRetention }
|
|
|
5198
5282
|
*/
|
|
5199
5283
|
export declare const synthesizeInverse: (cs: ChangeSet) => ReadonlyArray<InverseOp>;
|
|
5200
5284
|
|
|
5285
|
+
/** The Subject non-request work runs as: a schedule firing, a workflow resumed
|
|
5286
|
+
* after a restart, a `*.subscribe.ts` handler. `tenantId: null` means
|
|
5287
|
+
* `applyTenantScope` adds no tenant filter, so system work sees every tenant
|
|
5288
|
+
* rather than one arbitrary one. See this file's header for why it is a single
|
|
5289
|
+
* shared value. */
|
|
5290
|
+
export declare const SYSTEM_SUBJECT: Subject;
|
|
5291
|
+
|
|
5201
5292
|
/** The context handed to a `runAsSystem` block. Mirrors the handler-facing
|
|
5202
5293
|
* shape: a fluent, system-scoped `store` + the resolved `subject`. */
|
|
5203
5294
|
export declare interface SystemContext {
|
|
@@ -5936,7 +6027,7 @@ export declare interface WorkflowLayerExecutionContext {
|
|
|
5936
6027
|
}
|
|
5937
6028
|
|
|
5938
6029
|
export declare interface WorkflowLayerOptions<Context> {
|
|
5939
|
-
readonly buildContext: (callerContext:
|
|
6030
|
+
readonly buildContext: (callerContext: ResolvedWorkflowCallerContext, execution: WorkflowLayerExecutionContext) => Context;
|
|
5940
6031
|
readonly resolveStartContext?: (workflowName: string, executionId: string) => WorkflowCallerContext | undefined | Promise<WorkflowCallerContext | undefined>;
|
|
5941
6032
|
}
|
|
5942
6033
|
|