@diia-inhouse/workflow 2.7.0 → 2.8.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.
@@ -34,6 +34,15 @@ interface WorkerBootstrapOptions extends Omit<WorkerOptions, "taskQueue" | "acti
34
34
  nodeTracerProvider?: NodeTracerProviderLike;
35
35
  shutdownSignals?: NodeJS.Signals[];
36
36
  /**
37
+ * The workflows this worker runs. Recorded on the `diia_temporal_worker_info` metric.
38
+ *
39
+ * Optional — left empty, the workflows are picked up automatically from the workflows folder, so
40
+ * most services don't need to set this. Pass it only to override that.
41
+ */
42
+ workflowTypes?: string[];
43
+ /** Service name for the metric. Defaults to the name derived from the task queue. */
44
+ service?: string;
45
+ /**
37
46
  * When provided together with `deps`, `bootstrapWorker` manages the full application
38
47
  * lifecycle: setConfig → apply worker overrides → setDeps → initialize → start → run worker.
39
48
  */
@@ -0,0 +1,29 @@
1
+ //#region src/services/worker/info.d.ts
2
+ declare const WORKER_INFO_METRIC = "diia_temporal_worker_info";
3
+ interface WorkerInfoLabels {
4
+ namespace: string;
5
+ temporal_namespace: string;
6
+ task_queue: string;
7
+ service: string;
8
+ workflow_type: string;
9
+ }
10
+ declare function taskQueueToService(taskQueue: string): string;
11
+ interface RegisterWorkerInfoParams {
12
+ namespace: string;
13
+ taskQueue: string;
14
+ /** Service name. Defaults to the name derived from the task queue. */
15
+ service?: string;
16
+ /** The workflows this worker runs (one entry each). Leave empty to record just the worker. */
17
+ workflowTypes?: string[];
18
+ }
19
+ declare function registerWorkerInfo({
20
+ namespace,
21
+ taskQueue,
22
+ service,
23
+ workflowTypes
24
+ }: RegisterWorkerInfoParams): void;
25
+ declare function deriveWorkflowTypes(workflowsPath: string, logger?: {
26
+ warn(message: string, meta?: unknown): void;
27
+ }): Promise<string[] | undefined>;
28
+ //#endregion
29
+ export { RegisterWorkerInfoParams, WORKER_INFO_METRIC, WorkerInfoLabels, deriveWorkflowTypes, registerWorkerInfo, taskQueueToService };
@@ -0,0 +1,44 @@
1
+ import { pathToFileURL } from "node:url";
2
+ import { Observer } from "@diia-inhouse/diia-metrics";
3
+ //#region src/services/worker/info.ts
4
+ const WORKER_INFO_METRIC = "diia_temporal_worker_info";
5
+ const WORKER_INFO_LABELS = [
6
+ "namespace",
7
+ "temporal_namespace",
8
+ "task_queue",
9
+ "service",
10
+ "workflow_type"
11
+ ];
12
+ function taskQueueToService(taskQueue) {
13
+ const trimmed = taskQueue.trim();
14
+ if (!trimmed) return "unknown";
15
+ return trimmed.replace(/[-_](worker|workers|queue)$/i, "");
16
+ }
17
+ function registerWorkerInfo({ namespace, taskQueue, service, workflowTypes }) {
18
+ if (!taskQueue) return;
19
+ const resolvedService = service?.trim() || taskQueueToService(taskQueue);
20
+ const info = new Observer(WORKER_INFO_METRIC, WORKER_INFO_LABELS, "Which namespace, task queue and workflows a service runs (always 1).");
21
+ const base = {
22
+ namespace,
23
+ temporal_namespace: namespace,
24
+ task_queue: taskQueue,
25
+ service: resolvedService
26
+ };
27
+ const types = workflowTypes?.length ? workflowTypes : [""];
28
+ for (const workflow_type of types) info.observe({
29
+ ...base,
30
+ workflow_type
31
+ }, 1);
32
+ }
33
+ async function deriveWorkflowTypes(workflowsPath, logger) {
34
+ try {
35
+ const mod = await import(pathToFileURL(workflowsPath).href);
36
+ const types = Object.entries(mod).filter(([, value]) => typeof value === "function" && value.constructor?.name === "AsyncFunction").map(([name]) => name);
37
+ return types.length ? types : void 0;
38
+ } catch (err) {
39
+ logger?.warn("worker-info: could not read workflows; recording the worker without per-workflow detail", { err });
40
+ return;
41
+ }
42
+ }
43
+ //#endregion
44
+ export { WORKER_INFO_METRIC, deriveWorkflowTypes, registerWorkerInfo, taskQueueToService };
@@ -66,7 +66,9 @@ declare function instantiateActivities(app: App, workerActivities: Record<string
66
66
  declare function initTemporalWorker(app: App, options: {
67
67
  nodeTracerProvider: NodeTracerProviderLike;
68
68
  workflowsPath: string;
69
- activities: Record<string, ActivityClass>;
69
+ activities: Record<string, ActivityClass>; /** The workflows this worker runs. Auto-detected from the workflows folder when left empty. */
70
+ workflowTypes?: string[]; /** Service name. Defaults to the name derived from the task queue. */
71
+ service?: string;
70
72
  } & Omit<WorkerOptions, "taskQueue" | "activities" | "workflowsPath">): Promise<void>;
71
73
  /**
72
74
  * Bootstraps and runs Temporal worker with graceful shutdown.
@@ -118,7 +120,9 @@ declare function initWorker({
118
120
  custom: metricsConfig
119
121
  }
120
122
  }: AppConfig, options: Omit<WorkerOptions, "taskQueue"> & {
121
- taskQueue?: string;
123
+ taskQueue?: string; /** The workflows this worker runs. Auto-detected from the workflows folder when left empty. */
124
+ workflowTypes?: string[]; /** Service name. Defaults to the name derived from the task queue. */
125
+ service?: string;
122
126
  }, envService: EnvService, logger?: Logger, nodeTracerProvider?: NodeTracerProviderLike, asyncLocalStorage?: AsyncLocalStorage<AlsData>): Promise<Worker>;
