@openapi-typescript-infra/temporal-worker 1.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 +3 -0
- package/build/Temporal.d.ts +20 -0
- package/build/Temporal.js +141 -0
- package/build/Temporal.js.map +1 -0
- package/build/config.d.ts +13 -0
- package/build/config.js +1 -0
- package/build/config.js.map +1 -0
- package/build/createActivities.d.ts +15 -0
- package/build/createActivities.js +59 -0
- package/build/createActivities.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/workflow/BaseContext.d.ts +22 -0
- package/build/workflow/BaseContext.js +48 -0
- package/build/workflow/BaseContext.js.map +1 -0
- package/build/workflow/Triggers.d.ts +14 -0
- package/build/workflow/Triggers.js +81 -0
- package/build/workflow/Triggers.js.map +1 -0
- package/build/workflow/index.d.ts +3 -0
- package/build/workflow/index.js +4 -0
- package/build/workflow/index.js.map +1 -0
- package/build/workflow/utils.d.ts +24 -0
- package/build/workflow/utils.js +79 -0
- package/build/workflow/utils.js.map +1 -0
- package/package.json +94 -0
package/README.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# @openapi-typescript-infra/temporal-worker
|
|
2
|
+
|
|
3
|
+
A Typescript node module to centralize some boilerplate around creating Temporal.io workers. The module will wire up Temporal logging to @openapi-typescript-infra/service logging and take care of spin up and spin down as well as a default workflow code location.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ConnectionLike } from '@temporalio/client';
|
|
2
|
+
import { Client } from '@temporalio/client';
|
|
3
|
+
import type { WorkerOptions } from '@temporalio/worker';
|
|
4
|
+
import { Worker } from '@temporalio/worker';
|
|
5
|
+
import type { ServiceExpress } from '@openapi-typescript-infra/service';
|
|
6
|
+
import type { TemporalWorkerConfig } from './config.js';
|
|
7
|
+
export declare class Temporal {
|
|
8
|
+
private app;
|
|
9
|
+
private namespace;
|
|
10
|
+
private worker?;
|
|
11
|
+
private workerPromise;
|
|
12
|
+
private connection?;
|
|
13
|
+
private _client?;
|
|
14
|
+
constructor(app: ServiceExpress);
|
|
15
|
+
get client(): Client;
|
|
16
|
+
start(config: TemporalWorkerConfig, activities: WorkerOptions['activities'], workflowsPath?: string): Promise<void>;
|
|
17
|
+
stop(): Promise<void>;
|
|
18
|
+
setClientConnection(connection: ConnectionLike): void;
|
|
19
|
+
setWorker(worker: Worker): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { Client, Connection } from '@temporalio/client';
|
|
3
|
+
import { NativeConnection, Runtime, Worker, makeTelemetryFilterString } from '@temporalio/worker';
|
|
4
|
+
import { getNodeEnv } from '@openapi-typescript-infra/service';
|
|
5
|
+
let runtimeInstalled = false;
|
|
6
|
+
function init(app) {
|
|
7
|
+
if (!runtimeInstalled) {
|
|
8
|
+
const { logger } = app.locals;
|
|
9
|
+
const temporalLogger = {
|
|
10
|
+
trace(message, meta) {
|
|
11
|
+
logger.trace(meta, message);
|
|
12
|
+
},
|
|
13
|
+
debug(message, meta) {
|
|
14
|
+
logger.debug(meta, message);
|
|
15
|
+
},
|
|
16
|
+
info(message, meta) {
|
|
17
|
+
logger.info(meta, message);
|
|
18
|
+
},
|
|
19
|
+
warn(message, meta) {
|
|
20
|
+
logger.warn(meta, message);
|
|
21
|
+
},
|
|
22
|
+
error(message, meta) {
|
|
23
|
+
logger.error(meta, message);
|
|
24
|
+
},
|
|
25
|
+
log(level, message, meta) {
|
|
26
|
+
const l = level.toLowerCase();
|
|
27
|
+
if (['trace', 'debug', 'info', 'warn', 'error'].includes(l)) {
|
|
28
|
+
logger[l](meta, message);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
logger.warn({ originalLevel: l, originalMessage: message }, 'Unknown log level');
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
const logLevel = process.env.TEMPORAL_LOG_LEVEL ||
|
|
36
|
+
(getNodeEnv() === 'development' ? 'INFO' : 'WARN');
|
|
37
|
+
Runtime.install({
|
|
38
|
+
logger: temporalLogger,
|
|
39
|
+
shutdownSignals: [],
|
|
40
|
+
telemetryOptions: {
|
|
41
|
+
metrics: {
|
|
42
|
+
prometheus: { bindAddress: '0.0.0.0:9464' },
|
|
43
|
+
},
|
|
44
|
+
logging: {
|
|
45
|
+
filter: makeTelemetryFilterString({
|
|
46
|
+
core: logLevel,
|
|
47
|
+
other: logLevel,
|
|
48
|
+
}),
|
|
49
|
+
forward: {},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
runtimeInstalled = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class Temporal {
|
|
57
|
+
app;
|
|
58
|
+
namespace;
|
|
59
|
+
worker;
|
|
60
|
+
workerPromise;
|
|
61
|
+
connection;
|
|
62
|
+
_client;
|
|
63
|
+
constructor(app) {
|
|
64
|
+
this.app = app;
|
|
65
|
+
}
|
|
66
|
+
get client() {
|
|
67
|
+
if (!this._client) {
|
|
68
|
+
throw new Error('Temporal not connected');
|
|
69
|
+
}
|
|
70
|
+
return this._client;
|
|
71
|
+
}
|
|
72
|
+
async start(config, activities, workflowsPath) {
|
|
73
|
+
const { address, tls, clientEnabled, namespace, workerEnabled, ...workerConfig } = config;
|
|
74
|
+
this.namespace = namespace;
|
|
75
|
+
if (clientEnabled === false && !workerEnabled) {
|
|
76
|
+
// No point in doing anything
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
init(this.app);
|
|
80
|
+
if (clientEnabled !== false) {
|
|
81
|
+
const connection = Connection.lazy({ address, tls: tls });
|
|
82
|
+
this._client = new Client({ connection, namespace });
|
|
83
|
+
this.app.locals.logger.info({ namespace }, 'Started Temporal client');
|
|
84
|
+
}
|
|
85
|
+
if (!workerEnabled) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.connection = await NativeConnection.connect({
|
|
89
|
+
address,
|
|
90
|
+
tls: tls,
|
|
91
|
+
});
|
|
92
|
+
this.worker = await Worker.create({
|
|
93
|
+
connection: this.connection,
|
|
94
|
+
namespace,
|
|
95
|
+
activities,
|
|
96
|
+
workflowsPath: workflowsPath || path.resolve('src/temporal/workflows'),
|
|
97
|
+
...workerConfig,
|
|
98
|
+
});
|
|
99
|
+
this.workerPromise = this.worker.run().catch((error) => {
|
|
100
|
+
this.app.locals.logger.warn(error, 'Temporal worker failed, shutting down');
|
|
101
|
+
const stopPromise = this.app.locals.service.stop?.(this.app);
|
|
102
|
+
if (stopPromise) {
|
|
103
|
+
stopPromise.catch((stopError) => {
|
|
104
|
+
// eslint-disable-next-line no-console
|
|
105
|
+
console.error('Failed to stop the app', stopError);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
this.app.locals.logger.info('Started Temporal worker');
|
|
110
|
+
}
|
|
111
|
+
async stop() {
|
|
112
|
+
try {
|
|
113
|
+
if (this.worker) {
|
|
114
|
+
this.worker.shutdown();
|
|
115
|
+
await this.workerPromise;
|
|
116
|
+
await this.connection?.close();
|
|
117
|
+
delete this.worker;
|
|
118
|
+
delete this.connection;
|
|
119
|
+
delete this.workerPromise;
|
|
120
|
+
}
|
|
121
|
+
if (this._client) {
|
|
122
|
+
await this._client.connection.close();
|
|
123
|
+
delete this._client;
|
|
124
|
+
}
|
|
125
|
+
if (runtimeInstalled) {
|
|
126
|
+
await Runtime.instance().shutdown();
|
|
127
|
+
runtimeInstalled = false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.app.locals.logger.warn(error, 'Failed to stop Temporal');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
setClientConnection(connection) {
|
|
135
|
+
this._client = new Client({ connection, namespace: this.namespace });
|
|
136
|
+
}
|
|
137
|
+
setWorker(worker) {
|
|
138
|
+
this.worker = worker;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=Temporal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Temporal.js","sourceRoot":"","sources":["../src/Temporal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WorkerOptions } from '@temporalio/worker';
|
|
2
|
+
export interface TemporalWorkerConfig extends WorkerOptions {
|
|
3
|
+
clientEnabled?: boolean;
|
|
4
|
+
workerEnabled?: boolean;
|
|
5
|
+
address: string;
|
|
6
|
+
namespace?: string;
|
|
7
|
+
tls?: {
|
|
8
|
+
clientCertPair: {
|
|
9
|
+
key: Uint8Array;
|
|
10
|
+
crt: Uint8Array;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
package/build/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ServiceExpress } from '@openapi-typescript-infra/service';
|
|
2
|
+
type GenericAny = any;
|
|
3
|
+
type TailParameters<T, AppType> = T extends (arg0: AppType, ...rest: infer P) => GenericAny ? P : never;
|
|
4
|
+
type ExcludeFirstParamFn<F, AppType> = F extends (...args: GenericAny[]) => infer R ? (...args: TailParameters<F, AppType>) => R : never;
|
|
5
|
+
type ExcludeFirstParamMap<AppType, T> = {
|
|
6
|
+
[K in keyof T]: ExcludeFirstParamFn<T[K], AppType>;
|
|
7
|
+
};
|
|
8
|
+
export declare function createActivities<AppType extends ServiceExpress, Fns extends Record<string, (app: AppType, ...args: GenericAny[]) => GenericAny>>(app: AppType, fns: Fns): ExcludeFirstParamMap<AppType, Fns>;
|
|
9
|
+
/**
|
|
10
|
+
* Combine outputs of createActivities, making sure there are no clashes.
|
|
11
|
+
*/
|
|
12
|
+
export declare function combineActivities<Fns extends Record<string, (...args: GenericAny[]) => GenericAny>[]>(...fnList: Fns): {
|
|
13
|
+
[K in keyof Fns[number]]: Fns[number][K];
|
|
14
|
+
};
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Context } from '@temporalio/activity';
|
|
2
|
+
export function createActivities(app, fns) {
|
|
3
|
+
const result = {};
|
|
4
|
+
Object.keys(fns).forEach((key) => {
|
|
5
|
+
// Dynamically wrapping each function to inject `app` as the first parameter
|
|
6
|
+
result[key] = async (...args) => {
|
|
7
|
+
const context = Context.current();
|
|
8
|
+
function logFn(level, attrOrMessage, message) {
|
|
9
|
+
// This will pipe back to our logs
|
|
10
|
+
if (typeof attrOrMessage === 'string') {
|
|
11
|
+
context.log[level](attrOrMessage);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
context.log[level](message, attrOrMessage);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const contextApp = {
|
|
18
|
+
...app,
|
|
19
|
+
locals: {
|
|
20
|
+
...app.locals,
|
|
21
|
+
logger: {
|
|
22
|
+
trace: logFn.bind(null, 'trace'),
|
|
23
|
+
debug: logFn.bind(null, 'debug'),
|
|
24
|
+
info: logFn.bind(null, 'info'),
|
|
25
|
+
warn: logFn.bind(null, 'warn'),
|
|
26
|
+
error: logFn.bind(null, 'error'),
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
const result = await fns[key](contextApp, ...args);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
app.locals.logger.error(Object.assign(error, {
|
|
36
|
+
activity: key,
|
|
37
|
+
workflow: context.info.workflowExecution.workflowId,
|
|
38
|
+
}), `Error in activity ${key}`);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Combine outputs of createActivities, making sure there are no clashes.
|
|
47
|
+
*/
|
|
48
|
+
export function combineActivities(...fnList) {
|
|
49
|
+
const result = {};
|
|
50
|
+
fnList.forEach((fns) => {
|
|
51
|
+
const clashes = Object.keys(fns).filter((key) => result[key]);
|
|
52
|
+
if (clashes.length) {
|
|
53
|
+
throw new Error(`Duplicate activity names: ${clashes.join(', ')}`);
|
|
54
|
+
}
|
|
55
|
+
Object.assign(result, fns);
|
|
56
|
+
});
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=createActivities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createActivities.js","sourceRoot":"","sources":["../src/createActivities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAoB/C,MAAM,UAAU,gBAAgB,CAG9B,GAAY,EAAE,GAAQ;IACtB,MAAM,MAAM,GAAoD,EAAE,CAAC;IAEnE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC/B,4EAA4E;QAC5E,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;YACzC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YAClC,SAAS,KAAK,CACZ,KAAoD,EACpD,aAA+C,EAC/C,OAAgB;gBAEhB,kCAAkC;gBAClC,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;oBACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC;gBACpC,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAiB,EAAE,aAAa,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YAED,MAAM,UAAU,GAAY;gBAC1B,GAAG,GAAG;gBACN,MAAM,EAAE;oBACN,GAAG,GAAG,CAAC,MAAM;oBACb,MAAM,EAAE;wBACN,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;wBAChC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;wBAChC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;wBAC9B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;wBAC9B,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;qBACjC;iBACF;aACF,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;gBACnD,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CACrB,MAAM,CAAC,MAAM,CAAC,KAAc,EAAE;oBAC5B,QAAQ,EAAE,GAAG;oBACb,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU;iBACpD,CAAC,EACF,qBAAqB,GAAG,EAAE,CAC3B,CAAC;gBACF,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,MAA4C,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAE/B,GAAG,MAAW;IACd,MAAM,MAAM,GAAoD,EAAE,CAAC;IAEnE,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,OAAO,MAAsD,CAAC;AAChE,CAAC"}
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
type BaseContext = object;
|
|
2
|
+
/**
|
|
3
|
+
* BE CAREFUL! If you modify the logic here you may cause an NDE for existing workflows.
|
|
4
|
+
* Use patched() to guard new operations.
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class BaseWorkflowContext<SpecificContext extends BaseContext> {
|
|
7
|
+
protected context: SpecificContext;
|
|
8
|
+
didCancel: boolean;
|
|
9
|
+
stage: string;
|
|
10
|
+
waitingUntil?: string;
|
|
11
|
+
constructor(context: SpecificContext);
|
|
12
|
+
/**
|
|
13
|
+
* Run any cancellation activities.
|
|
14
|
+
*/
|
|
15
|
+
abstract cancel(): Promise<void>;
|
|
16
|
+
setProgress(stage: string, until?: string): void;
|
|
17
|
+
endWorkflow(): Promise<{
|
|
18
|
+
outcome: string;
|
|
19
|
+
}>;
|
|
20
|
+
handleCancelOrThrow(e: unknown): void;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { log, upsertSearchAttributes } from '@temporalio/workflow';
|
|
2
|
+
import { isCancelError, workflowLog } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* BE CAREFUL! If you modify the logic here you may cause an NDE for existing workflows.
|
|
5
|
+
* Use patched() to guard new operations.
|
|
6
|
+
*/
|
|
7
|
+
export class BaseWorkflowContext {
|
|
8
|
+
context;
|
|
9
|
+
didCancel = false;
|
|
10
|
+
stage = 'start';
|
|
11
|
+
waitingUntil;
|
|
12
|
+
constructor(context) {
|
|
13
|
+
this.context = context;
|
|
14
|
+
}
|
|
15
|
+
setProgress(stage, until) {
|
|
16
|
+
if (until) {
|
|
17
|
+
workflowLog.info({ until, stage }, 'Sleeping');
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
workflowLog.debug({ stage }, 'Progress');
|
|
21
|
+
}
|
|
22
|
+
this.stage = stage;
|
|
23
|
+
upsertSearchAttributes({ CurrentStage: [this.stage] });
|
|
24
|
+
this.waitingUntil = until;
|
|
25
|
+
}
|
|
26
|
+
async endWorkflow() {
|
|
27
|
+
log.info('The workflow will terminate');
|
|
28
|
+
if (this.didCancel) {
|
|
29
|
+
this.setProgress('cancel');
|
|
30
|
+
await this.cancel();
|
|
31
|
+
return { outcome: 'canceled' };
|
|
32
|
+
}
|
|
33
|
+
this.setProgress('ending');
|
|
34
|
+
return { outcome: 'completed' };
|
|
35
|
+
}
|
|
36
|
+
handleCancelOrThrow(e) {
|
|
37
|
+
if (isCancelError(e)) {
|
|
38
|
+
// This allows the activity exceptions to do what the signal would have done
|
|
39
|
+
// without having direct access to the workflow context.
|
|
40
|
+
this.didCancel = true;
|
|
41
|
+
workflowLog.info('Cancellation signal received');
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
throw e;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=BaseContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseContext.js","sourceRoot":"","sources":["../../src/workflow/BaseContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIxD;;;GAGG;AACH,MAAM,OAAgB,mBAAmB;IAKjB;IAJtB,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,GAAG,OAAO,CAAC;IAChB,YAAY,CAAU;IAEtB,YAAsB,OAAwB;QAAxB,YAAO,GAAP,OAAO,CAAiB;IAAG,CAAC;IAOlD,WAAW,CAAC,KAAa,EAAE,KAAc;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,sBAAsB,CAAC,EAAE,YAAY,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW;QACf,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;IAED,mBAAmB,CAAC,CAAU;QAC5B,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,4EAA4E;YAC5E,wDAAwD;YACxD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,WAAW,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Trigger } from '@temporalio/workflow';
|
|
2
|
+
import { WAIT_COMPLETE } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* This class makes it easier to manage a set of signals that can be awaited on.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Triggers<T extends Record<keyof T, object>> {
|
|
7
|
+
private triggers;
|
|
8
|
+
withTrigger<K extends keyof T, R>(key: K, fn: (trigger: Trigger<T[K]>) => Promise<T[K] | R>): Promise<T[K] | R>;
|
|
9
|
+
waitFor<K extends keyof T>(key: K): Promise<T[K]>;
|
|
10
|
+
waitForFirst<K extends keyof T>(...keys: K[]): Promise<[K, T[K]]>;
|
|
11
|
+
waitUntilTriggersOrSpecificTime<K extends keyof T>(targetTime: Date, ...keys: K[]): Promise<T[K] | typeof WAIT_COMPLETE>;
|
|
12
|
+
resolve<K extends keyof T>(key: K, value: T[K]): void;
|
|
13
|
+
reject<K extends keyof T>(key: K, error: unknown): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { sleep, Trigger } from '@temporalio/workflow';
|
|
2
|
+
import { WAIT_COMPLETE } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* This class makes it easier to manage a set of signals that can be awaited on.
|
|
5
|
+
*/
|
|
6
|
+
export class Triggers {
|
|
7
|
+
triggers = {};
|
|
8
|
+
async withTrigger(key, fn) {
|
|
9
|
+
this.triggers[key] = this.triggers[key] ?? new Trigger();
|
|
10
|
+
try {
|
|
11
|
+
return await fn(this.triggers[key]);
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
delete this.triggers[key];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async waitFor(key) {
|
|
18
|
+
if (!this.triggers[key]) {
|
|
19
|
+
this.triggers[key] = new Trigger();
|
|
20
|
+
}
|
|
21
|
+
const trigger = this.triggers[key];
|
|
22
|
+
try {
|
|
23
|
+
return await trigger;
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
delete this.triggers[key];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async waitForFirst(...keys) {
|
|
30
|
+
const promises = keys.map(async (key) => {
|
|
31
|
+
if (!this.triggers[key]) {
|
|
32
|
+
this.triggers[key] = new Trigger();
|
|
33
|
+
}
|
|
34
|
+
const result = await this.triggers[key];
|
|
35
|
+
return [key, result];
|
|
36
|
+
});
|
|
37
|
+
const firstResolved = await Promise.race(promises);
|
|
38
|
+
// Clean up all triggers after the first one resolves
|
|
39
|
+
for (const key of keys) {
|
|
40
|
+
delete this.triggers[key];
|
|
41
|
+
}
|
|
42
|
+
return firstResolved;
|
|
43
|
+
}
|
|
44
|
+
async waitUntilTriggersOrSpecificTime(targetTime, ...keys) {
|
|
45
|
+
const currentTime = new Date();
|
|
46
|
+
const delay = targetTime.getTime() - currentTime.getTime();
|
|
47
|
+
if (delay > 0) {
|
|
48
|
+
const triggerPromises = keys.map((key) => {
|
|
49
|
+
if (!this.triggers[key]) {
|
|
50
|
+
this.triggers[key] = new Trigger();
|
|
51
|
+
}
|
|
52
|
+
return this.triggers[key];
|
|
53
|
+
});
|
|
54
|
+
// We can't use waitForFirst here because if the sleep wins, that would end
|
|
55
|
+
// up resetting all the triggers when it resolved, even if we've moved on from it.
|
|
56
|
+
const result = await Promise.race([
|
|
57
|
+
sleep(delay).then(() => WAIT_COMPLETE),
|
|
58
|
+
...triggerPromises,
|
|
59
|
+
]);
|
|
60
|
+
// Clean up all triggers after the first one resolves
|
|
61
|
+
for (const key of keys) {
|
|
62
|
+
delete this.triggers[key];
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
return WAIT_COMPLETE;
|
|
67
|
+
}
|
|
68
|
+
resolve(key, value) {
|
|
69
|
+
if (!this.triggers[key]) {
|
|
70
|
+
this.triggers[key] = new Trigger();
|
|
71
|
+
}
|
|
72
|
+
this.triggers[key].resolve(value);
|
|
73
|
+
}
|
|
74
|
+
reject(key, error) {
|
|
75
|
+
if (!this.triggers[key]) {
|
|
76
|
+
this.triggers[key] = new Trigger();
|
|
77
|
+
}
|
|
78
|
+
this.triggers[key].reject(error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=Triggers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Triggers.js","sourceRoot":"","sources":["../../src/workflow/Triggers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workflow/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Trigger } from '@temporalio/workflow';
|
|
2
|
+
import { ActivityFailure } from '@temporalio/workflow';
|
|
3
|
+
export declare const WAIT_COMPLETE: unique symbol;
|
|
4
|
+
/**
|
|
5
|
+
* Wait until a specific future time using Workflow primitives
|
|
6
|
+
*/
|
|
7
|
+
export declare function waitUntilSpecificTime(targetTime: Date): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Wait until the a trigger resolves OR a specific future time using Workflow primitives (whichever comes first).
|
|
10
|
+
* @returns The result of the trigger or WAIT_COMPLETE if the target time was reached first
|
|
11
|
+
*/
|
|
12
|
+
export declare function waitUntilTriggerOrSpecificTime<T>(targetTime: Date, trigger: Trigger<T>): Promise<T | typeof WAIT_COMPLETE>;
|
|
13
|
+
/**
|
|
14
|
+
* Our logging convention is metadata first, message second. This
|
|
15
|
+
* just makes the Temporal workflow logger consistent
|
|
16
|
+
*/
|
|
17
|
+
export declare const workflowLog: {
|
|
18
|
+
trace(attrOrMessage: Record<string, unknown> | string, message?: string): void;
|
|
19
|
+
debug(attrOrMessage: Record<string, unknown> | string, message?: string): void;
|
|
20
|
+
info(attrOrMessage: Record<string, unknown> | string, message?: string): void;
|
|
21
|
+
warn(attrOrMessage: Record<string, unknown> | string, message?: string): void;
|
|
22
|
+
error(attrOrMessage: Record<string, unknown> | string, message?: string): void;
|
|
23
|
+
};
|
|
24
|
+
export declare function isCancelError(e: unknown): e is ActivityFailure;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ActivityFailure, log, sleep } from '@temporalio/workflow';
|
|
2
|
+
export const WAIT_COMPLETE = Symbol.for('@sesamecare/temporal-worker::WAIT_COMPLETE');
|
|
3
|
+
/**
|
|
4
|
+
* Wait until a specific future time using Workflow primitives
|
|
5
|
+
*/
|
|
6
|
+
export async function waitUntilSpecificTime(targetTime) {
|
|
7
|
+
const currentTime = new Date();
|
|
8
|
+
const delay = targetTime.getTime() - currentTime.getTime();
|
|
9
|
+
if (delay > 0) {
|
|
10
|
+
// Wait for the calculated delay duration
|
|
11
|
+
await sleep(delay);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Wait until the a trigger resolves OR a specific future time using Workflow primitives (whichever comes first).
|
|
16
|
+
* @returns The result of the trigger or WAIT_COMPLETE if the target time was reached first
|
|
17
|
+
*/
|
|
18
|
+
export async function waitUntilTriggerOrSpecificTime(targetTime, trigger) {
|
|
19
|
+
const currentTime = new Date();
|
|
20
|
+
const delay = targetTime.getTime() - currentTime.getTime();
|
|
21
|
+
if (delay > 0) {
|
|
22
|
+
// Wait for the calculated delay duration or until a signal is received
|
|
23
|
+
return Promise.race([
|
|
24
|
+
sleep(delay).then(() => WAIT_COMPLETE),
|
|
25
|
+
trigger,
|
|
26
|
+
]);
|
|
27
|
+
}
|
|
28
|
+
return WAIT_COMPLETE;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Our logging convention is metadata first, message second. This
|
|
32
|
+
* just makes the Temporal workflow logger consistent
|
|
33
|
+
*/
|
|
34
|
+
export const workflowLog = {
|
|
35
|
+
trace(attrOrMessage, message) {
|
|
36
|
+
if (typeof attrOrMessage === 'string') {
|
|
37
|
+
log.trace(attrOrMessage);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
log.trace(message, attrOrMessage);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
debug(attrOrMessage, message) {
|
|
44
|
+
if (typeof attrOrMessage === 'string') {
|
|
45
|
+
log.debug(attrOrMessage);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
log.debug(message, attrOrMessage);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
info(attrOrMessage, message) {
|
|
52
|
+
if (typeof attrOrMessage === 'string') {
|
|
53
|
+
log.info(attrOrMessage);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
log.info(message, attrOrMessage);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
warn(attrOrMessage, message) {
|
|
60
|
+
if (typeof attrOrMessage === 'string') {
|
|
61
|
+
log.warn(attrOrMessage);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
log.warn(message, attrOrMessage);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
error(attrOrMessage, message) {
|
|
68
|
+
if (typeof attrOrMessage === 'string') {
|
|
69
|
+
log.error(attrOrMessage);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
log.error(message, attrOrMessage);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
export function isCancelError(e) {
|
|
77
|
+
return e instanceof ActivityFailure && e.cause?.type === 'CancelException';
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/workflow/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAEnE,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;AAEtF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAAgB;IAC1D,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;IAE3D,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,yCAAyC;QACzC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,UAAgB,EAChB,OAAmB;IAEnB,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;IAE3D,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,uEAAuE;QACvE,OAAO,OAAO,CAAC,IAAI,CAAC;YAClB,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAkC;YACvE,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK,CAAC,aAA+C,EAAE,OAAgB;QACrE,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,KAAK,CAAC,OAAiB,EAAE,aAAa,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,KAAK,CAAC,aAA+C,EAAE,OAAgB;QACrE,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,KAAK,CAAC,OAAiB,EAAE,aAAa,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,IAAI,CAAC,aAA+C,EAAE,OAAgB;QACpE,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,OAAiB,EAAE,aAAa,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,IAAI,CAAC,aAA+C,EAAE,OAAgB;QACpE,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,OAAiB,EAAE,aAAa,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,KAAK,CAAC,aAA+C,EAAE,OAAgB;QACrE,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,KAAK,CAAC,OAAiB,EAAE,aAAa,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAO,CAAC,YAAY,eAAe,IAAK,CAAC,CAAC,KAA2B,EAAE,IAAI,KAAK,iBAAiB,CAAC;AACpG,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openapi-typescript-infra/temporal-worker",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Typescript node module to centralize some boilerplate around creating Temporal.io workers",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./build/index.js",
|
|
8
|
+
"types": "./build/index.d.ts"
|
|
9
|
+
},
|
|
10
|
+
"./workflow": {
|
|
11
|
+
"types": "./build/workflow/index.d.ts",
|
|
12
|
+
"import": "./build/workflow/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"types": "./build/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"build",
|
|
20
|
+
"config",
|
|
21
|
+
"Makefile",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "vitest",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"build": "tsc -p tsconfig.build.json",
|
|
28
|
+
"watch": "tsc -p tsconfig.json -w --preserveWatchOutput",
|
|
29
|
+
"clean": "npx rimraf ./build",
|
|
30
|
+
"prepublishOnly": "yarn build",
|
|
31
|
+
"postinstall": "cpconfig"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/openapi-typescript-infra/temporal-worker.git"
|
|
36
|
+
},
|
|
37
|
+
"config": {
|
|
38
|
+
"cpconfig": "@openapi-typescript-infra/cpconfig",
|
|
39
|
+
"vitest": {
|
|
40
|
+
"timeout": "60000"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">22.0.0"
|
|
45
|
+
},
|
|
46
|
+
"author": "Max Metral <developers@pyralis.com>",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"keywords": [
|
|
49
|
+
"typescript",
|
|
50
|
+
"workflows",
|
|
51
|
+
"temporal"
|
|
52
|
+
],
|
|
53
|
+
"release": {
|
|
54
|
+
"branches": [
|
|
55
|
+
"main"
|
|
56
|
+
],
|
|
57
|
+
"plugins": [
|
|
58
|
+
"@semantic-release/commit-analyzer",
|
|
59
|
+
"@semantic-release/release-notes-generator",
|
|
60
|
+
[
|
|
61
|
+
"@semantic-release/exec",
|
|
62
|
+
{
|
|
63
|
+
"publishCmd": "yarn dlx pinst --disable"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"@semantic-release/npm",
|
|
67
|
+
"@semantic-release/github"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@openapi-typescript-infra/cpconfig": "^1.1.0",
|
|
72
|
+
"@openapi-typescript-infra/service": "^6.11.0",
|
|
73
|
+
"@semantic-release/exec": "^7.1.0",
|
|
74
|
+
"@semantic-release/github": "^12.0.6",
|
|
75
|
+
"@temporalio/testing": "^1.15.0",
|
|
76
|
+
"@types/node": "^25.5.0",
|
|
77
|
+
"cpconfig": "^1.4.4",
|
|
78
|
+
"eslint": "^9.39.4",
|
|
79
|
+
"prettier": "^3.8.1",
|
|
80
|
+
"typescript": "^5.9.3",
|
|
81
|
+
"vitest": "^4.1.0"
|
|
82
|
+
},
|
|
83
|
+
"peerDependencies": {
|
|
84
|
+
"@openapi-typescript-infra/service": ">6"
|
|
85
|
+
},
|
|
86
|
+
"dependencies": {
|
|
87
|
+
"@temporalio/client": "^1.15.0",
|
|
88
|
+
"@temporalio/worker": "^1.15.0"
|
|
89
|
+
},
|
|
90
|
+
"publishConfig": {
|
|
91
|
+
"access": "public"
|
|
92
|
+
},
|
|
93
|
+
"packageManager": "yarn@3.8.7"
|
|
94
|
+
}
|