pg-workflows 0.11.0 → 0.12.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 +43 -0
- package/dist/client.entry.d.cts +11 -1
- package/dist/client.entry.d.ts +11 -1
- package/dist/client.entry.js.map +1 -1
- package/dist/index.cjs +188 -6
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +192 -6
- package/dist/index.js.map +7 -6
- package/dist/shared/chunk-ahxqsytt.js.map +1 -1
- package/package.json +10 -1
package/dist/index.js
CHANGED
|
@@ -732,21 +732,32 @@ class WorkflowEngine {
|
|
|
732
732
|
};
|
|
733
733
|
let step = { ...baseStep };
|
|
734
734
|
const plugins = workflow2.plugins ?? [];
|
|
735
|
-
for (const plugin of plugins) {
|
|
736
|
-
const extra = plugin.methods(step);
|
|
737
|
-
step = { ...step, ...extra };
|
|
738
|
-
}
|
|
739
735
|
const context = {
|
|
740
736
|
input: run.input,
|
|
741
737
|
workflowId: run.workflowId,
|
|
742
738
|
runId: run.id,
|
|
739
|
+
resourceId: run.resourceId ?? undefined,
|
|
740
|
+
attempt: run.retryCount,
|
|
743
741
|
get timeline() {
|
|
744
742
|
return run?.timeline ?? {};
|
|
745
743
|
},
|
|
746
744
|
logger: this.logger,
|
|
747
745
|
step
|
|
748
746
|
};
|
|
749
|
-
const
|
|
747
|
+
for (const plugin of plugins) {
|
|
748
|
+
const extra = plugin.methods(step, context);
|
|
749
|
+
step = { ...step, ...extra };
|
|
750
|
+
context.step = step;
|
|
751
|
+
}
|
|
752
|
+
let next = () => workflow2.handler(context);
|
|
753
|
+
for (const plugin of [...plugins].reverse()) {
|
|
754
|
+
if (plugin.wrap) {
|
|
755
|
+
const inner = next;
|
|
756
|
+
const wrap = plugin.wrap;
|
|
757
|
+
next = () => wrap(context, inner);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
const result = await next();
|
|
750
761
|
run = await this.getRun({ runId, resourceId: scopedResourceId });
|
|
751
762
|
const isLastParsedStep = run.currentStepId === workflow2.steps[workflow2.steps.length - 1]?.id;
|
|
752
763
|
const hasPluginSteps = (workflow2.plugins?.length ?? 0) > 0;
|
|
@@ -1279,8 +1290,183 @@ ${error.stack}` : String(error)
|
|
|
1279
1290
|
}, this.db);
|
|
1280
1291
|
}
|
|
1281
1292
|
}
|
|
1293
|
+
// src/plugins/otel.ts
|
|
1294
|
+
import {
|
|
1295
|
+
context as otelContext,
|
|
1296
|
+
SpanStatusCode,
|
|
1297
|
+
trace
|
|
1298
|
+
} from "@opentelemetry/api";
|
|
1299
|
+
var DEFAULT_PREFIX = "pg_workflows";
|
|
1300
|
+
function isCachedHit(timeline, stepId, kind) {
|
|
1301
|
+
const entry = timeline[stepId];
|
|
1302
|
+
if (entry && typeof entry === "object" && "output" in entry && entry.output !== undefined) {
|
|
1303
|
+
return true;
|
|
1304
|
+
}
|
|
1305
|
+
if (kind === "invokeChildWorkflow" && timeline[invokeChildWorkflowTimelineKey(stepId)]) {
|
|
1306
|
+
return true;
|
|
1307
|
+
}
|
|
1308
|
+
return false;
|
|
1309
|
+
}
|
|
1310
|
+
function otelPlugin(options = {}) {
|
|
1311
|
+
const tracer = options.tracer ?? trace.getTracer("pg-workflows");
|
|
1312
|
+
const prefix = options.spanNamePrefix ?? DEFAULT_PREFIX;
|
|
1313
|
+
const extraAttrs = options.attributes;
|
|
1314
|
+
return {
|
|
1315
|
+
name: "opentelemetry",
|
|
1316
|
+
methods: (step, context) => {
|
|
1317
|
+
const wrapVoidish = (kind, base) => {
|
|
1318
|
+
return async (stepId, ...args) => {
|
|
1319
|
+
if (isCachedHit(context.timeline, stepId, kind)) {
|
|
1320
|
+
return base(stepId, ...args);
|
|
1321
|
+
}
|
|
1322
|
+
const capturedCtx = otelContext.active();
|
|
1323
|
+
const startTime = new Date;
|
|
1324
|
+
let result;
|
|
1325
|
+
let originalErr;
|
|
1326
|
+
let thrownError;
|
|
1327
|
+
try {
|
|
1328
|
+
result = await base(stepId, ...args);
|
|
1329
|
+
} catch (err) {
|
|
1330
|
+
originalErr = err;
|
|
1331
|
+
thrownError = err instanceof Error ? err : new Error(String(err));
|
|
1332
|
+
}
|
|
1333
|
+
const span = tracer.startSpan(`${prefix}.step.${kind}`, {
|
|
1334
|
+
startTime,
|
|
1335
|
+
attributes: { "step.id": stepId, "step.type": kind }
|
|
1336
|
+
}, capturedCtx);
|
|
1337
|
+
if (thrownError) {
|
|
1338
|
+
span.recordException(thrownError);
|
|
1339
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: thrownError.message });
|
|
1340
|
+
span.end();
|
|
1341
|
+
throw originalErr;
|
|
1342
|
+
}
|
|
1343
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1344
|
+
span.end();
|
|
1345
|
+
return result;
|
|
1346
|
+
};
|
|
1347
|
+
};
|
|
1348
|
+
return {
|
|
1349
|
+
run: async (stepId, handler) => {
|
|
1350
|
+
if (isCachedHit(context.timeline, stepId, "run")) {
|
|
1351
|
+
return step.run(stepId, handler);
|
|
1352
|
+
}
|
|
1353
|
+
const capturedCtx = otelContext.active();
|
|
1354
|
+
const startTime = new Date;
|
|
1355
|
+
let result;
|
|
1356
|
+
let originalErr;
|
|
1357
|
+
let thrownError;
|
|
1358
|
+
try {
|
|
1359
|
+
result = await step.run(stepId, handler);
|
|
1360
|
+
} catch (err) {
|
|
1361
|
+
originalErr = err;
|
|
1362
|
+
thrownError = err instanceof Error ? err : new Error(String(err));
|
|
1363
|
+
}
|
|
1364
|
+
if (result === undefined && !thrownError) {
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
const span = tracer.startSpan(`${prefix}.step.run`, {
|
|
1368
|
+
startTime,
|
|
1369
|
+
attributes: { "step.id": stepId, "step.type": "run" }
|
|
1370
|
+
}, capturedCtx);
|
|
1371
|
+
if (thrownError) {
|
|
1372
|
+
span.recordException(thrownError);
|
|
1373
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: thrownError.message });
|
|
1374
|
+
span.end();
|
|
1375
|
+
throw originalErr;
|
|
1376
|
+
}
|
|
1377
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1378
|
+
span.end();
|
|
1379
|
+
return result;
|
|
1380
|
+
},
|
|
1381
|
+
waitFor: wrapVoidish("waitFor", step.waitFor),
|
|
1382
|
+
delay: wrapVoidish("delay", step.delay),
|
|
1383
|
+
sleep: wrapVoidish("delay", step.delay),
|
|
1384
|
+
waitUntil: wrapVoidish("waitUntil", step.waitUntil),
|
|
1385
|
+
pause: wrapVoidish("pause", step.pause),
|
|
1386
|
+
poll: async (stepId, conditionFn, pollOptions) => {
|
|
1387
|
+
const capturedCtx = otelContext.active();
|
|
1388
|
+
const startTime = new Date;
|
|
1389
|
+
let result;
|
|
1390
|
+
let originalErr;
|
|
1391
|
+
let thrownError;
|
|
1392
|
+
try {
|
|
1393
|
+
result = await step.poll(stepId, conditionFn, pollOptions);
|
|
1394
|
+
} catch (err) {
|
|
1395
|
+
originalErr = err;
|
|
1396
|
+
thrownError = err instanceof Error ? err : new Error(String(err));
|
|
1397
|
+
}
|
|
1398
|
+
const span = tracer.startSpan(`${prefix}.step.poll`, {
|
|
1399
|
+
startTime,
|
|
1400
|
+
attributes: { "step.id": stepId, "step.type": "poll" }
|
|
1401
|
+
}, capturedCtx);
|
|
1402
|
+
if (thrownError) {
|
|
1403
|
+
span.recordException(thrownError);
|
|
1404
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: thrownError.message });
|
|
1405
|
+
span.end();
|
|
1406
|
+
throw originalErr;
|
|
1407
|
+
}
|
|
1408
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1409
|
+
span.end();
|
|
1410
|
+
return result;
|
|
1411
|
+
},
|
|
1412
|
+
invokeChildWorkflow: async (stepId, refOrParams, inputArg, optionsArg) => {
|
|
1413
|
+
if (isCachedHit(context.timeline, stepId, "invokeChildWorkflow")) {
|
|
1414
|
+
return step.invokeChildWorkflow(stepId, refOrParams, inputArg, optionsArg);
|
|
1415
|
+
}
|
|
1416
|
+
const capturedCtx = otelContext.active();
|
|
1417
|
+
const startTime = new Date;
|
|
1418
|
+
let result;
|
|
1419
|
+
let originalErr;
|
|
1420
|
+
let thrownError;
|
|
1421
|
+
try {
|
|
1422
|
+
result = await step.invokeChildWorkflow(stepId, refOrParams, inputArg, optionsArg);
|
|
1423
|
+
} catch (err) {
|
|
1424
|
+
originalErr = err;
|
|
1425
|
+
thrownError = err instanceof Error ? err : new Error(String(err));
|
|
1426
|
+
}
|
|
1427
|
+
const span = tracer.startSpan(`${prefix}.step.invokeChildWorkflow`, {
|
|
1428
|
+
startTime,
|
|
1429
|
+
attributes: { "step.id": stepId, "step.type": "invokeChildWorkflow" }
|
|
1430
|
+
}, capturedCtx);
|
|
1431
|
+
if (thrownError) {
|
|
1432
|
+
span.recordException(thrownError);
|
|
1433
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: thrownError.message });
|
|
1434
|
+
span.end();
|
|
1435
|
+
throw originalErr;
|
|
1436
|
+
}
|
|
1437
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1438
|
+
span.end();
|
|
1439
|
+
return result;
|
|
1440
|
+
}
|
|
1441
|
+
};
|
|
1442
|
+
},
|
|
1443
|
+
wrap: (context, next) => tracer.startActiveSpan(`${prefix}.workflow.run`, {
|
|
1444
|
+
attributes: {
|
|
1445
|
+
"workflow.id": context.workflowId,
|
|
1446
|
+
"workflow.run_id": context.runId,
|
|
1447
|
+
"workflow.attempt": context.attempt,
|
|
1448
|
+
...context.resourceId ? { "workflow.resource_id": context.resourceId } : {},
|
|
1449
|
+
...extraAttrs ? extraAttrs(context) : {}
|
|
1450
|
+
}
|
|
1451
|
+
}, async (span) => {
|
|
1452
|
+
try {
|
|
1453
|
+
const result = await next();
|
|
1454
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1455
|
+
return result;
|
|
1456
|
+
} catch (err) {
|
|
1457
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1458
|
+
span.recordException(error);
|
|
1459
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
1460
|
+
throw err;
|
|
1461
|
+
} finally {
|
|
1462
|
+
span.end();
|
|
1463
|
+
}
|
|
1464
|
+
})
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1282
1467
|
export {
|
|
1283
1468
|
workflow,
|
|
1469
|
+
otelPlugin,
|
|
1284
1470
|
createWorkflowRef,
|
|
1285
1471
|
WorkflowStatus,
|
|
1286
1472
|
WorkflowRunNotFoundError,
|
|
@@ -1289,5 +1475,5 @@ export {
|
|
|
1289
1475
|
WorkflowClient
|
|
1290
1476
|
};
|
|
1291
1477
|
|
|
1292
|
-
//# debugId=
|
|
1478
|
+
//# debugId=3131CBB2B482181264756E2164756E21
|
|
1293
1479
|
//# sourceMappingURL=index.js.map
|