123
127
  //#endregion
124
128
  export { applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, initTemporalWorker, initWorker, instantiateActivities, toWorkflowsPath };
@@ -3,6 +3,7 @@ import "../encryption/index.js";
3
3
  import { traceExporter } from "../instrumentation.js";
4
4
  import { AsyncLocalStorageBridgeInterceptor } from "../interceptors/asyncLocalStorageBridge.js";
5
5
  import { buildWorkerIdentity } from "./worker/identity.js";
6
+ import { deriveWorkflowTypes, registerWorkerInfo } from "./worker/info.js";
6
7
  import { WorkerHealthService } from "./workerHealth.js";
7
8
  import { EnvService } from "@diia-inhouse/env";
8
9
  import { NativeConnection, Runtime, Worker } from "@temporalio/worker";
@@ -266,17 +267,29 @@ async function initWorker({ temporal: temporalConfig, metrics: { custom: metrics
266
267
  const tracingEnabled = EnvService.getVar("TRACING_ENABLED", "boolean", false);
267
268
  const workflowsPath = options.workflowsPath ? toWorkflowsPath(options.workflowsPath) : void 0;
268
269
  const mergedInterceptors = mergeInterceptors(buildWorkerInterceptors(tracingEnabled, asyncLocalStorage, logger, workflowsPath), options.interceptors);
270
+ const { workflowTypes, service: serviceOverride, ...workerCreateOptions } = options;
269
271
  try {
270
- return await Worker.create({
272
+ const worker = await Worker.create({
271
273
  namespace,
272
274
  taskQueue,
273
275
  connection: await NativeConnection.connect({ address }),
274
276
  dataConverter: encryptionEnabled ? await getDataConverter(encryptionKeyId, envService, encryptionKeyRefreshInterval) : void 0,
275
- ...options,
277
+ ...workerCreateOptions,
276
278
  workflowsPath,
277
279
  sinks: tracingEnabled ? { exporter: makeWorkflowExporter(traceExporter, resource) } : void 0,
278
280
  interceptors: mergedInterceptors
279
281
  });
282
+ if (taskQueue) try {
283
+ registerWorkerInfo({
284
+ namespace,
285
+ taskQueue,
286
+ service: serviceOverride,
287
+ workflowTypes: workflowTypes ?? (workflowsPath ? await deriveWorkflowTypes(workflowsPath, logger) : void 0)
288
+ });
289
+ } catch (err) {
290
+ logger?.warn("Failed to record diia_temporal_worker_info metric", { err });
291
+ }
292
+ return worker;
280
293
  } catch (err) {
281
294
  logger?.error("Failed to create Temporal worker", { err });
282
295
  throw new Error("Failed to create Temporal worker", { cause: err });
package/dist/worker.d.ts CHANGED
@@ -3,5 +3,6 @@ import { ActivityClass, App, WorkerBootstrapOptions } from "./interfaces/service
3
3
  import { WorkerHealthDetails, WorkerHealthService } from "./services/workerHealth.js";
4
4
  import { buildWorkerIdentity } from "./services/worker/identity.js";
5
5
  import { applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, initTemporalWorker, initWorker, instantiateActivities, toWorkflowsPath } from "./services/worker.js";
6
+ import { RegisterWorkerInfoParams, WORKER_INFO_METRIC, WorkerInfoLabels, deriveWorkflowTypes, registerWorkerInfo, taskQueueToService } from "./services/worker/info.js";
6
7
  import { NativeConnection, Runtime, State, Worker, WorkerInterceptors, WorkerOptions, WorkerStatus, bundleWorkflowCode } from "@temporalio/worker";
7
- export { ActivityClass, App, NativeConnection, Runtime, type State, Worker, WorkerBootstrapOptions, WorkerHealthDetails, WorkerHealthService, type WorkerInterceptors, type WorkerOptions, type WorkerStatus, applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, buildWorkerIdentity, bundleWorkflowCode, initTemporalWorker, initWorker, instantiateActivities, toWorkflowsPath, workflowInterceptors };
8
+ export { ActivityClass, App, NativeConnection, RegisterWorkerInfoParams, Runtime, type State, WORKER_INFO_METRIC, Worker, WorkerBootstrapOptions, WorkerHealthDetails, WorkerHealthService, WorkerInfoLabels, type WorkerInterceptors, type WorkerOptions, type WorkerStatus, applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, buildWorkerIdentity, bundleWorkflowCode, deriveWorkflowTypes, initTemporalWorker, initWorker, instantiateActivities, registerWorkerInfo, taskQueueToService, toWorkflowsPath, workflowInterceptors };
package/dist/worker.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { workflowInterceptors } from "./interceptors.js";
2
2
  import { buildWorkerIdentity } from "./services/worker/identity.js";
3
+ import { WORKER_INFO_METRIC, deriveWorkflowTypes, registerWorkerInfo, taskQueueToService } from "./services/worker/info.js";
3
4
  import { WorkerHealthService } from "./services/workerHealth.js";
4
5
  import { applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, initTemporalWorker, initWorker, instantiateActivities, toWorkflowsPath } from "./services/worker.js";
5
6
  import { NativeConnection, Runtime, Worker, bundleWorkflowCode } from "@temporalio/worker";
6
- export { NativeConnection, Runtime, Worker, WorkerHealthService, applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, buildWorkerIdentity, bundleWorkflowCode, initTemporalWorker, initWorker, instantiateActivities, toWorkflowsPath, workflowInterceptors };
7
+ export { NativeConnection, Runtime, WORKER_INFO_METRIC, Worker, WorkerHealthService, applyServiceProcessConfig, applyWorkerProcessConfig, bootstrapWorker, buildWorkerIdentity, bundleWorkflowCode, deriveWorkflowTypes, initTemporalWorker, initWorker, instantiateActivities, registerWorkerInfo, taskQueueToService, toWorkflowsPath, workflowInterceptors };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diia-inhouse/workflow",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Workflow",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -100,15 +100,15 @@
100
100
  },
101
101
  "devDependencies": {
102
102
  "@diia-inhouse/configs": "7.0.1",
103
- "@diia-inhouse/diia-logger": "4.3.13",
104
- "@diia-inhouse/diia-metrics": "7.1.23",
105
- "@diia-inhouse/diia-queue": "14.0.21",
106
- "@diia-inhouse/env": "3.3.12",
107
- "@diia-inhouse/healthcheck": "2.1.25",
103
+ "@diia-inhouse/diia-logger": "4.3.18",
104
+ "@diia-inhouse/diia-metrics": "7.1.26",
105
+ "@diia-inhouse/diia-queue": "14.0.23",
106
+ "@diia-inhouse/env": "3.3.17",
107
+ "@diia-inhouse/healthcheck": "2.1.30",
108
108
  "@diia-inhouse/oxc-config": "1.11.0",
109
- "@diia-inhouse/test": "8.2.9",
110
- "@diia-inhouse/types": "13.2.2",
111
- "@diia-inhouse/utils": "6.0.21",
109
+ "@diia-inhouse/test": "8.2.10",
110
+ "@diia-inhouse/types": "13.3.0",
111
+ "@diia-inhouse/utils": "6.0.25",
112
112
  "@types/lodash": "4.17.24",
113
113
  "@types/node": "25.6.2",
114
114
  "@types/yargs": "17.0.35",