notifkit 0.1.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/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/index.d.mts +9973 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +38 -0
- package/dist/index.mjs.map +1 -0
- package/dist/main-4H6vNXvy.mjs +392 -0
- package/dist/main-4H6vNXvy.mjs.map +1 -0
- package/dist/main-BHYZfBBq.mjs +224 -0
- package/dist/main-BHYZfBBq.mjs.map +1 -0
- package/dist/main-BIcKzWHE.mjs +430 -0
- package/dist/main-BIcKzWHE.mjs.map +1 -0
- package/dist/main-ClEeP5qw.mjs +629 -0
- package/dist/main-ClEeP5qw.mjs.map +1 -0
- package/dist/main-D-oWWzR3.mjs +234 -0
- package/dist/main-D-oWWzR3.mjs.map +1 -0
- package/dist/main-Dlfy9mWs.mjs +571 -0
- package/dist/main-Dlfy9mWs.mjs.map +1 -0
- package/dist/main-Dztc2dqR.mjs +294 -0
- package/dist/main-Dztc2dqR.mjs.map +1 -0
- package/dist/main-Ok9cQJ7q.mjs +1636 -0
- package/dist/main-Ok9cQJ7q.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/src-DrSN2wCg.mjs +3424 -0
- package/dist/src-DrSN2wCg.mjs.map +1 -0
- package/drizzle/0000_spotty_jack_flag.sql +189 -0
- package/drizzle/0001_stale_shotgun.sql +17 -0
- package/drizzle/meta/0000_snapshot.json +1314 -0
- package/drizzle/meta/0001_snapshot.json +1460 -0
- package/drizzle/meta/_journal.json +20 -0
- package/package.json +110 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/index.ts","../src/contracts/common.ts","../src/contracts/metadata.ts","../src/contracts/events/notification-requested.ts","../src/contracts/events/notification-created.ts","../src/contracts/events/notification-enriched.ts","../src/contracts/events/notification-scheduled.ts","../src/contracts/events/notification-dispatched.ts","../src/contracts/events/notification-delivered.ts","../src/contracts/events/notification-failed.ts","../src/contracts/events/notification-skipped.ts","../src/contracts/events/notification-canceled.ts","../src/contracts/events/notification-ai-pending.ts","../src/contracts/registry.ts","../src/contracts/envelope.ts","../src/contracts/streams.ts","../src/contracts/helpers.ts","../src/contracts/sdk.ts","../src/db/schema.ts","../src/db/index.ts","../src/idempotency/index.ts","../src/logger/index.ts","../src/metrics/index.ts","../src/queue/index.ts","../src/rate-limiter/index.ts","../src/redis/index.ts","../src/repositories/index.ts","../src/shared/events.ts","../src/shared/cache.ts","../src/shared/utils.ts","../src/shared/semaphore.ts","../src/shared/batch-processor.ts","../src/shared/circuit-breaker.ts","../src/shared/dataloader.ts","../src/workers/health.ts","../src/workers/index.ts","../src/shared/index.ts","../src/templates/render.ts","../src/templates/cache.ts","../src/templates/index.ts","../src/transport/index.ts","../src/unsubscribe/index.ts","../src/workflows/sdk.ts","../src/workflows/registry.ts","../src/client.ts","../src/server.ts"],"mappings":"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"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { $ as childLogger, $t as PUBSUB_CHANNELS, A as ProjectSettingsCache, At as NotificationRequestedPayloadSchema, B as LUA_RELEASE_LOCK, Bt as QuietHoursSchema, C as ProjectRepository, Ct as DeliveryOptionsSchema, D as WorkflowRepository, Dt as NotificationEnrichedPayloadSchema, E as UserRepository, Et as NotificationScheduledPayloadSchema, F as sleep, Ft as CreateWorkflowSchema, G as normaliseTarget, Gt as UpdateUserSchema, H as LUA_SCHEDULER_CLAIM, Ht as TemplateSchema, I as DataLoader, It as IngestEventSchema, J as PendingMessageScanner, Jt as buildStreamEvent, K as LRUCache, Kt as WorkflowNotifyPayloadSchema, L as CircuitBreaker, Lt as InlineUserSchema, M as AppError, Mt as AddContactSchema, N as ValidationError, Nt as AddUserSchema, O as Redis, Ot as RecipientProfileSchema, P as generateId, Pt as ContactChannelSchema, Q as metrics, Qt as OUTBOUND_STREAMS, R as BatchProcessor, Rt as NotifyRequestSchema, S as PreferenceRepository, St as NotificationDeliveredPayloadSchema, T as TemplateRepository, Tt as RenderedContentSchema, U as LUA_SCHEDULER_POLL, Ut as TriggerWorkflowSchema, V as LUA_RENEW_LOCK, Vt as SyncTemplatesSchema, W as getPriorityBucket, Wt as UpdateProjectSchema, X as StreamProducer, Xt as ENRICHED_STREAMS, Y as StreamConsumer, Yt as CONSUMER_GROUPS, Z as getMetricsRegistry, Zt as INBOUND_STREAMS, _ as escapeHeader, _n as setGlobalConfig, a as SuspendExecutionError, an as registry, at as runMigrations, b as renderWithTemplate, bt as NotificationSkippedPayloadSchema, c as BaseWorker, cn as NotificationPrioritySchema, d as buildUnsubscribeHeaders, dn as baseConfigSchema, en as STREAMS, et as createLogger, f as signUnsubscribeToken, fn as getAiConfig, g as TemplateCache, gn as setAiConfig, h as templateRegistry, hn as readBaseConfig, i as workflowRegistry, in as EventRegistry, it as createDatabase, j as UserThrottle, jt as NotificationTargetSchema, k as RedisClient, kt as NotificationCreatedPayloadSchema, l as NonRetryableError, ln as NotificationStatusSchema, m as renderTemplate, mn as parseConfig, n as NotifkitClient, nn as StreamEventMetadataSchema, nt as withRequestId, o as buildStepNotifyPayload, on as EventMetadataSchema, p as verifyUnsubscribeToken, pn as loadEnv, q as globalEmitter, qt as WorkflowStepSchema, r as workflow, rn as StreamEventSchema, rt as IdempotencyGuard, s as resolveStepTarget, sn as NotificationChannelSchema, t as NotifkitServer, tn as EventEnvelopeSchema, tt as withContext, u as startHealthReporter, un as AI_DEFAULTS, v as escapeHtml, vt as NotificationAiPendingPayloadSchema, w as SegmentRepository, wt as NotificationDispatchedPayloadSchema, x as ContactRepository, xt as NotificationFailedPayloadSchema, y as interpolate, yt as NotificationCanceledPayloadSchema, z as AsyncSemaphore, zt as PreferencesSchema } from "./src-DrSN2wCg.mjs";
|
|
3
|
+
//#region src/transport/index.ts
|
|
4
|
+
var transport_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
registerTransport: () => registerTransport,
|
|
6
|
+
transportRegistry: () => transportRegistry
|
|
7
|
+
});
|
|
8
|
+
var TransportRegistry = class {
|
|
9
|
+
transports = /* @__PURE__ */ new Map();
|
|
10
|
+
register(transport, priority = 0) {
|
|
11
|
+
const list = this.transports.get(transport.channel) || [];
|
|
12
|
+
list.push({
|
|
13
|
+
transport,
|
|
14
|
+
priority
|
|
15
|
+
});
|
|
16
|
+
list.sort((a, b) => b.priority - a.priority);
|
|
17
|
+
this.transports.set(transport.channel, list);
|
|
18
|
+
}
|
|
19
|
+
get(channel) {
|
|
20
|
+
const list = this.transports.get(channel);
|
|
21
|
+
return list && list.length > 0 ? list[0]?.transport : void 0;
|
|
22
|
+
}
|
|
23
|
+
getAll(channel) {
|
|
24
|
+
const list = this.transports.get(channel);
|
|
25
|
+
return list ? list.map((item) => item.transport) : [];
|
|
26
|
+
}
|
|
27
|
+
registeredChannels() {
|
|
28
|
+
return [...this.transports.keys()];
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const transportRegistry = new TransportRegistry();
|
|
32
|
+
function registerTransport(transport, priority = 0) {
|
|
33
|
+
transportRegistry.register(transport, priority);
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { AI_DEFAULTS, AddContactSchema, AddUserSchema, AppError, AsyncSemaphore, BaseWorker, BatchProcessor, CONSUMER_GROUPS, CircuitBreaker, ContactChannelSchema, ContactRepository, CreateWorkflowSchema, DataLoader, DeliveryOptionsSchema, ENRICHED_STREAMS, EventEnvelopeSchema, EventMetadataSchema, EventRegistry, INBOUND_STREAMS, IdempotencyGuard, IngestEventSchema, InlineUserSchema, LRUCache, LUA_RELEASE_LOCK, LUA_RENEW_LOCK, LUA_SCHEDULER_CLAIM, LUA_SCHEDULER_POLL, NonRetryableError, NotificationAiPendingPayloadSchema, NotificationCanceledPayloadSchema, NotificationChannelSchema, NotificationCreatedPayloadSchema, NotificationDeliveredPayloadSchema, NotificationDispatchedPayloadSchema, NotificationEnrichedPayloadSchema, NotificationFailedPayloadSchema, NotificationPrioritySchema, NotificationRequestedPayloadSchema, NotificationScheduledPayloadSchema, NotificationSkippedPayloadSchema, NotificationStatusSchema, NotificationTargetSchema, NotifkitClient, NotifkitServer, NotifyRequestSchema, OUTBOUND_STREAMS, PUBSUB_CHANNELS, PendingMessageScanner, PreferenceRepository, PreferencesSchema, ProjectRepository, ProjectSettingsCache, QuietHoursSchema, RecipientProfileSchema, Redis, RedisClient, RenderedContentSchema, STREAMS, SegmentRepository, StreamConsumer, StreamEventMetadataSchema, StreamEventSchema, StreamProducer, SuspendExecutionError, SyncTemplatesSchema, TemplateCache, TemplateRepository, TemplateSchema, TriggerWorkflowSchema, UpdateProjectSchema, UpdateUserSchema, UserRepository, UserThrottle, ValidationError, WorkflowNotifyPayloadSchema, WorkflowRepository, WorkflowStepSchema, baseConfigSchema, buildStepNotifyPayload, buildStreamEvent, buildUnsubscribeHeaders, childLogger, createDatabase, createLogger, escapeHeader, escapeHtml, generateId, getAiConfig, getMetricsRegistry, getPriorityBucket, globalEmitter, interpolate, loadEnv, metrics, normaliseTarget, parseConfig, readBaseConfig, registerTransport, registry, renderTemplate, renderWithTemplate, resolveStepTarget, runMigrations, setAiConfig, setGlobalConfig, signUnsubscribeToken, sleep, startHealthReporter, transport_exports as t, templateRegistry, transportRegistry, verifyUnsubscribeToken, withContext, withRequestId, workflow, workflowRegistry };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/transport/index.ts"],"sourcesContent":["import type { NotificationChannel, NotificationDispatchedPayload } from \"@/index.js\";\n\n// ─── Core interface ──────────────────────────────────────────────────────────\n//\n// Implement this interface to add a new channel (Email, SMS, APNS, Web Push …).\n// Register the implementation with transportRegistry at app startup.\n\nexport interface DeliveryResult {\n success: boolean;\n providerMessageId?: string;\n invalidToken?: boolean;\n error?: string;\n}\n\nexport interface WebhookEvent {\n providerMessageId: string;\n status: \"opened\" | \"clicked\" | \"bounced\" | \"complained\" | \"unsubscribed\";\n timestamp?: Date;\n /**\n * The address the event concerns. Required to suppress it — without this a\n * bounce or unsubscribe can be logged but not acted on, because the delivery\n * log records the message, not the destination.\n */\n recipient?: string;\n /**\n * Whether a bounce is permanent. Only hard bounces suppress; a soft bounce is\n * a full mailbox or a temporary outage and the address is still good. Left\n * undefined by providers that do not distinguish them, which is treated as\n * soft — the conservative reading, since wrongly suppressing a live address\n * silently stops mail the person still wants.\n */\n bounceType?: \"hard\" | \"soft\";\n /** Provider detail worth keeping: the clicked URL, the bounce description. */\n metadata?: Record<string, unknown>;\n}\n\nexport interface Transport {\n readonly channel: NotificationChannel;\n readonly limits?: { limit: number; windowSeconds: number };\n send(task: NotificationDispatchedPayload): Promise<DeliveryResult>;\n\n webhookPath?: string;\n verifyWebhook?: (\n rawBody: string,\n headers: Record<string, string | string[] | undefined>,\n ) => Promise<boolean> | boolean;\n parseWebhook?: (\n body: any,\n rawBody?: string,\n headers?: Record<string, string | string[] | undefined>,\n ) => Promise<WebhookEvent[]>;\n}\n\n// ─── TransportRegistry ───────────────────────────────────────────────────────\n\nclass TransportRegistry {\n private readonly transports = new Map<string, { transport: Transport; priority: number }[]>();\n\n register(transport: Transport, priority: number = 0): void {\n const list = this.transports.get(transport.channel) || [];\n list.push({ transport, priority });\n // Sort descending so higher priority is first\n list.sort((a, b) => b.priority - a.priority);\n this.transports.set(transport.channel, list);\n }\n\n get(channel: NotificationChannel): Transport | undefined {\n const list = this.transports.get(channel);\n return list && list.length > 0 ? list[0]?.transport : undefined;\n }\n\n getAll(channel: NotificationChannel): Transport[] {\n const list = this.transports.get(channel);\n return list ? list.map((item) => item.transport) : [];\n }\n\n registeredChannels(): string[] {\n return [...this.transports.keys()];\n }\n}\n\nexport const transportRegistry = new TransportRegistry();\n\nexport function registerTransport(transport: Transport, priority: number = 0): void {\n transportRegistry.register(transport, priority);\n}\n"],"mappings":";;;;;;;AAuDA,IAAM,oBAAN,MAAwB;CACtB,6BAA8B,IAAI,IAA0D;CAE5F,SAAS,WAAsB,WAAmB,GAAS;EACzD,MAAM,OAAO,KAAK,WAAW,IAAI,UAAU,OAAO,KAAK,CAAC;EACxD,KAAK,KAAK;GAAE;GAAW;EAAS,CAAC;EAEjC,KAAK,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;EAC3C,KAAK,WAAW,IAAI,UAAU,SAAS,IAAI;CAC7C;CAEA,IAAI,SAAqD;EACvD,MAAM,OAAO,KAAK,WAAW,IAAI,OAAO;EACxC,OAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,EAAE,EAAE,YAAY,KAAA;CACxD;CAEA,OAAO,SAA2C;EAChD,MAAM,OAAO,KAAK,WAAW,IAAI,OAAO;EACxC,OAAO,OAAO,KAAK,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;CACtD;CAEA,qBAA+B;EAC7B,OAAO,CAAC,GAAG,KAAK,WAAW,KAAK,CAAC;CACnC;AACF;AAEA,MAAa,oBAAoB,IAAI,kBAAkB;AAEvD,SAAgB,kBAAkB,WAAsB,WAAmB,GAAS;CAClF,kBAAkB,SAAS,WAAW,QAAQ;AAChD"}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { B as LUA_RELEASE_LOCK, J as PendingMessageScanner, Jt as buildStreamEvent, U as LUA_SCHEDULER_POLL, V as LUA_RENEW_LOCK, X as StreamProducer, Y as StreamConsumer, Yt as CONSUMER_GROUPS, _t as workflowWaiters, a as SuspendExecutionError, c as BaseWorker, en as STREAMS, et as createLogger, gt as workflowSteps, hn as readBaseConfig, ht as workflowInstances, i as workflowRegistry, it as createDatabase, k as RedisClient, mt as workflowDefinitions, o as buildStepNotifyPayload, pn as loadEnv, u as startHealthReporter } from "./src-DrSN2wCg.mjs";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { and, eq } from "drizzle-orm";
|
|
4
|
+
//#region src/services/workflow/main.ts
|
|
5
|
+
/** How long a workflow instance lock is held before it self-expires. */
|
|
6
|
+
const WORKFLOW_LOCK_TTL_SECONDS = 60;
|
|
7
|
+
/** Renew the lock well inside its TTL so long-running handlers keep it. */
|
|
8
|
+
const WORKFLOW_LOCK_RENEW_MS = WORKFLOW_LOCK_TTL_SECONDS / 3 * 1e3;
|
|
9
|
+
/** How long a claimed workflow timer stays invisible to other pollers. */
|
|
10
|
+
const WORKFLOW_TIMER_VISIBILITY_MS = 6e4;
|
|
11
|
+
loadEnv();
|
|
12
|
+
const config = readBaseConfig();
|
|
13
|
+
let logger;
|
|
14
|
+
let redis;
|
|
15
|
+
let sql$1;
|
|
16
|
+
let db;
|
|
17
|
+
let consumer;
|
|
18
|
+
let pendingScanner;
|
|
19
|
+
let worker;
|
|
20
|
+
let healthInterval = null;
|
|
21
|
+
let pollInterval = null;
|
|
22
|
+
let reaperInterval = null;
|
|
23
|
+
let notificationProducer;
|
|
24
|
+
let workflowProducer;
|
|
25
|
+
var WorkflowWorker = class extends BaseWorker {
|
|
26
|
+
redisCli;
|
|
27
|
+
dbConn;
|
|
28
|
+
workflowProducer;
|
|
29
|
+
notificationProducer;
|
|
30
|
+
eventBuffer = [];
|
|
31
|
+
flushTimer = null;
|
|
32
|
+
constructor(options) {
|
|
33
|
+
super(options);
|
|
34
|
+
this.redisCli = options.redis;
|
|
35
|
+
this.dbConn = options.db;
|
|
36
|
+
this.workflowProducer = options.workflowProducer;
|
|
37
|
+
this.notificationProducer = options.notificationProducer;
|
|
38
|
+
this.flushTimer = setInterval(() => void this.flushWorkerBuffers(), 100);
|
|
39
|
+
}
|
|
40
|
+
async stop() {
|
|
41
|
+
if (this.flushTimer) {
|
|
42
|
+
clearInterval(this.flushTimer);
|
|
43
|
+
this.flushTimer = null;
|
|
44
|
+
}
|
|
45
|
+
await this.flushWorkerBuffers();
|
|
46
|
+
await super.stop();
|
|
47
|
+
}
|
|
48
|
+
async flushWorkerBuffers() {
|
|
49
|
+
if (this.eventBuffer.length === 0) return;
|
|
50
|
+
const events = this.eventBuffer;
|
|
51
|
+
this.eventBuffer = [];
|
|
52
|
+
try {
|
|
53
|
+
const byProducer = /* @__PURE__ */ new Map();
|
|
54
|
+
for (const item of events) {
|
|
55
|
+
if (!byProducer.has(item.producer)) byProducer.set(item.producer, []);
|
|
56
|
+
byProducer.get(item.producer).push(item);
|
|
57
|
+
}
|
|
58
|
+
for (const [producer, batch] of byProducer) {
|
|
59
|
+
const { messageIds, eventIds } = await producer.publishBatch(batch.map((b) => b.event));
|
|
60
|
+
for (let i = 0; i < batch.length; i++) {
|
|
61
|
+
const mId = messageIds[i];
|
|
62
|
+
const eId = eventIds[i];
|
|
63
|
+
if (mId && eId) batch[i].resolve({
|
|
64
|
+
messageId: mId,
|
|
65
|
+
notificationId: eId
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
this.logger.error({ err }, "failed to flush workflow worker buffer");
|
|
71
|
+
for (const e of events) e.reject(err);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async process(message) {
|
|
75
|
+
const { event } = message;
|
|
76
|
+
const publishPromises = [];
|
|
77
|
+
if (event.type !== "workflow.triggered" && event.type !== "workflow.resumed") return;
|
|
78
|
+
const payload = event.payload;
|
|
79
|
+
const name = payload.name;
|
|
80
|
+
const instanceId = payload.instanceId;
|
|
81
|
+
if (!name || !instanceId || !payload.projectId) {
|
|
82
|
+
this.logger.warn("Missing name, instanceId, or projectId in workflow event");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let handler = workflowRegistry.get(name);
|
|
86
|
+
if (!handler) {
|
|
87
|
+
const defRows = await this.dbConn.select().from(workflowDefinitions).where(and(eq(workflowDefinitions.projectId, payload.projectId), eq(workflowDefinitions.name, name))).limit(1);
|
|
88
|
+
if (defRows.length === 0) {
|
|
89
|
+
this.logger.warn({
|
|
90
|
+
name,
|
|
91
|
+
projectId: payload.projectId
|
|
92
|
+
}, "No handler or dynamic definition found for workflow");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const def = defRows[0];
|
|
96
|
+
handler = async ({ step }) => {
|
|
97
|
+
const steps = def.steps;
|
|
98
|
+
for (const stepDef of steps) if (stepDef.action === "notify") await step.notify(stepDef.payload);
|
|
99
|
+
else if (stepDef.action === "wait") await step.wait(stepDef.duration);
|
|
100
|
+
else if (stepDef.action === "waitForEvent") await step.waitForEvent(stepDef.event, stepDef.options);
|
|
101
|
+
else this.logger.warn({
|
|
102
|
+
action: stepDef?.action,
|
|
103
|
+
name
|
|
104
|
+
}, "unknown workflow step action");
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const lockKey = `lock:workflow:${instanceId}`;
|
|
108
|
+
const lockToken = randomUUID();
|
|
109
|
+
if (!await this.redisCli.set(lockKey, lockToken, "EX", WORKFLOW_LOCK_TTL_SECONDS, "NX")) {
|
|
110
|
+
this.logger.info({ instanceId }, "Workflow is locked by another process, skipping");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const renewTimer = setInterval(() => {
|
|
114
|
+
this.redisCli.eval(LUA_RENEW_LOCK, 1, lockKey, lockToken, String(WORKFLOW_LOCK_TTL_SECONDS)).catch((err) => {
|
|
115
|
+
this.logger.warn({
|
|
116
|
+
err,
|
|
117
|
+
instanceId
|
|
118
|
+
}, "failed to renew workflow lock");
|
|
119
|
+
});
|
|
120
|
+
}, WORKFLOW_LOCK_RENEW_MS);
|
|
121
|
+
try {
|
|
122
|
+
let instance = (await this.dbConn.select().from(workflowInstances).where(eq(workflowInstances.id, instanceId)).limit(1))[0];
|
|
123
|
+
if (!instance) instance = (await this.dbConn.insert(workflowInstances).values({
|
|
124
|
+
id: instanceId,
|
|
125
|
+
projectId: payload.projectId,
|
|
126
|
+
name,
|
|
127
|
+
status: "pending",
|
|
128
|
+
input: payload.input || {}
|
|
129
|
+
}).returning())[0];
|
|
130
|
+
if (instance.status !== "pending") {
|
|
131
|
+
this.logger.info({ instanceId }, "Workflow is not pending, skipping");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
await this.dbConn.update(workflowInstances).set({ status: "running" }).where(eq(workflowInstances.id, instanceId));
|
|
135
|
+
const existingSteps = await this.dbConn.select().from(workflowSteps).where(eq(workflowSteps.instanceId, instanceId));
|
|
136
|
+
const stepOutputMap = /* @__PURE__ */ new Map();
|
|
137
|
+
for (const s of existingSteps) stepOutputMap.set(s.stepIndex, s.output);
|
|
138
|
+
let currentStepIndex = 0;
|
|
139
|
+
const ctx = {
|
|
140
|
+
step: {
|
|
141
|
+
notify: async (args) => {
|
|
142
|
+
const stepId = String(currentStepIndex++);
|
|
143
|
+
if (stepOutputMap.has(stepId)) return stepOutputMap.get(stepId);
|
|
144
|
+
const requested = buildStepNotifyPayload(args, instance.input, payload.projectId, `wf-${instanceId}-${stepId}`);
|
|
145
|
+
const result = await new Promise((resolve, reject) => {
|
|
146
|
+
this.eventBuffer.push({
|
|
147
|
+
producer: this.notificationProducer,
|
|
148
|
+
event: buildStreamEvent("notification.requested", requested, "workflow", event.metadata.traceId),
|
|
149
|
+
resolve,
|
|
150
|
+
reject
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
const output = {
|
|
154
|
+
success: true,
|
|
155
|
+
messageId: result.messageId,
|
|
156
|
+
notificationId: result.notificationId
|
|
157
|
+
};
|
|
158
|
+
await this.dbConn.insert(workflowSteps).values({
|
|
159
|
+
instanceId: instance.id,
|
|
160
|
+
projectId: payload.projectId,
|
|
161
|
+
stepIndex: stepId,
|
|
162
|
+
action: "notify",
|
|
163
|
+
output
|
|
164
|
+
});
|
|
165
|
+
return output;
|
|
166
|
+
},
|
|
167
|
+
wait: async (duration) => {
|
|
168
|
+
const stepId = String(currentStepIndex++);
|
|
169
|
+
if (stepOutputMap.has(stepId)) return;
|
|
170
|
+
let ms = 0;
|
|
171
|
+
if (duration.endsWith("d")) ms = parseInt(duration) * 24 * 60 * 60 * 1e3;
|
|
172
|
+
else if (duration.endsWith("h")) ms = parseInt(duration) * 60 * 60 * 1e3;
|
|
173
|
+
else if (duration.endsWith("m")) ms = parseInt(duration) * 60 * 1e3;
|
|
174
|
+
else if (duration.endsWith("s")) ms = parseInt(duration) * 1e3;
|
|
175
|
+
else throw new Error(`Invalid wait duration: ${duration}`);
|
|
176
|
+
const resumeAt = Date.now() + ms;
|
|
177
|
+
await this.redisCli.zadd("notif:workflow:timers", resumeAt, JSON.stringify({
|
|
178
|
+
instanceId: instance.id,
|
|
179
|
+
name: instance.name,
|
|
180
|
+
projectId: payload.projectId,
|
|
181
|
+
input: instance.input
|
|
182
|
+
}));
|
|
183
|
+
await this.dbConn.insert(workflowSteps).values({
|
|
184
|
+
instanceId: instance.id,
|
|
185
|
+
projectId: payload.projectId,
|
|
186
|
+
stepIndex: stepId,
|
|
187
|
+
action: "wait",
|
|
188
|
+
output: { scheduledAt: resumeAt }
|
|
189
|
+
});
|
|
190
|
+
throw new SuspendExecutionError("wait", { duration });
|
|
191
|
+
},
|
|
192
|
+
waitForEvent: async (eventName, options) => {
|
|
193
|
+
const stepId = String(currentStepIndex++);
|
|
194
|
+
if (stepOutputMap.has(stepId)) {
|
|
195
|
+
const out = stepOutputMap.get(stepId);
|
|
196
|
+
if (out && typeof out === "object" && out.timedOut === true) return null;
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
options = options || {};
|
|
200
|
+
options.timeout = options.timeout || "24h";
|
|
201
|
+
options.match = options.match || {};
|
|
202
|
+
let ms = 0;
|
|
203
|
+
if (options.timeout.endsWith("d")) ms = parseInt(options.timeout) * 24 * 60 * 60 * 1e3;
|
|
204
|
+
else if (options.timeout.endsWith("h")) ms = parseInt(options.timeout) * 60 * 60 * 1e3;
|
|
205
|
+
else if (options.timeout.endsWith("m")) ms = parseInt(options.timeout) * 60 * 1e3;
|
|
206
|
+
else if (options.timeout.endsWith("s")) ms = parseInt(options.timeout) * 1e3;
|
|
207
|
+
else throw new Error(`Invalid waitForEvent timeout: ${options.timeout}`);
|
|
208
|
+
const resumeAt = Date.now() + ms;
|
|
209
|
+
await this.redisCli.zadd("notif:workflow:timers", resumeAt, JSON.stringify({
|
|
210
|
+
instanceId: instance.id,
|
|
211
|
+
name: instance.name,
|
|
212
|
+
projectId: payload.projectId,
|
|
213
|
+
input: instance.input,
|
|
214
|
+
isEventTimeout: true,
|
|
215
|
+
eventName,
|
|
216
|
+
stepId
|
|
217
|
+
}));
|
|
218
|
+
await this.dbConn.insert(workflowWaiters).values({
|
|
219
|
+
instanceId: instance.id,
|
|
220
|
+
projectId: payload.projectId,
|
|
221
|
+
eventName,
|
|
222
|
+
matchCriteria: options.match,
|
|
223
|
+
expiresAt: new Date(resumeAt)
|
|
224
|
+
});
|
|
225
|
+
await this.dbConn.insert(workflowSteps).values({
|
|
226
|
+
instanceId: instance.id,
|
|
227
|
+
projectId: payload.projectId,
|
|
228
|
+
stepIndex: stepId,
|
|
229
|
+
action: "waitForEvent",
|
|
230
|
+
output: null
|
|
231
|
+
});
|
|
232
|
+
throw new SuspendExecutionError("waitForEvent", { eventName });
|
|
233
|
+
},
|
|
234
|
+
run: async (stepName, fn) => {
|
|
235
|
+
const stepId = String(currentStepIndex++);
|
|
236
|
+
if (stepOutputMap.has(stepId)) return stepOutputMap.get(stepId);
|
|
237
|
+
const result = await fn();
|
|
238
|
+
await this.dbConn.insert(workflowSteps).values({
|
|
239
|
+
instanceId: instance.id,
|
|
240
|
+
projectId: payload.projectId,
|
|
241
|
+
stepIndex: stepId,
|
|
242
|
+
action: "run",
|
|
243
|
+
output: result
|
|
244
|
+
});
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
event: instance.input || { user: { id: "unknown" } }
|
|
249
|
+
};
|
|
250
|
+
try {
|
|
251
|
+
await handler(ctx);
|
|
252
|
+
await this.dbConn.update(workflowInstances).set({ status: "completed" }).where(eq(workflowInstances.id, instance.id));
|
|
253
|
+
this.logger.info({ instanceId: instance.id }, "Workflow completed successfully");
|
|
254
|
+
} catch (err) {
|
|
255
|
+
if (err instanceof SuspendExecutionError || err.name === "SuspendExecutionError") {
|
|
256
|
+
await this.dbConn.update(workflowInstances).set({ status: "pending" }).where(eq(workflowInstances.id, instance.id));
|
|
257
|
+
this.logger.info({
|
|
258
|
+
instanceId: instance.id,
|
|
259
|
+
reason: err.reason
|
|
260
|
+
}, "Workflow suspended");
|
|
261
|
+
} else {
|
|
262
|
+
this.logger.error({
|
|
263
|
+
err,
|
|
264
|
+
instanceId: instance.id
|
|
265
|
+
}, "Workflow failed");
|
|
266
|
+
await this.dbConn.update(workflowInstances).set({ status: "failed" }).where(eq(workflowInstances.id, instance.id));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} finally {
|
|
270
|
+
clearInterval(renewTimer);
|
|
271
|
+
await this.redisCli.eval(LUA_RELEASE_LOCK, 1, lockKey, lockToken);
|
|
272
|
+
}
|
|
273
|
+
await Promise.all(publishPromises);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
async function startWorkflowWorker() {
|
|
277
|
+
logger = createLogger({
|
|
278
|
+
name: "workflow-worker",
|
|
279
|
+
level: config.LOG_LEVEL
|
|
280
|
+
});
|
|
281
|
+
redis = new RedisClient({
|
|
282
|
+
url: config.REDIS_URL,
|
|
283
|
+
name: "workflow",
|
|
284
|
+
logger
|
|
285
|
+
});
|
|
286
|
+
const dbData = createDatabase({
|
|
287
|
+
url: config.DATABASE_URL,
|
|
288
|
+
applicationName: "workflow",
|
|
289
|
+
logger
|
|
290
|
+
});
|
|
291
|
+
sql$1 = dbData.sql;
|
|
292
|
+
db = dbData.db;
|
|
293
|
+
notificationProducer = new StreamProducer({
|
|
294
|
+
redis: redis.native,
|
|
295
|
+
stream: STREAMS.INBOUND_NORMAL,
|
|
296
|
+
logger
|
|
297
|
+
});
|
|
298
|
+
workflowProducer = new StreamProducer({
|
|
299
|
+
redis: redis.native,
|
|
300
|
+
stream: STREAMS.WORKFLOW_INBOUND,
|
|
301
|
+
logger
|
|
302
|
+
});
|
|
303
|
+
consumer = new StreamConsumer({
|
|
304
|
+
redis: redis.native,
|
|
305
|
+
stream: STREAMS.WORKFLOW_INBOUND,
|
|
306
|
+
group: CONSUMER_GROUPS.WORKFLOW,
|
|
307
|
+
consumer: `workflow-${process.pid}`,
|
|
308
|
+
dlqStream: STREAMS.DEAD_LETTER,
|
|
309
|
+
batchSize: config.WORKER_CONCURRENCY,
|
|
310
|
+
logger
|
|
311
|
+
});
|
|
312
|
+
pendingScanner = new PendingMessageScanner({
|
|
313
|
+
redis: redis.native,
|
|
314
|
+
stream: STREAMS.WORKFLOW_INBOUND,
|
|
315
|
+
group: CONSUMER_GROUPS.WORKFLOW,
|
|
316
|
+
consumer: `workflow-${process.pid}`,
|
|
317
|
+
logger
|
|
318
|
+
});
|
|
319
|
+
worker = new WorkflowWorker({
|
|
320
|
+
consumer,
|
|
321
|
+
pendingScanner,
|
|
322
|
+
logger,
|
|
323
|
+
concurrency: config.WORKER_CONCURRENCY,
|
|
324
|
+
redis: redis.native,
|
|
325
|
+
db,
|
|
326
|
+
workflowProducer,
|
|
327
|
+
notificationProducer
|
|
328
|
+
});
|
|
329
|
+
pollInterval = setInterval(() => {
|
|
330
|
+
(async () => {
|
|
331
|
+
try {
|
|
332
|
+
const now = Date.now();
|
|
333
|
+
const tasks = await redis.native.eval(LUA_SCHEDULER_POLL, 1, "notif:workflow:timers", now, 100, WORKFLOW_TIMER_VISIBILITY_MS);
|
|
334
|
+
for (const taskStr of tasks) {
|
|
335
|
+
const task = JSON.parse(taskStr);
|
|
336
|
+
const inst = (await db.select().from(workflowInstances).where(eq(workflowInstances.id, task.instanceId)).limit(1))[0];
|
|
337
|
+
if (!inst || inst.status === "completed" || inst.status === "failed") {
|
|
338
|
+
await redis.native.zrem("notif:workflow:timers", taskStr);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (inst.status === "running") continue;
|
|
342
|
+
if (task.isEventTimeout) {
|
|
343
|
+
if ((await db.delete(workflowWaiters).where(and(eq(workflowWaiters.instanceId, task.instanceId), eq(workflowWaiters.eventName, task.eventName))).returning()).length === 0) {
|
|
344
|
+
await redis.native.zrem("notif:workflow:timers", taskStr);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const pendingStep = (await db.select().from(workflowSteps).where(and(eq(workflowSteps.instanceId, task.instanceId), eq(workflowSteps.action, "waitForEvent")))).find((s) => s.output === null);
|
|
348
|
+
if (pendingStep) await db.update(workflowSteps).set({ output: { timedOut: true } }).where(eq(workflowSteps.id, pendingStep.id));
|
|
349
|
+
}
|
|
350
|
+
await workflowProducer.publish(buildStreamEvent("workflow.resumed", task, "scheduler", void 0));
|
|
351
|
+
await redis.native.zrem("notif:workflow:timers", taskStr);
|
|
352
|
+
logger.info({ instanceId: task.instanceId }, "Workflow resumed from timer");
|
|
353
|
+
}
|
|
354
|
+
} catch (err) {
|
|
355
|
+
logger.error({ err }, "error in workflow polling loop");
|
|
356
|
+
}
|
|
357
|
+
})();
|
|
358
|
+
}, 5e3);
|
|
359
|
+
reaperInterval = setInterval(() => {
|
|
360
|
+
(async () => {
|
|
361
|
+
try {
|
|
362
|
+
const runningInstances = await db.select({ id: workflowInstances.id }).from(workflowInstances).where(eq(workflowInstances.status, "running"));
|
|
363
|
+
for (const inst of runningInstances) {
|
|
364
|
+
const lockKey = `lock:workflow:${inst.id}`;
|
|
365
|
+
if (!await redis.native.exists(lockKey)) {
|
|
366
|
+
await db.update(workflowInstances).set({ status: "pending" }).where(eq(workflowInstances.id, inst.id));
|
|
367
|
+
logger.info({ instanceId: inst.id }, "Reaped stuck workflow instance (lock expired)");
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
} catch (err) {
|
|
371
|
+
logger.error({ err }, "error in stuck workflow reaper");
|
|
372
|
+
}
|
|
373
|
+
})();
|
|
374
|
+
}, 6e4);
|
|
375
|
+
healthInterval = startHealthReporter("workflow", worker, redis, logger);
|
|
376
|
+
logger.info("workflow worker starting");
|
|
377
|
+
await worker.start();
|
|
378
|
+
}
|
|
379
|
+
async function stopWorkflowWorker() {
|
|
380
|
+
logger?.info("shutdown initiated");
|
|
381
|
+
if (healthInterval) clearInterval(healthInterval);
|
|
382
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
383
|
+
if (reaperInterval) clearInterval(reaperInterval);
|
|
384
|
+
if (worker) await worker.stop();
|
|
385
|
+
if (sql$1) await sql$1.end();
|
|
386
|
+
if (redis) await redis.disconnect();
|
|
387
|
+
logger?.info("workflow worker stopped");
|
|
388
|
+
}
|
|
389
|
+
//#endregion
|
|
390
|
+
export { startWorkflowWorker, stopWorkflowWorker };
|
|
391
|
+
|
|
392
|
+
//# sourceMappingURL=main-4H6vNXvy.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-4H6vNXvy.mjs","names":["sql"],"sources":["../src/services/workflow/main.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { loadEnv, readBaseConfig } from \"@/index.js\";\nimport { createLogger } from \"@/index.js\";\nimport { RedisClient, type Redis } from \"@/index.js\";\nimport {\n StreamConsumer,\n PendingMessageScanner,\n StreamProducer,\n type StreamMessage,\n} from \"@/index.js\";\nimport { BaseWorker } from \"@/index.js\";\nimport { STREAMS, CONSUMER_GROUPS, buildStreamEvent } from \"@/index.js\";\nimport { type StreamName } from \"@/contracts/streams.js\";\nimport { createDatabase } from \"@/db/index.js\";\nimport {\n workflowInstances,\n workflowSteps,\n workflowWaiters,\n workflowDefinitions,\n} from \"@/db/schema.js\";\nimport { eq, and } from \"drizzle-orm\";\nimport {\n workflowRegistry,\n SuspendExecutionError,\n buildStepNotifyPayload,\n type WorkflowContext,\n type WorkflowStepContext,\n} from \"@/workflows/index.js\";\nimport {\n type WorkerOptions,\n LUA_SCHEDULER_POLL,\n LUA_RELEASE_LOCK,\n LUA_RENEW_LOCK,\n} from \"@/shared/index.js\";\nimport { startHealthReporter } from \"@/workers/index.js\";\n\n/** How long a workflow instance lock is held before it self-expires. */\nconst WORKFLOW_LOCK_TTL_SECONDS = 60;\n/** Renew the lock well inside its TTL so long-running handlers keep it. */\nconst WORKFLOW_LOCK_RENEW_MS = (WORKFLOW_LOCK_TTL_SECONDS / 3) * 1000;\n/** How long a claimed workflow timer stays invisible to other pollers. */\nconst WORKFLOW_TIMER_VISIBILITY_MS = 60_000;\n\nloadEnv();\nconst config = readBaseConfig();\nlet logger: ReturnType<typeof createLogger>;\nlet redis: RedisClient;\nlet sql: any;\nlet db: any;\n\nlet consumer: StreamConsumer;\nlet pendingScanner: PendingMessageScanner;\nlet worker: BaseWorker;\nlet healthInterval: NodeJS.Timeout | null = null;\nlet pollInterval: NodeJS.Timeout | null = null;\nlet reaperInterval: NodeJS.Timeout | null = null;\n\nlet notificationProducer: StreamProducer;\nlet workflowProducer: StreamProducer;\n\nexport interface WorkflowWorkerOptions extends WorkerOptions {\n redis: Redis;\n db: any;\n workflowProducer: any;\n notificationProducer: any;\n}\n\nexport class WorkflowWorker extends BaseWorker {\n private readonly redisCli: Redis;\n private readonly dbConn: any;\n private readonly workflowProducer: any;\n private readonly notificationProducer: any;\n\n private eventBuffer: {\n producer: any;\n event: any;\n resolve: (result?: { messageId: string; notificationId: string }) => void;\n reject: (err: any) => void;\n }[] = [];\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(options: WorkflowWorkerOptions) {\n super(options);\n this.redisCli = options.redis;\n this.dbConn = options.db;\n this.workflowProducer = options.workflowProducer;\n this.notificationProducer = options.notificationProducer;\n\n this.flushTimer = setInterval(() => void this.flushWorkerBuffers(), 100);\n }\n\n override async stop(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushWorkerBuffers();\n await super.stop();\n }\n\n private async flushWorkerBuffers(): Promise<void> {\n if (this.eventBuffer.length === 0) return;\n\n const events = this.eventBuffer;\n this.eventBuffer = [];\n\n try {\n const byProducer = new Map<any, typeof events>();\n for (const item of events) {\n if (!byProducer.has(item.producer)) byProducer.set(item.producer, []);\n byProducer.get(item.producer)!.push(item);\n }\n\n for (const [producer, batch] of byProducer) {\n const { messageIds, eventIds } = await producer.publishBatch(batch.map((b) => b.event));\n for (let i = 0; i < batch.length; i++) {\n const mId = messageIds[i];\n const eId = eventIds[i];\n if (mId && eId) batch[i]!.resolve({ messageId: mId, notificationId: eId });\n }\n }\n } catch (err: any) {\n this.logger.error({ err }, \"failed to flush workflow worker buffer\");\n for (const e of events) e.reject(err);\n }\n }\n\n async process(message: StreamMessage): Promise<void> {\n const { event } = message;\n const publishPromises: Promise<void>[] = [];\n\n if (event.type !== \"workflow.triggered\" && event.type !== \"workflow.resumed\") {\n return;\n }\n\n const payload = event.payload as any;\n const name = payload.name;\n const instanceId = payload.instanceId;\n\n if (!name || !instanceId || !payload.projectId) {\n this.logger.warn(\"Missing name, instanceId, or projectId in workflow event\");\n return;\n }\n\n let handler = workflowRegistry.get(name);\n if (!handler) {\n // Fallback: check dynamic JSON workflows\n const defRows = await this.dbConn\n .select()\n .from(workflowDefinitions)\n .where(\n and(\n eq(workflowDefinitions.projectId, payload.projectId),\n eq(workflowDefinitions.name, name),\n ),\n )\n .limit(1);\n\n if (defRows.length === 0) {\n this.logger.warn(\n { name, projectId: payload.projectId },\n \"No handler or dynamic definition found for workflow\",\n );\n return;\n }\n\n const def = defRows[0];\n handler = async ({ step }) => {\n const steps = def.steps as any[];\n for (const stepDef of steps) {\n if (stepDef.action === \"notify\") {\n // A payload target wins; naming none inherits the instance user.\n await step.notify(stepDef.payload);\n } else if (stepDef.action === \"wait\") {\n await step.wait(stepDef.duration);\n } else if (stepDef.action === \"waitForEvent\") {\n await step.waitForEvent(stepDef.event, stepDef.options);\n } else {\n this.logger.warn(\n { action: (stepDef as any)?.action, name },\n \"unknown workflow step action\",\n );\n }\n }\n };\n }\n\n const lockKey = `lock:workflow:${instanceId}`;\n const lockToken = randomUUID();\n const acquired = await this.redisCli.set(\n lockKey,\n lockToken,\n \"EX\",\n WORKFLOW_LOCK_TTL_SECONDS,\n \"NX\",\n );\n if (!acquired) {\n this.logger.info({ instanceId }, \"Workflow is locked by another process, skipping\");\n return;\n }\n\n // Keep the lock alive while the handler runs; without this a handler that\n // outlives the TTL lets a second resume execute the same steps in parallel.\n const renewTimer = setInterval(() => {\n void this.redisCli\n .eval(LUA_RENEW_LOCK, 1, lockKey, lockToken, String(WORKFLOW_LOCK_TTL_SECONDS))\n .catch((err: unknown) => {\n this.logger.warn({ err, instanceId }, \"failed to renew workflow lock\");\n });\n }, WORKFLOW_LOCK_RENEW_MS);\n\n try {\n let instance = (\n await this.dbConn\n .select()\n .from(workflowInstances)\n .where(eq(workflowInstances.id, instanceId))\n .limit(1)\n )[0];\n if (!instance) {\n const rows = await this.dbConn\n .insert(workflowInstances)\n .values({\n id: instanceId,\n projectId: payload.projectId,\n name: name,\n status: \"pending\",\n input: payload.input || {},\n })\n .returning();\n instance = rows[0]!;\n }\n\n if (instance.status !== \"pending\") {\n this.logger.info({ instanceId }, \"Workflow is not pending, skipping\");\n return;\n }\n\n await this.dbConn\n .update(workflowInstances)\n .set({ status: \"running\" })\n .where(eq(workflowInstances.id, instanceId));\n\n // Load existing steps\n const existingSteps = await this.dbConn\n .select()\n .from(workflowSteps)\n .where(eq(workflowSteps.instanceId, instanceId));\n const stepOutputMap = new Map<string, any>();\n for (const s of existingSteps) {\n stepOutputMap.set(s.stepIndex, s.output);\n }\n\n let currentStepIndex = 0;\n\n const stepProxy: WorkflowStepContext = {\n notify: async (args) => {\n const stepId = String(currentStepIndex++);\n if (stepOutputMap.has(stepId)) return stepOutputMap.get(stepId);\n\n // The step payload is the same shape as notify(), but the wire event\n // is not — translate rather than spread.\n const requested = buildStepNotifyPayload(\n args,\n instance!.input,\n payload.projectId,\n `wf-${instanceId}-${stepId}`,\n );\n\n const result = await new Promise<{ messageId: string; notificationId: string }>(\n (resolve, reject) => {\n this.eventBuffer.push({\n producer: this.notificationProducer,\n event: buildStreamEvent(\n \"notification.requested\",\n requested as unknown as Record<string, unknown>,\n \"workflow\",\n event.metadata.traceId,\n ),\n resolve: resolve as any,\n reject,\n });\n },\n );\n\n const output = {\n success: true,\n messageId: result.messageId,\n notificationId: result.notificationId,\n };\n\n await this.dbConn.insert(workflowSteps).values({\n instanceId: instance!.id,\n projectId: payload.projectId,\n stepIndex: stepId,\n action: \"notify\",\n output,\n });\n\n return output;\n },\n wait: async (duration) => {\n const stepId = String(currentStepIndex++);\n if (stepOutputMap.has(stepId)) return;\n\n // Simple duration parse (e.g. '2h' -> ms)\n let ms = 0;\n if (duration.endsWith(\"d\")) ms = parseInt(duration) * 24 * 60 * 60 * 1000;\n else if (duration.endsWith(\"h\")) ms = parseInt(duration) * 60 * 60 * 1000;\n else if (duration.endsWith(\"m\")) ms = parseInt(duration) * 60 * 1000;\n else if (duration.endsWith(\"s\")) ms = parseInt(duration) * 1000;\n else throw new Error(`Invalid wait duration: ${duration}`);\n\n const resumeAt = Date.now() + ms;\n\n // Persist the wake-up signal before committing the suspended state.\n // If the process dies after this point the source event is retried;\n // if it dies after the database write, the timer is already durable.\n await this.redisCli.zadd(\n \"notif:workflow:timers\",\n resumeAt,\n JSON.stringify({\n instanceId: instance!.id,\n name: instance!.name,\n projectId: payload.projectId,\n input: instance!.input,\n }),\n );\n\n await this.dbConn.insert(workflowSteps).values({\n instanceId: instance!.id,\n projectId: payload.projectId,\n stepIndex: stepId,\n action: \"wait\",\n output: { scheduledAt: resumeAt },\n });\n\n throw new SuspendExecutionError(\"wait\", { duration });\n },\n waitForEvent: async (eventName, options) => {\n const stepId = String(currentStepIndex++);\n if (stepOutputMap.has(stepId)) {\n const out = stepOutputMap.get(stepId);\n if (out && typeof out === \"object\" && (out as any).timedOut === true) {\n return null;\n }\n return out;\n }\n\n options = options || {};\n options.timeout = options.timeout || \"24h\";\n options.match = options.match || {};\n\n let ms = 0;\n if (options.timeout.endsWith(\"d\")) ms = parseInt(options.timeout) * 24 * 60 * 60 * 1000;\n else if (options.timeout.endsWith(\"h\")) ms = parseInt(options.timeout) * 60 * 60 * 1000;\n else if (options.timeout.endsWith(\"m\")) ms = parseInt(options.timeout) * 60 * 1000;\n else if (options.timeout.endsWith(\"s\")) ms = parseInt(options.timeout) * 1000;\n else throw new Error(`Invalid waitForEvent timeout: ${options.timeout}`);\n\n const resumeAt = Date.now() + ms;\n\n await this.redisCli.zadd(\n \"notif:workflow:timers\",\n resumeAt,\n JSON.stringify({\n instanceId: instance!.id,\n name: instance!.name,\n projectId: payload.projectId,\n input: instance!.input,\n isEventTimeout: true,\n eventName,\n stepId,\n }),\n );\n\n // Register waiter\n await this.dbConn.insert(workflowWaiters).values({\n instanceId: instance!.id,\n projectId: payload.projectId,\n eventName: eventName,\n matchCriteria: options.match,\n expiresAt: new Date(resumeAt),\n });\n\n // Register step as pending event\n await this.dbConn.insert(workflowSteps).values({\n instanceId: instance!.id,\n projectId: payload.projectId,\n stepIndex: stepId,\n action: \"waitForEvent\",\n output: null, // this will be updated by event worker or timeout\n });\n\n throw new SuspendExecutionError(\"waitForEvent\", { eventName });\n },\n run: async (stepName, fn) => {\n const stepId = String(currentStepIndex++);\n if (stepOutputMap.has(stepId)) return stepOutputMap.get(stepId);\n\n const result = await fn();\n await this.dbConn.insert(workflowSteps).values({\n instanceId: instance!.id,\n projectId: payload.projectId,\n stepIndex: stepId,\n action: \"run\",\n output: result,\n });\n return result;\n },\n };\n\n const ctx: WorkflowContext = {\n step: stepProxy,\n event: (instance!.input as any) || { user: { id: \"unknown\" } },\n };\n\n try {\n await handler(ctx);\n // If we reach here, workflow completed\n await this.dbConn\n .update(workflowInstances)\n .set({ status: \"completed\" })\n .where(eq(workflowInstances.id, instance!.id));\n this.logger.info({ instanceId: instance!.id }, \"Workflow completed successfully\");\n } catch (err: any) {\n if (err instanceof SuspendExecutionError || err.name === \"SuspendExecutionError\") {\n await this.dbConn\n .update(workflowInstances)\n .set({ status: \"pending\" })\n .where(eq(workflowInstances.id, instance!.id));\n this.logger.info({ instanceId: instance!.id, reason: err.reason }, \"Workflow suspended\");\n } else {\n this.logger.error({ err, instanceId: instance!.id }, \"Workflow failed\");\n await this.dbConn\n .update(workflowInstances)\n .set({ status: \"failed\" })\n .where(eq(workflowInstances.id, instance!.id));\n }\n }\n } finally {\n clearInterval(renewTimer);\n // Compare-and-delete: never release a lock a later process re-acquired.\n await this.redisCli.eval(LUA_RELEASE_LOCK, 1, lockKey, lockToken);\n }\n\n await Promise.all(publishPromises);\n }\n}\n\nexport function __injectForTests(r: any, d: any, wp: any, np: any) {\n redis = r;\n db = d;\n workflowProducer = wp;\n notificationProducer = np;\n}\n\nexport async function startWorkflowWorker() {\n logger = createLogger({ name: \"workflow-worker\", level: config.LOG_LEVEL });\n redis = new RedisClient({ url: config.REDIS_URL, name: \"workflow\", logger });\n const dbData = createDatabase({ url: config.DATABASE_URL, applicationName: \"workflow\", logger });\n sql = dbData.sql;\n db = dbData.db;\n notificationProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.INBOUND_NORMAL,\n logger,\n });\n workflowProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.WORKFLOW_INBOUND,\n logger,\n });\n consumer = new StreamConsumer({\n redis: redis.native,\n stream: STREAMS.WORKFLOW_INBOUND as StreamName,\n group: CONSUMER_GROUPS.WORKFLOW as any,\n consumer: `workflow-${process.pid}`,\n dlqStream: STREAMS.DEAD_LETTER,\n batchSize: config.WORKER_CONCURRENCY,\n logger,\n });\n\n pendingScanner = new PendingMessageScanner({\n redis: redis.native,\n stream: STREAMS.WORKFLOW_INBOUND as StreamName,\n group: CONSUMER_GROUPS.WORKFLOW as any,\n consumer: `workflow-${process.pid}`,\n logger,\n });\n\n worker = new WorkflowWorker({\n consumer,\n pendingScanner,\n logger,\n concurrency: config.WORKER_CONCURRENCY,\n redis: redis.native,\n db,\n workflowProducer,\n notificationProducer,\n });\n\n // Polling loop for timers\n pollInterval = setInterval(() => {\n void (async () => {\n try {\n const now = Date.now();\n const tasks = (await redis.native.eval(\n LUA_SCHEDULER_POLL,\n 1,\n \"notif:workflow:timers\",\n now,\n 100,\n WORKFLOW_TIMER_VISIBILITY_MS,\n )) as string[];\n\n for (const taskStr of tasks) {\n const task = JSON.parse(taskStr);\n\n // Check if workflow is already completed/failed\n const inst = (\n await db\n .select()\n .from(workflowInstances)\n .where(eq(workflowInstances.id, task.instanceId))\n .limit(1)\n )[0];\n if (!inst || inst.status === \"completed\" || inst.status === \"failed\") {\n await redis.native.zrem(\"notif:workflow:timers\", taskStr);\n continue;\n }\n // A timer can be observed while the worker is still persisting the\n // corresponding suspension. Leave the claimed member in place; its\n // visibility timeout will make it eligible once the instance becomes\n // pending instead of losing the wake-up signal.\n if (inst.status === \"running\") continue;\n\n if (task.isEventTimeout) {\n // It's a timeout for waitForEvent. Clean up only this step's waiter\n const deleted = await db\n .delete(workflowWaiters)\n .where(\n and(\n eq(workflowWaiters.instanceId, task.instanceId),\n eq(workflowWaiters.eventName, task.eventName),\n ),\n )\n .returning();\n\n // If the waiter was already deleted (by EventWorker when event arrived before timeout),\n // this timer is stale. Clean up from Redis and skip re-resuming the workflow.\n if (deleted.length === 0) {\n await redis.native.zrem(\"notif:workflow:timers\", taskStr);\n continue;\n }\n\n // Record timedOut state on the pending waitForEvent step\n const steps = await db\n .select()\n .from(workflowSteps)\n .where(\n and(\n eq(workflowSteps.instanceId, task.instanceId),\n eq(workflowSteps.action, \"waitForEvent\"),\n ),\n );\n const pendingStep = steps.find((s: any) => s.output === null);\n if (pendingStep) {\n await db\n .update(workflowSteps)\n .set({ output: { timedOut: true } })\n .where(eq(workflowSteps.id, pendingStep.id));\n }\n }\n\n await workflowProducer.publish(\n buildStreamEvent(\"workflow.resumed\", task, \"scheduler\", undefined),\n );\n await redis.native.zrem(\"notif:workflow:timers\", taskStr);\n logger.info({ instanceId: task.instanceId }, \"Workflow resumed from timer\");\n }\n } catch (err) {\n logger.error({ err }, \"error in workflow polling loop\");\n }\n })();\n }, 5000);\n\n reaperInterval = setInterval(() => {\n void (async () => {\n try {\n const runningInstances = await db\n .select({ id: workflowInstances.id })\n .from(workflowInstances)\n .where(eq(workflowInstances.status, \"running\"));\n for (const inst of runningInstances) {\n const lockKey = `lock:workflow:${inst.id}`;\n const hasLock = await redis.native.exists(lockKey);\n if (!hasLock) {\n await db\n .update(workflowInstances)\n .set({ status: \"pending\" })\n .where(eq(workflowInstances.id, inst.id));\n logger.info({ instanceId: inst.id }, \"Reaped stuck workflow instance (lock expired)\");\n }\n }\n } catch (err) {\n logger.error({ err }, \"error in stuck workflow reaper\");\n }\n })();\n }, 60000);\n\n healthInterval = startHealthReporter(\"workflow\", worker, redis, logger);\n\n logger.info(\"workflow worker starting\");\n await worker.start();\n}\n\nexport async function stopWorkflowWorker(): Promise<void> {\n logger?.info(\"shutdown initiated\");\n if (healthInterval) clearInterval(healthInterval);\n if (pollInterval) clearInterval(pollInterval);\n if (reaperInterval) clearInterval(reaperInterval);\n if (worker) await worker.stop();\n if (sql) await sql.end();\n if (redis) await redis.disconnect();\n logger?.info(\"workflow worker stopped\");\n}\n"],"mappings":"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"}
|