@shware/workflow 6.1.1 → 8.0.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/README.md +132 -35
- package/dist/aws/engine-step.cjs +4 -1
- package/dist/aws/engine-step.cjs.map +1 -1
- package/dist/aws/engine-step.d.cts.map +1 -1
- package/dist/aws/engine-step.d.mts.map +1 -1
- package/dist/aws/engine-step.mjs +4 -1
- package/dist/aws/engine-step.mjs.map +1 -1
- package/dist/aws/index.cjs +3 -2
- package/dist/aws/index.cjs.map +1 -1
- package/dist/aws/index.mjs +3 -2
- package/dist/aws/index.mjs.map +1 -1
- package/dist/client.cjs +66 -41
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +72 -22
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.mts +72 -22
- package/dist/client.d.mts.map +1 -1
- package/dist/client.mjs +66 -42
- package/dist/client.mjs.map +1 -1
- package/dist/cloudflare/index.d.cts +4 -3
- package/dist/cloudflare/index.d.mts +4 -3
- package/dist/cloudflare/runner.cjs +3 -1
- package/dist/cloudflare/runner.cjs.map +1 -1
- package/dist/cloudflare/runner.d.cts.map +1 -1
- package/dist/cloudflare/runner.d.mts.map +1 -1
- package/dist/cloudflare/runner.mjs +3 -1
- package/dist/cloudflare/runner.mjs.map +1 -1
- package/dist/cloudflare/worker.cjs +13 -2
- package/dist/cloudflare/worker.cjs.map +1 -1
- package/dist/cloudflare/worker.d.cts +9 -1
- package/dist/cloudflare/worker.d.cts.map +1 -1
- package/dist/cloudflare/worker.d.mts +9 -1
- package/dist/cloudflare/worker.d.mts.map +1 -1
- package/dist/cloudflare/worker.mjs +13 -2
- package/dist/cloudflare/worker.mjs.map +1 -1
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +4 -4
- package/dist/contract.d.mts +4 -4
- package/dist/contract.mjs.map +1 -1
- package/dist/dsl/trigger.cjs +2 -1
- package/dist/dsl/trigger.cjs.map +1 -1
- package/dist/dsl/trigger.d.cts +6 -0
- package/dist/dsl/trigger.d.cts.map +1 -1
- package/dist/dsl/trigger.d.mts +6 -0
- package/dist/dsl/trigger.d.mts.map +1 -1
- package/dist/dsl/trigger.mjs +2 -1
- package/dist/dsl/trigger.mjs.map +1 -1
- package/dist/email-sender.cjs +8 -1
- package/dist/email-sender.cjs.map +1 -1
- package/dist/email-sender.d.cts +2 -2
- package/dist/email-sender.d.cts.map +1 -1
- package/dist/email-sender.d.mts +2 -2
- package/dist/email-sender.d.mts.map +1 -1
- package/dist/email-sender.mjs +9 -2
- package/dist/email-sender.mjs.map +1 -1
- package/dist/email.cjs +5 -0
- package/dist/email.cjs.map +1 -1
- package/dist/email.d.cts +2 -0
- package/dist/email.d.cts.map +1 -1
- package/dist/email.d.mts +2 -0
- package/dist/email.d.mts.map +1 -1
- package/dist/email.mjs +5 -1
- package/dist/email.mjs.map +1 -1
- package/dist/engine/condition.cjs +7 -5
- package/dist/engine/condition.cjs.map +1 -1
- package/dist/engine/condition.d.cts +3 -3
- package/dist/engine/condition.d.cts.map +1 -1
- package/dist/engine/condition.d.mts +3 -3
- package/dist/engine/condition.d.mts.map +1 -1
- package/dist/engine/condition.mjs +7 -5
- package/dist/engine/condition.mjs.map +1 -1
- package/dist/engine/interpreter.cjs +11 -6
- package/dist/engine/interpreter.cjs.map +1 -1
- package/dist/engine/interpreter.d.cts.map +1 -1
- package/dist/engine/interpreter.d.mts.map +1 -1
- package/dist/engine/interpreter.mjs +11 -6
- package/dist/engine/interpreter.mjs.map +1 -1
- package/dist/engine/ports.d.cts +21 -3
- package/dist/engine/ports.d.cts.map +1 -1
- package/dist/engine/ports.d.mts +21 -3
- package/dist/engine/ports.d.mts.map +1 -1
- package/dist/host/batch.cjs +172 -0
- package/dist/host/batch.cjs.map +1 -0
- package/dist/host/batch.d.cts +88 -0
- package/dist/host/batch.d.cts.map +1 -0
- package/dist/host/batch.d.mts +88 -0
- package/dist/host/batch.d.mts.map +1 -0
- package/dist/host/batch.mjs +163 -0
- package/dist/host/batch.mjs.map +1 -0
- package/dist/host/execute.cjs +10 -6
- package/dist/host/execute.cjs.map +1 -1
- package/dist/host/execute.mjs +10 -6
- package/dist/host/execute.mjs.map +1 -1
- package/dist/host/http.cjs +31 -90
- package/dist/host/http.cjs.map +1 -1
- package/dist/host/http.d.cts +4 -2
- package/dist/host/http.d.cts.map +1 -1
- package/dist/host/http.d.mts +4 -2
- package/dist/host/http.d.mts.map +1 -1
- package/dist/host/http.mjs +25 -84
- package/dist/host/http.mjs.map +1 -1
- package/dist/host/ingest.cjs +164 -25
- package/dist/host/ingest.cjs.map +1 -1
- package/dist/host/ingest.d.cts +38 -8
- package/dist/host/ingest.d.cts.map +1 -1
- package/dist/host/ingest.d.mts +38 -8
- package/dist/host/ingest.d.mts.map +1 -1
- package/dist/host/ingest.mjs +161 -26
- package/dist/host/ingest.mjs.map +1 -1
- package/dist/host/journey-host.cjs +8 -1
- package/dist/host/journey-host.cjs.map +1 -1
- package/dist/host/journey-host.d.cts +10 -4
- package/dist/host/journey-host.d.cts.map +1 -1
- package/dist/host/journey-host.d.mts +10 -4
- package/dist/host/journey-host.d.mts.map +1 -1
- package/dist/host/journey-host.mjs +8 -1
- package/dist/host/journey-host.mjs.map +1 -1
- package/dist/host/platform.cjs.map +1 -1
- package/dist/host/platform.d.cts +2 -0
- package/dist/host/platform.d.cts.map +1 -1
- package/dist/host/platform.d.mts +2 -0
- package/dist/host/platform.d.mts.map +1 -1
- package/dist/host/platform.mjs.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/ir.cjs +2 -1
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +3 -0
- package/dist/ir.d.cts.map +1 -1
- package/dist/ir.d.mts +3 -0
- package/dist/ir.d.mts.map +1 -1
- package/dist/ir.mjs +2 -1
- package/dist/ir.mjs.map +1 -1
- package/dist/reporting/observer.cjs +1 -0
- package/dist/reporting/observer.cjs.map +1 -1
- package/dist/reporting/observer.mjs +1 -0
- package/dist/reporting/observer.mjs.map +1 -1
- package/dist/store/facts.cjs +29 -9
- package/dist/store/facts.cjs.map +1 -1
- package/dist/store/facts.d.cts +7 -2
- package/dist/store/facts.d.cts.map +1 -1
- package/dist/store/facts.d.mts +7 -2
- package/dist/store/facts.d.mts.map +1 -1
- package/dist/store/facts.mjs +29 -9
- package/dist/store/facts.mjs.map +1 -1
- package/dist/store/identity.cjs +34 -0
- package/dist/store/identity.cjs.map +1 -0
- package/dist/store/identity.d.cts +13 -0
- package/dist/store/identity.d.cts.map +1 -0
- package/dist/store/identity.d.mts +13 -0
- package/dist/store/identity.d.mts.map +1 -0
- package/dist/store/identity.mjs +30 -0
- package/dist/store/identity.mjs.map +1 -0
- package/dist/store/index.cjs +5 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +119 -25
- package/dist/store/index.d.cts.map +1 -1
- package/dist/store/index.d.mts +119 -25
- package/dist/store/index.d.mts.map +1 -1
- package/dist/store/index.mjs +2 -1
- package/dist/store/index.mjs.map +1 -1
- package/dist/store/postgres-reporting.cjs +4 -0
- package/dist/store/postgres-reporting.cjs.map +1 -1
- package/dist/store/postgres-reporting.d.cts +1 -0
- package/dist/store/postgres-reporting.d.cts.map +1 -1
- package/dist/store/postgres-reporting.d.mts +1 -0
- package/dist/store/postgres-reporting.d.mts.map +1 -1
- package/dist/store/postgres-reporting.mjs +4 -0
- package/dist/store/postgres-reporting.mjs.map +1 -1
- package/dist/store/postgres.cjs +271 -55
- package/dist/store/postgres.cjs.map +1 -1
- package/dist/store/postgres.d.cts +29 -7
- package/dist/store/postgres.d.cts.map +1 -1
- package/dist/store/postgres.d.mts +29 -7
- package/dist/store/postgres.d.mts.map +1 -1
- package/dist/store/postgres.mjs +272 -56
- package/dist/store/postgres.mjs.map +1 -1
- package/dist/store/tables.cjs +28 -9
- package/dist/store/tables.cjs.map +1 -1
- package/dist/store/tables.d.cts +1 -0
- package/dist/store/tables.d.cts.map +1 -1
- package/dist/store/tables.d.mts +1 -0
- package/dist/store/tables.d.mts.map +1 -1
- package/dist/store/tables.mjs +28 -9
- package/dist/store/tables.mjs.map +1 -1
- package/dist/webpush.cjs.map +1 -1
- package/dist/webpush.d.cts +1 -1
- package/dist/webpush.d.mts +1 -1
- package/dist/webpush.mjs.map +1 -1
- package/package.json +1 -1
package/dist/host/ingest.d.cts
CHANGED
|
@@ -56,6 +56,25 @@ export interface SweepResult {
|
|
|
56
56
|
size: number;
|
|
57
57
|
}[];
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* How long an entry may wait for its runner's admission before maintenance looks for its
|
|
61
|
+
* instance. A create takes well under a second and a queued instance is found by `get`, so this
|
|
62
|
+
* only has to outlast a create still in flight — generously, since a wrong call fails a journey.
|
|
63
|
+
*/
|
|
64
|
+
export declare const LOST_START_AFTER_MS: number;
|
|
65
|
+
/**
|
|
66
|
+
* Starts lost between the entry and the platform's create — the Worker cut off there, or a
|
|
67
|
+
* create that failed with its rollback failing too — leave a `running` entry nothing will ever
|
|
68
|
+
* admit, and the once-policy would then bar the user from the workflow for good. An instance that
|
|
69
|
+
* ended before admitting itself leaves the same. An entry old enough, unadmitted, whose instance
|
|
70
|
+
* the runtime does not know or reports ended, is marked `failed`: the pair's next trigger reclaims
|
|
71
|
+
* it. Nothing of such an instance ran, since admission precedes its first effect. Platform-neutral:
|
|
72
|
+
* on AWS a planned start is always known to `get` (its registry row), and reads as ended only once
|
|
73
|
+
* its retries have given up, so only a start with nothing behind it is touched.
|
|
74
|
+
*/
|
|
75
|
+
export declare function failLostStarts(env: JourneyEnv, store: JourneyStore, now: number): Promise<string[]>;
|
|
76
|
+
/** How long a visitor who never signs in is kept after they were last heard from. */
|
|
77
|
+
export declare const VISITOR_RETENTION_MS: number;
|
|
59
78
|
/** How many users one sweep page evaluates: a unit of resumable work (AWS checkpoints each). */
|
|
60
79
|
export declare const SWEEP_PAGE_SIZE = 500;
|
|
61
80
|
/**
|
|
@@ -106,17 +125,26 @@ export interface IdentifyResult {
|
|
|
106
125
|
* and re-evaluate segment triggers. The merge is one statement in the store, so
|
|
107
126
|
* two identifies landing together cannot lose each other's fields.
|
|
108
127
|
*/
|
|
109
|
-
export declare function identifyUser(env: JourneyEnv, userId: string, props: ProfileProps, store: JourneyStore
|
|
128
|
+
export declare function identifyUser(env: JourneyEnv, userId: string, props: ProfileProps, store: JourneyStore,
|
|
129
|
+
/** When these values were read; a property written later stays. The Worker's clock by default. */
|
|
130
|
+
at?: number): Promise<IdentifyResult>;
|
|
110
131
|
export interface DeviceRegistration {
|
|
111
|
-
|
|
132
|
+
deviceId?: string | undefined;
|
|
133
|
+
userId?: string | undefined;
|
|
134
|
+
visitorId?: string | undefined;
|
|
112
135
|
token: string;
|
|
113
136
|
platform: string;
|
|
114
|
-
ts?: number;
|
|
115
137
|
}
|
|
116
138
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
139
|
+
* The visitor signed in as the user: what the engine knows of them moves to the user, once. Their
|
|
140
|
+
* journeys carry on as the user's (`instanceOwner`), except one the user is already in, which
|
|
141
|
+
* stops. Answers nothing to do when already linked: every signed-in batch names its visitor.
|
|
142
|
+
*/
|
|
143
|
+
export declare function linkVisitor(env: JourneyEnv, visitorId: string, userId: string, store: JourneyStore, at?: number): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* A push token registered for its current owner: the user, or before sign-in the visitor. The
|
|
146
|
+
* device holds only that, so a token moves to whoever registered it last. Wakes the waits that read
|
|
147
|
+
* devices (`reachable('push')` inside `waitUntil`), for the new owner and the previous one.
|
|
120
148
|
*/
|
|
121
149
|
export declare function registerDevice(env: JourneyEnv, device: DeviceRegistration, store: JourneyStore): Promise<{
|
|
122
150
|
ok: true;
|
|
@@ -177,9 +205,11 @@ export declare class BundleIntegrityError extends Error {
|
|
|
177
205
|
* Bundle deploy, terraform-apply style: workflow bodies first (content-addressed, so a failed
|
|
178
206
|
* deploy leaves only harmless orphans), then the routing swap. With a `version` the swap happens
|
|
179
207
|
* only over an older live version (`replaceRoutesIfNewer`) — how journeyWorker applies the bundle
|
|
180
|
-
* compiled into it
|
|
208
|
+
* compiled into it — unless `force` is set: then it happens whatever is live, and the version is
|
|
209
|
+
* recorded as live (`POST /bundle/deploy`). Without a version it is forced and records nothing
|
|
210
|
+
* (`POST /deploy`, a hand-posted bundle).
|
|
181
211
|
*/
|
|
182
|
-
export declare function deployBundle(env: JourneyEnv, bundle: unknown, store: JourneyStore, version?: BundleVersion): Promise<DeployResult>;
|
|
212
|
+
export declare function deployBundle(env: JourneyEnv, bundle: unknown, store: JourneyStore, version?: BundleVersion, force?: boolean): Promise<DeployResult>;
|
|
183
213
|
/** The channels a user opts out of per topic: `suppression` rows are keyed by (user, channel, topic). */
|
|
184
214
|
export declare const SUBSCRIPTION_CHANNELS: readonly ['email', 'push'];
|
|
185
215
|
export type SubscriptionChannel = (typeof SUBSCRIPTION_CHANNELS)[number];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.cts","names":[],"sources":["../../src/host/ingest.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ingest.d.cts","names":[],"sources":["../../src/host/ingest.ts"],"mappings":";;;iBAiDiB;EACf;EACA;EACA,UAAU;EACV;;;;;;;;;;;;;;;EAeA;;iBAGe;;EAEf;;EAEA;EACA;EACA;;wBAGoB,YACpB,KAAK,YACL,OAAO,aACP,OAAO,eACN,QAAQ;;;;;;wBAwCW,gBACpB,KAAK,YACL,OAAO,cACP,gBACA,4BACC;;;;;;;;;wBAgFmB,uBACpB,KAAK,YACL,OAAO,cACP,gBACA,aACC;iBAkGc;EACf;;EAEA;;EAEA;IAAS;IAAiB;;;;;;;;qBAQf;;;;;;;;;;;wBAeS,eACpB,KAAK,YACL,OAAO,cACP,cACC;;qBAsBU;;qBAKA;;;;;;;wBAQS,iBAAiB,KAAK,YAAY,OAAO,eAAe;iBA4B7D;;EAEf;;EAEA;;EAEA;;EAEA;;;;;;;;wBASoB,mBACpB,KAAK,YACL,OAAO,cACP;EAAQ;EAA4B;EAA4B;IAC/D,QAAQ;;;;;;;;;wBAsCW,cACpB,KAAK,YACL,OAAO,cACP,eACC,QAAQ;iBAuJM;EACf;EACA,OAAO;EACP;EACA;;;;;;;wBAQoB,aACpB,KAAK,YACL,gBACA,OAAO,cACP,OAAO;;AAEP,cACC,QAAQ;iBAiBM;EACf;EACA;EACA;EACA;EACA;;;;;;;wBAQoB,YACpB,KAAK,YACL,mBACA,gBACA,OAAO,cACP,cACC;;;;;;wBA2BmB,eACpB,KAAK,YACL,QAAQ,oBACR,OAAO,eACN;EAAU;EAAU;;;;;;;;;;;wBA2GD,WACpB,KAAK,YACL,gBACA,OAAO,cACP,eACC;EAAU;EAAU;EAAiB;;;;;;;wBAUlB,aACpB,KAAK,YACL,eACA,OAAO,eACN;EAAU;EAAU;;;wBAQD,aACpB,KAAK,YACL,eACA,OAAO,eACN;EAAU;EAAU;;iBASN;EACf;;;;;;;;EAQA;IAAY;IAAkB,SAAS;;;;;;EAKvC;;;qBAIW,6BAA6B;EACxC,YAAY;;;;;;;;;;wBAgDQ,aACpB,KAAK,YACL,iBACA,OAAO,cACP,UAAU,eACV,kBACC,QAAQ;;qBA2BE;YACD,8BAA8B;;;;;;iBAOzB,qBAAqB;;;;;EAKpC;;;;;;EAMA,QAAQ,OAAO;;;;;;;iBAQA,cAAc;EAC7B,OAAO,qBAAqB;EAC5B,MAAM,qBAAqB;;;iBAIZ,0BAA0B;EACzC;EACA,SAAS,QAAQ,OAAO;;;;;;;iBAQT,mBAAmB;EAClC,QAAQ,0BAA0B;EAClC,OAAO,0BAA0B;;;iBAIlB;EACf;EACA;;;;;;wBAOc,wBACd,eACA;EACG;EAAU,OAAO;;EAAyB;EAAW,QAAQ;;;wBA8D5C,iBACpB,OAAO,cACP,gBACA,4BACC,QAAQ;;;;;;;;;wBAaW,iBACpB,KAAK,YACL,OAAO,cACP,gBACA,OAAO,oBACP,2BACA,eACC,QAAQ;;iBAwBM,cAAc;EAC7B,SAAS;EACT,OAAO;;;;;;;iBAQQ,qBAAqB,mCAAmC,cAAc;EACrF,SAAS,cAAc;;;;;;;;;wBAUH,oBACpB,OAAO,cACP,oBACC;EAAU;EAAgB,SAAS;;;wBAchB,0BACpB,OAAO,cACP,mBACA,4BACC,QAAQ;;wBAOW,0BACpB,KAAK,YACL,OAAO,cACP,mBACA,OAAO,oBACP,2BACA,eACC,QAAQ"}
|
package/dist/host/ingest.d.mts
CHANGED
|
@@ -56,6 +56,25 @@ export interface SweepResult {
|
|
|
56
56
|
size: number;
|
|
57
57
|
}[];
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* How long an entry may wait for its runner's admission before maintenance looks for its
|
|
61
|
+
* instance. A create takes well under a second and a queued instance is found by `get`, so this
|
|
62
|
+
* only has to outlast a create still in flight — generously, since a wrong call fails a journey.
|
|
63
|
+
*/
|
|
64
|
+
export declare const LOST_START_AFTER_MS: number;
|
|
65
|
+
/**
|
|
66
|
+
* Starts lost between the entry and the platform's create — the Worker cut off there, or a
|
|
67
|
+
* create that failed with its rollback failing too — leave a `running` entry nothing will ever
|
|
68
|
+
* admit, and the once-policy would then bar the user from the workflow for good. An instance that
|
|
69
|
+
* ended before admitting itself leaves the same. An entry old enough, unadmitted, whose instance
|
|
70
|
+
* the runtime does not know or reports ended, is marked `failed`: the pair's next trigger reclaims
|
|
71
|
+
* it. Nothing of such an instance ran, since admission precedes its first effect. Platform-neutral:
|
|
72
|
+
* on AWS a planned start is always known to `get` (its registry row), and reads as ended only once
|
|
73
|
+
* its retries have given up, so only a start with nothing behind it is touched.
|
|
74
|
+
*/
|
|
75
|
+
export declare function failLostStarts(env: JourneyEnv, store: JourneyStore, now: number): Promise<string[]>;
|
|
76
|
+
/** How long a visitor who never signs in is kept after they were last heard from. */
|
|
77
|
+
export declare const VISITOR_RETENTION_MS: number;
|
|
59
78
|
/** How many users one sweep page evaluates: a unit of resumable work (AWS checkpoints each). */
|
|
60
79
|
export declare const SWEEP_PAGE_SIZE = 500;
|
|
61
80
|
/**
|
|
@@ -106,17 +125,26 @@ export interface IdentifyResult {
|
|
|
106
125
|
* and re-evaluate segment triggers. The merge is one statement in the store, so
|
|
107
126
|
* two identifies landing together cannot lose each other's fields.
|
|
108
127
|
*/
|
|
109
|
-
export declare function identifyUser(env: JourneyEnv, userId: string, props: ProfileProps, store: JourneyStore
|
|
128
|
+
export declare function identifyUser(env: JourneyEnv, userId: string, props: ProfileProps, store: JourneyStore,
|
|
129
|
+
/** When these values were read; a property written later stays. The Worker's clock by default. */
|
|
130
|
+
at?: number): Promise<IdentifyResult>;
|
|
110
131
|
export interface DeviceRegistration {
|
|
111
|
-
|
|
132
|
+
deviceId?: string | undefined;
|
|
133
|
+
userId?: string | undefined;
|
|
134
|
+
visitorId?: string | undefined;
|
|
112
135
|
token: string;
|
|
113
136
|
platform: string;
|
|
114
|
-
ts?: number;
|
|
115
137
|
}
|
|
116
138
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
139
|
+
* The visitor signed in as the user: what the engine knows of them moves to the user, once. Their
|
|
140
|
+
* journeys carry on as the user's (`instanceOwner`), except one the user is already in, which
|
|
141
|
+
* stops. Answers nothing to do when already linked: every signed-in batch names its visitor.
|
|
142
|
+
*/
|
|
143
|
+
export declare function linkVisitor(env: JourneyEnv, visitorId: string, userId: string, store: JourneyStore, at?: number): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* A push token registered for its current owner: the user, or before sign-in the visitor. The
|
|
146
|
+
* device holds only that, so a token moves to whoever registered it last. Wakes the waits that read
|
|
147
|
+
* devices (`reachable('push')` inside `waitUntil`), for the new owner and the previous one.
|
|
120
148
|
*/
|
|
121
149
|
export declare function registerDevice(env: JourneyEnv, device: DeviceRegistration, store: JourneyStore): Promise<{
|
|
122
150
|
ok: true;
|
|
@@ -177,9 +205,11 @@ export declare class BundleIntegrityError extends Error {
|
|
|
177
205
|
* Bundle deploy, terraform-apply style: workflow bodies first (content-addressed, so a failed
|
|
178
206
|
* deploy leaves only harmless orphans), then the routing swap. With a `version` the swap happens
|
|
179
207
|
* only over an older live version (`replaceRoutesIfNewer`) — how journeyWorker applies the bundle
|
|
180
|
-
* compiled into it
|
|
208
|
+
* compiled into it — unless `force` is set: then it happens whatever is live, and the version is
|
|
209
|
+
* recorded as live (`POST /bundle/deploy`). Without a version it is forced and records nothing
|
|
210
|
+
* (`POST /deploy`, a hand-posted bundle).
|
|
181
211
|
*/
|
|
182
|
-
export declare function deployBundle(env: JourneyEnv, bundle: unknown, store: JourneyStore, version?: BundleVersion): Promise<DeployResult>;
|
|
212
|
+
export declare function deployBundle(env: JourneyEnv, bundle: unknown, store: JourneyStore, version?: BundleVersion, force?: boolean): Promise<DeployResult>;
|
|
183
213
|
/** The channels a user opts out of per topic: `suppression` rows are keyed by (user, channel, topic). */
|
|
184
214
|
export declare const SUBSCRIPTION_CHANNELS: readonly ['email', 'push'];
|
|
185
215
|
export type SubscriptionChannel = (typeof SUBSCRIPTION_CHANNELS)[number];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.mts","names":[],"sources":["../../src/host/ingest.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ingest.d.mts","names":[],"sources":["../../src/host/ingest.ts"],"mappings":";;;iBAiDiB;EACf;EACA;EACA,UAAU;EACV;;;;;;;;;;;;;;;EAeA;;iBAGe;;EAEf;;EAEA;EACA;EACA;;wBAGoB,YACpB,KAAK,YACL,OAAO,aACP,OAAO,eACN,QAAQ;;;;;;wBAwCW,gBACpB,KAAK,YACL,OAAO,cACP,gBACA,4BACC;;;;;;;;;wBAgFmB,uBACpB,KAAK,YACL,OAAO,cACP,gBACA,aACC;iBAkGc;EACf;;EAEA;;EAEA;IAAS;IAAiB;;;;;;;;qBAQf;;;;;;;;;;;wBAeS,eACpB,KAAK,YACL,OAAO,cACP,cACC;;qBAsBU;;qBAKA;;;;;;;wBAQS,iBAAiB,KAAK,YAAY,OAAO,eAAe;iBA4B7D;;EAEf;;EAEA;;EAEA;;EAEA;;;;;;;;wBASoB,mBACpB,KAAK,YACL,OAAO,cACP;EAAQ;EAA4B;EAA4B;IAC/D,QAAQ;;;;;;;;;wBAsCW,cACpB,KAAK,YACL,OAAO,cACP,eACC,QAAQ;iBAuJM;EACf;EACA,OAAO;EACP;EACA;;;;;;;wBAQoB,aACpB,KAAK,YACL,gBACA,OAAO,cACP,OAAO;;AAEP,cACC,QAAQ;iBAiBM;EACf;EACA;EACA;EACA;EACA;;;;;;;wBAQoB,YACpB,KAAK,YACL,mBACA,gBACA,OAAO,cACP,cACC;;;;;;wBA2BmB,eACpB,KAAK,YACL,QAAQ,oBACR,OAAO,eACN;EAAU;EAAU;;;;;;;;;;;wBA2GD,WACpB,KAAK,YACL,gBACA,OAAO,cACP,eACC;EAAU;EAAU;EAAiB;;;;;;;wBAUlB,aACpB,KAAK,YACL,eACA,OAAO,eACN;EAAU;EAAU;;;wBAQD,aACpB,KAAK,YACL,eACA,OAAO,eACN;EAAU;EAAU;;iBASN;EACf;;;;;;;;EAQA;IAAY;IAAkB,SAAS;;;;;;EAKvC;;;qBAIW,6BAA6B;EACxC,YAAY;;;;;;;;;;wBAgDQ,aACpB,KAAK,YACL,iBACA,OAAO,cACP,UAAU,eACV,kBACC,QAAQ;;qBA2BE;YACD,8BAA8B;;;;;;iBAOzB,qBAAqB;;;;;EAKpC;;;;;;EAMA,QAAQ,OAAO;;;;;;;iBAQA,cAAc;EAC7B,OAAO,qBAAqB;EAC5B,MAAM,qBAAqB;;;iBAIZ,0BAA0B;EACzC;EACA,SAAS,QAAQ,OAAO;;;;;;;iBAQT,mBAAmB;EAClC,QAAQ,0BAA0B;EAClC,OAAO,0BAA0B;;;iBAIlB;EACf;EACA;;;;;;wBAOc,wBACd,eACA;EACG;EAAU,OAAO;;EAAyB;EAAW,QAAQ;;;wBA8D5C,iBACpB,OAAO,cACP,gBACA,4BACC,QAAQ;;;;;;;;;wBAaW,iBACpB,KAAK,YACL,OAAO,cACP,gBACA,OAAO,oBACP,2BACA,eACC,QAAQ;;iBAwBM,cAAc;EAC7B,SAAS;EACT,OAAO;;;;;;;iBAQQ,qBAAqB,mCAAmC,cAAc;EACrF,SAAS,cAAc;;;;;;;;;wBAUH,oBACpB,OAAO,cACP,oBACC;EAAU;EAAgB,SAAS;;;wBAchB,0BACpB,OAAO,cACP,mBACA,4BACC,QAAQ;;wBAOW,0BACpB,KAAK,YACL,OAAO,cACP,mBACA,OAAO,oBACP,2BACA,eACC,QAAQ"}
|
package/dist/host/ingest.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { BundleIR } from "../ir.mjs";
|
|
|
6
6
|
import { isMessageId } from "../reporting/tracking.mjs";
|
|
7
7
|
import { JourneyFactSource } from "../store/facts.mjs";
|
|
8
8
|
import { UserErasedError } from "../store/erasure.mjs";
|
|
9
|
+
import { isVisitorSubject } from "../store/identity.mjs";
|
|
9
10
|
import { SchemaMismatchError } from "../store/index.mjs";
|
|
10
11
|
import { InstanceNotFoundError, WAKE_EVENT_TYPE } from "./platform.mjs";
|
|
11
12
|
// src/host/ingest.ts
|
|
@@ -86,6 +87,7 @@ async function wakeSubscribers(env, store, userId, events) {
|
|
|
86
87
|
async function startTriggeredJourneys(env, store, input, ts) {
|
|
87
88
|
const started = [];
|
|
88
89
|
for (const route of await store.findTriggers(input.event)) {
|
|
90
|
+
if (isVisitorSubject(input.userId) && !route.visitors) continue;
|
|
89
91
|
if (route.where !== null && !matchesWhere(input.payload, route.where)) continue;
|
|
90
92
|
if (route.filter !== null) {
|
|
91
93
|
const facts = new JourneyFactSource(store, input.userId);
|
|
@@ -93,7 +95,8 @@ async function startTriggeredJourneys(env, store, input, ts) {
|
|
|
93
95
|
}
|
|
94
96
|
const instanceId = await startJourney(env, store, route.workflow, route.hash, input.userId, ts, {
|
|
95
97
|
event: input.event,
|
|
96
|
-
payload: input.payload
|
|
98
|
+
payload: input.payload,
|
|
99
|
+
ts
|
|
97
100
|
}, route.version);
|
|
98
101
|
if (instanceId !== null) started.push(instanceId);
|
|
99
102
|
}
|
|
@@ -117,6 +120,7 @@ async function refreshSegmentTriggers(env, store, userId, ts) {
|
|
|
117
120
|
* users who enter after it is deployed; a user already a member is not entered again.
|
|
118
121
|
*/
|
|
119
122
|
async function refreshSegments(env, store, userId, ts, routes, segments = [], definitions = /* @__PURE__ */ new Map()) {
|
|
123
|
+
if (isVisitorSubject(userId)) return [];
|
|
120
124
|
const bySegment = new Map(segments.map((name) => [name, []]));
|
|
121
125
|
for (const route of routes) {
|
|
122
126
|
const list = bySegment.get(route.segment) ?? [];
|
|
@@ -152,7 +156,7 @@ async function refreshSegments(env, store, userId, ts, routes, segments = [], de
|
|
|
152
156
|
payload: { segment: segmentId }
|
|
153
157
|
}, route.version);
|
|
154
158
|
if (instanceId !== null) started.push(instanceId);
|
|
155
|
-
await store.completeSegmentStart(segmentId, userId, route.workflow);
|
|
159
|
+
if (instanceId !== null || await entryStarted(env, store, route.workflow, userId)) await store.completeSegmentStart(segmentId, userId, route.workflow);
|
|
156
160
|
} catch (error) {
|
|
157
161
|
failures.push(error);
|
|
158
162
|
}
|
|
@@ -161,6 +165,43 @@ async function refreshSegments(env, store, userId, ts, routes, segments = [], de
|
|
|
161
165
|
if (failures.length > 0) throw failures[0];
|
|
162
166
|
return started;
|
|
163
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* How long an entry may wait for its runner's admission before maintenance looks for its
|
|
170
|
+
* instance. A create takes well under a second and a queued instance is found by `get`, so this
|
|
171
|
+
* only has to outlast a create still in flight — generously, since a wrong call fails a journey.
|
|
172
|
+
*/
|
|
173
|
+
const LOST_START_AFTER_MS = 9e5;
|
|
174
|
+
/** Entries one maintenance run examines, oldest first; the next run takes the rest. */
|
|
175
|
+
const LOST_START_BATCH = 25;
|
|
176
|
+
/**
|
|
177
|
+
* Starts lost between the entry and the platform's create — the Worker cut off there, or a
|
|
178
|
+
* create that failed with its rollback failing too — leave a `running` entry nothing will ever
|
|
179
|
+
* admit, and the once-policy would then bar the user from the workflow for good. An instance that
|
|
180
|
+
* ended before admitting itself leaves the same. An entry old enough, unadmitted, whose instance
|
|
181
|
+
* the runtime does not know or reports ended, is marked `failed`: the pair's next trigger reclaims
|
|
182
|
+
* it. Nothing of such an instance ran, since admission precedes its first effect. Platform-neutral:
|
|
183
|
+
* on AWS a planned start is always known to `get` (its registry row), and reads as ended only once
|
|
184
|
+
* its retries have given up, so only a start with nothing behind it is touched.
|
|
185
|
+
*/
|
|
186
|
+
async function failLostStarts(env, store, now) {
|
|
187
|
+
const failed = [];
|
|
188
|
+
for (const entry of await store.unadmittedEntries(now - LOST_START_AFTER_MS, LOST_START_BATCH)) {
|
|
189
|
+
try {
|
|
190
|
+
if (!await hasEnded(await env.JOURNEY.get(entry.instanceId))) continue;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (!(error instanceof InstanceNotFoundError)) continue;
|
|
193
|
+
}
|
|
194
|
+
if (await store.failUnadmittedEntry(entry.instanceId)) {
|
|
195
|
+
failed.push(entry.instanceId);
|
|
196
|
+
console.error(`[workflow] the start of ${entry.instanceId} (${entry.workflow}) was lost before its instance existed: marked failed, the next trigger re-enters`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return failed;
|
|
200
|
+
}
|
|
201
|
+
/** How long a visitor who never signs in is kept after they were last heard from. */
|
|
202
|
+
const VISITOR_RETENTION_MS = 7776e6;
|
|
203
|
+
/** Visitors one sweep prunes: the next sweep goes on. */
|
|
204
|
+
const VISITOR_PRUNE_BATCH = 100;
|
|
164
205
|
/** How many users one sweep page evaluates: a unit of resumable work (AWS checkpoints each). */
|
|
165
206
|
const SWEEP_PAGE_SIZE = 500;
|
|
166
207
|
/**
|
|
@@ -175,6 +216,16 @@ async function sweepMaintenance(env, store) {
|
|
|
175
216
|
} catch (error) {
|
|
176
217
|
console.error("[workflow] runtime maintenance failed", error);
|
|
177
218
|
}
|
|
219
|
+
try {
|
|
220
|
+
await failLostStarts(env, store, Date.now());
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error("[workflow] reclaiming lost starts failed", error);
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
await store.pruneVisitors(Date.now() - VISITOR_RETENTION_MS, VISITOR_PRUNE_BATCH);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.error("[workflow] pruning idle visitors failed", error);
|
|
228
|
+
}
|
|
178
229
|
for (const userId of await store.pendingErasures()) try {
|
|
179
230
|
await eraseUser(env, userId, store, Date.now());
|
|
180
231
|
} catch (error) {
|
|
@@ -246,6 +297,50 @@ async function sweepSegments(env, store, now = Date.now()) {
|
|
|
246
297
|
};
|
|
247
298
|
}
|
|
248
299
|
/**
|
|
300
|
+
* Whether the (workflow, user) entry's start is known to have happened: the runner admitted
|
|
301
|
+
* itself, the entry already ended, or the runtime knows its instance and it has not ended. An
|
|
302
|
+
* unadmitted entry whose instance cannot be found, cannot be looked up right now, or ended without
|
|
303
|
+
* admitting itself is not; the caller asks again.
|
|
304
|
+
*/
|
|
305
|
+
async function entryStarted(env, store, workflow, userId) {
|
|
306
|
+
const entry = await store.getEntry(workflow, userId);
|
|
307
|
+
if (entry === void 0 || entry.status === "failed") return false;
|
|
308
|
+
if (entry.admitted || entry.status !== "running") return true;
|
|
309
|
+
try {
|
|
310
|
+
return !await hasEnded(await env.JOURNEY.get(entry.instanceId));
|
|
311
|
+
} catch {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Create the instance, idempotently by id, on a runtime that does not record its starts
|
|
317
|
+
* (Cloudflare): a create the platform refuses because the id already exists — a concurrent
|
|
318
|
+
* retry of the same start won the race — is the instance we wanted, not a failure. Rolling the
|
|
319
|
+
* entry back over it would strand a running instance with no ledger row, and it would never be
|
|
320
|
+
* admitted. A create whose instance the runtime cannot find failed, and so did one refused by an
|
|
321
|
+
* instance that already ended: the id stays taken by that corpse, which will never admit itself,
|
|
322
|
+
* and taking it for the start would leave a running entry nothing ever fails. True when this call
|
|
323
|
+
* created it, false when it already existed.
|
|
324
|
+
*/
|
|
325
|
+
async function createInstance(env, id, params) {
|
|
326
|
+
try {
|
|
327
|
+
await env.JOURNEY.create({
|
|
328
|
+
id,
|
|
329
|
+
params
|
|
330
|
+
});
|
|
331
|
+
return true;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
let ended;
|
|
334
|
+
try {
|
|
335
|
+
ended = await hasEnded(await env.JOURNEY.get(id));
|
|
336
|
+
} catch {
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
339
|
+
if (ended) throw error;
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
249
344
|
* Create one journey instance behind the entry ledger. Returns null when the
|
|
250
345
|
* once-policy blocks the entry (the store's attempt is atomic, so concurrent
|
|
251
346
|
* ingests cannot double-enter). A pair whose previous instance is recorded as
|
|
@@ -274,17 +369,23 @@ async function startJourney(env, store, workflow, hash, userId, ts, trigger, ver
|
|
|
274
369
|
execution
|
|
275
370
|
});
|
|
276
371
|
if (outcome === null) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
372
|
+
if (env.JOURNEY.resume !== void 0) {
|
|
373
|
+
await env.JOURNEY.resume({
|
|
374
|
+
workflow,
|
|
375
|
+
userId
|
|
376
|
+
});
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
const entry = await store.getEntry(workflow, userId);
|
|
380
|
+
if (entry?.instanceId !== instanceId || entry.status !== "running" || entry.admitted) return null;
|
|
381
|
+
return await createInstance(env, instanceId, params) ? instanceId : null;
|
|
282
382
|
}
|
|
283
383
|
try {
|
|
284
|
-
await env.JOURNEY.create({
|
|
384
|
+
if (execution !== void 0) await env.JOURNEY.create({
|
|
285
385
|
id: instanceId,
|
|
286
386
|
params
|
|
287
387
|
});
|
|
388
|
+
else await createInstance(env, instanceId, params);
|
|
288
389
|
} catch (error) {
|
|
289
390
|
if (execution !== void 0) throw error;
|
|
290
391
|
if (outcome === "reclaimed") await store.setEntryStatus(instanceId, "failed");
|
|
@@ -309,30 +410,58 @@ function buildInstanceId(workflow, hash, userId, ts) {
|
|
|
309
410
|
* and re-evaluate segment triggers. The merge is one statement in the store, so
|
|
310
411
|
* two identifies landing together cannot lose each other's fields.
|
|
311
412
|
*/
|
|
312
|
-
async function identifyUser(env, userId, props, store) {
|
|
413
|
+
async function identifyUser(env, userId, props, store, at) {
|
|
313
414
|
await refuseIfErased(store, userId);
|
|
314
415
|
const ts = Date.now();
|
|
315
416
|
return {
|
|
316
417
|
ok: true,
|
|
317
|
-
props: await store.mergeProfile(userId, props),
|
|
418
|
+
props: await store.mergeProfile(userId, props, at ?? ts),
|
|
318
419
|
woke: await wakeSubscribers(env, store, userId, Object.keys(props).map(profileUpdatedEvent)),
|
|
319
420
|
started: await refreshSegmentTriggers(env, store, userId, ts)
|
|
320
421
|
};
|
|
321
422
|
}
|
|
322
423
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
424
|
+
* The visitor signed in as the user: what the engine knows of them moves to the user, once. Their
|
|
425
|
+
* journeys carry on as the user's (`instanceOwner`), except one the user is already in, which
|
|
426
|
+
* stops. Answers nothing to do when already linked: every signed-in batch names its visitor.
|
|
427
|
+
*/
|
|
428
|
+
async function linkVisitor(env, visitorId, userId, store, at = Date.now()) {
|
|
429
|
+
await refuseIfErased(store, userId);
|
|
430
|
+
const linked = await store.linkedUser(visitorId);
|
|
431
|
+
if (linked !== void 0) {
|
|
432
|
+
if (linked !== userId) console.warn(`[workflow] visitor ${visitorId} stays with its first user, not ${userId}`);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const merge = await store.linkVisitor(visitorId, userId, at);
|
|
436
|
+
if (merge === null) return;
|
|
437
|
+
for (const instanceId of merge.dropped) await stopInstance(env, instanceId);
|
|
438
|
+
await wakeSubscribers(env, store, userId, [
|
|
439
|
+
DEVICES_UPDATED_EVENT,
|
|
440
|
+
...merge.events,
|
|
441
|
+
...merge.props.map(profileUpdatedEvent)
|
|
442
|
+
]);
|
|
443
|
+
await refreshSegmentTriggers(env, store, userId, at);
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* A push token registered for its current owner: the user, or before sign-in the visitor. The
|
|
447
|
+
* device holds only that, so a token moves to whoever registered it last. Wakes the waits that read
|
|
448
|
+
* devices (`reachable('push')` inside `waitUntil`), for the new owner and the previous one.
|
|
326
449
|
*/
|
|
327
450
|
async function registerDevice(env, device, store) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
await store.
|
|
331
|
-
|
|
332
|
-
|
|
451
|
+
const { deviceId, userId, visitorId, token, platform } = device;
|
|
452
|
+
if (userId !== void 0 && visitorId !== void 0) await linkVisitor(env, visitorId, userId, store);
|
|
453
|
+
const subject = userId ?? await store.touchVisitor(visitorId ?? "", Date.now());
|
|
454
|
+
await refuseIfErased(store, subject);
|
|
455
|
+
const previous = await store.upsertDevice({
|
|
456
|
+
deviceId,
|
|
457
|
+
userId: isVisitorSubject(subject) ? null : subject,
|
|
458
|
+
visitorId,
|
|
459
|
+
token,
|
|
460
|
+
platform,
|
|
461
|
+
at: Date.now()
|
|
333
462
|
});
|
|
334
|
-
let woke = await wakeSubscribers(env, store,
|
|
335
|
-
|
|
463
|
+
let woke = await wakeSubscribers(env, store, subject, [DEVICES_UPDATED_EVENT]);
|
|
464
|
+
for (const owner of previous) woke += await wakeSubscribers(env, store, owner, [DEVICES_UPDATED_EVENT]);
|
|
336
465
|
return {
|
|
337
466
|
ok: true,
|
|
338
467
|
woke
|
|
@@ -344,6 +473,11 @@ const STOPPED_STATUSES = /* @__PURE__ */ new Set([
|
|
|
344
473
|
"errored",
|
|
345
474
|
"terminated"
|
|
346
475
|
]);
|
|
476
|
+
/** Whether the instance reports a terminal state. An unreadable status says nothing: false. */
|
|
477
|
+
async function hasEnded(instance) {
|
|
478
|
+
const status = await instance.status?.().catch(() => void 0);
|
|
479
|
+
return status !== void 0 && STOPPED_STATUSES.has(status.status);
|
|
480
|
+
}
|
|
347
481
|
/**
|
|
348
482
|
* Stop one admitted instance for good; true once it is known not to run again: terminated, or
|
|
349
483
|
* already in a terminal state (terminate refuses those). Any other failure is not taken for
|
|
@@ -368,8 +502,7 @@ async function stopInstance(env, instanceId) {
|
|
|
368
502
|
await instance.terminate();
|
|
369
503
|
return true;
|
|
370
504
|
} catch (error) {
|
|
371
|
-
|
|
372
|
-
if (status !== void 0 && STOPPED_STATUSES.has(status.status)) return true;
|
|
505
|
+
if (await hasEnded(instance)) return true;
|
|
373
506
|
console.warn(`[workflow] terminating ${instanceId} failed`, error);
|
|
374
507
|
return false;
|
|
375
508
|
}
|
|
@@ -479,16 +612,18 @@ function verifyBundleHashes(parsed) {
|
|
|
479
612
|
* Bundle deploy, terraform-apply style: workflow bodies first (content-addressed, so a failed
|
|
480
613
|
* deploy leaves only harmless orphans), then the routing swap. With a `version` the swap happens
|
|
481
614
|
* only over an older live version (`replaceRoutesIfNewer`) — how journeyWorker applies the bundle
|
|
482
|
-
* compiled into it
|
|
615
|
+
* compiled into it — unless `force` is set: then it happens whatever is live, and the version is
|
|
616
|
+
* recorded as live (`POST /bundle/deploy`). Without a version it is forced and records nothing
|
|
617
|
+
* (`POST /deploy`, a hand-posted bundle).
|
|
483
618
|
*/
|
|
484
|
-
async function deployBundle(env, bundle, store, version) {
|
|
619
|
+
async function deployBundle(env, bundle, store, version, force = false) {
|
|
485
620
|
const parsed = BundleIR.parse(bundle);
|
|
486
621
|
verifyBundleHashes(parsed);
|
|
487
622
|
const problems = await store.checkSchema();
|
|
488
623
|
if (problems.length > 0) throw new SchemaMismatchError(problems);
|
|
489
624
|
for (const workflow of parsed.workflows) await store.putWorkflowIR(workflow);
|
|
490
625
|
let applied = true;
|
|
491
|
-
if (version === void 0) await store.replaceRoutes(parsed);
|
|
626
|
+
if (version === void 0 || force) await store.replaceRoutes(parsed, version);
|
|
492
627
|
else applied = await store.replaceRoutesIfNewer(parsed, version);
|
|
493
628
|
const unrouted = parsed.workflows.filter((workflow) => workflow.trigger.type === "date" || workflow.trigger.type === "webhook").map((workflow) => ({
|
|
494
629
|
workflow: workflow.id,
|
|
@@ -660,6 +795,6 @@ async function setSubscriptionsByMessage(env, store, messageId, patch, topics, n
|
|
|
660
795
|
message: owner.message
|
|
661
796
|
};
|
|
662
797
|
}
|
|
663
|
-
export { BundleIntegrityError, SUBSCRIPTION_CHANNELS, SWEEP_PAGE_SIZE, deployBundle, forgetUser, getSubscriptions, getSubscriptionsByMessage, identifyUser, ingestEvent, parseSubscriptionsPatch, refreshSegmentTriggers, registerDevice, removeDevice, resolveMessageOwner, setSubscriptions, setSubscriptionsByMessage, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice, wakeSubscribers };
|
|
798
|
+
export { BundleIntegrityError, LOST_START_AFTER_MS, SUBSCRIPTION_CHANNELS, SWEEP_PAGE_SIZE, VISITOR_RETENTION_MS, deployBundle, failLostStarts, forgetUser, getSubscriptions, getSubscriptionsByMessage, identifyUser, ingestEvent, linkVisitor, parseSubscriptionsPatch, refreshSegmentTriggers, registerDevice, removeDevice, resolveMessageOwner, setSubscriptions, setSubscriptionsByMessage, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice, wakeSubscribers };
|
|
664
799
|
|
|
665
800
|
//# sourceMappingURL=ingest.mjs.map
|