@hatchet-dev/typescript-sdk 1.19.0 → 1.19.2-alpha.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.
@@ -14,6 +14,7 @@ const events_1 = require("../../protoc/events/events");
14
14
  const hatchet_error_1 = require("../../util/errors/hatchet-error");
15
15
  const retrier_1 = require("../../util/retrier");
16
16
  const apply_namespace_1 = require("../../util/apply-namespace");
17
+ const parent_run_context_vars_1 = require("../../v1/parent-run-context-vars");
17
18
  var LogLevel;
18
19
  (function (LogLevel) {
19
20
  LogLevel["INFO"] = "INFO";
@@ -21,6 +22,13 @@ var LogLevel;
21
22
  LogLevel["ERROR"] = "ERROR";
22
23
  LogLevel["DEBUG"] = "DEBUG";
23
24
  })(LogLevel || (exports.LogLevel = LogLevel = {}));
25
+ function injectSourceInfo(metadata) {
26
+ const ctx = parent_run_context_vars_1.parentRunContextManager.getContext();
27
+ if (!(ctx === null || ctx === void 0 ? void 0 : ctx.parentId) || !(ctx === null || ctx === void 0 ? void 0 : ctx.parentTaskRunExternalId)) {
28
+ return metadata;
29
+ }
30
+ return Object.assign(Object.assign({}, metadata), { hatchet__source_workflow_run_id: ctx.parentId, hatchet__source_step_run_id: ctx.parentTaskRunExternalId });
31
+ }
24
32
  class EventClient {
25
33
  constructor(config, channel, factory, api) {
26
34
  this.config = config;
@@ -35,14 +43,14 @@ class EventClient {
35
43
  * Keep the signature in sync with the instrumentor wrapper.
36
44
  */
37
45
  push(type, input, options = {}) {
46
+ var _a;
38
47
  const namespacedType = (0, apply_namespace_1.applyNamespace)(type, this.config.namespace);
48
+ const enhancedMetadata = injectSourceInfo((_a = options.additionalMetadata) !== null && _a !== void 0 ? _a : {});
39
49
  const req = {
40
50
  key: namespacedType,
41
51
  payload: JSON.stringify(input),
42
52
  eventTimestamp: new Date(),
43
- additionalMetadata: options.additionalMetadata
44
- ? JSON.stringify(options.additionalMetadata)
45
- : undefined,
53
+ additionalMetadata: Object.keys(enhancedMetadata).length > 0 ? JSON.stringify(enhancedMetadata) : undefined,
46
54
  priority: options.priority,
47
55
  scope: options.scope,
48
56
  };
@@ -62,19 +70,14 @@ class EventClient {
62
70
  bulkPush(type, inputs, options = {}) {
63
71
  const namespacedType = (0, apply_namespace_1.applyNamespace)(type, this.config.namespace);
64
72
  const events = inputs.map((input) => {
73
+ var _a, _b;
74
+ const baseMeta = (_b = (_a = input.additionalMetadata) !== null && _a !== void 0 ? _a : options.additionalMetadata) !== null && _b !== void 0 ? _b : {};
75
+ const enhanced = injectSourceInfo(baseMeta);
65
76
  return {
66
77
  key: namespacedType,
67
78
  payload: JSON.stringify(input.payload),
68
79
  eventTimestamp: new Date(),
69
- additionalMetadata: (() => {
70
- if (input.additionalMetadata) {
71
- return JSON.stringify(input.additionalMetadata);
72
- }
73
- if (options.additionalMetadata) {
74
- return JSON.stringify(options.additionalMetadata);
75
- }
76
- return undefined;
77
- })(),
80
+ additionalMetadata: Object.keys(enhanced).length > 0 ? JSON.stringify(enhanced) : undefined,
78
81
  priority: input.priority,
79
82
  scope: input.scope,
80
83
  };
@@ -96,9 +96,19 @@ class HatchetExporterWrapper {
96
96
  */
97
97
  class HatchetAttributeSpanProcessor extends BatchSpanProcessor {
98
98
  onStart(span) {
99
+ var _a;
99
100
  const attrs = hatchet_span_context_1.hatchetSpanAttributes.getStore();
100
101
  if (attrs) {
101
- span.setAttributes(attrs);
102
+ const existing = (_a = span.attributes) !== null && _a !== void 0 ? _a : {};
103
+ const filtered = {};
104
+ for (const [key, value] of Object.entries(attrs)) {
105
+ if (!(key in existing)) {
106
+ filtered[key] = value;
107
+ }
108
+ }
109
+ if (Object.keys(filtered).length > 0) {
110
+ span.setAttributes(filtered);
111
+ }
102
112
  }
103
113
  super.onStart(span, undefined);
104
114
  }
@@ -108,10 +118,14 @@ class HatchetAttributeSpanProcessor extends BatchSpanProcessor {
108
118
  }
109
119
  function createHatchetExporter(config) {
110
120
  const insecure = config.tls_config.tls_strategy === 'none';
121
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
122
+ const grpc = require('@grpc/grpc-js');
123
+ const metadata = new grpc.Metadata();
124
+ metadata.set('authorization', `Bearer ${config.token}`);
111
125
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
126
  const opts = {
113
127
  url: `${insecure ? 'http' : 'https'}://${config.host_port}`,
114
- metadata: { authorization: `Bearer ${config.token}` },
128
+ metadata,
115
129
  };
116
130
  if (!insecure && config.tls_config.ca_file) {
117
131
  try {
@@ -46,6 +46,17 @@ function extractContext(carrier) {
46
46
  function injectContext(carrier) {
47
47
  propagation.inject(context.active(), carrier);
48
48
  }
49
+ function injectSourceInfo(carrier) {
50
+ const store = hatchet_span_context_1.hatchetSpanAttributes.getStore();
51
+ if (!store)
52
+ return;
53
+ const wfRunId = store['hatchet.workflow_run_id'];
54
+ const stepRunId = store['hatchet.step_run_id'];
55
+ if (typeof wfRunId === 'string' && typeof stepRunId === 'string') {
56
+ carrier['hatchet__source_workflow_run_id'] = wfRunId;
57
+ carrier['hatchet__source_step_run_id'] = stepRunId;
58
+ }
59
+ }
49
60
  function getActionOtelAttributes(action, excludedAttributes = [], workerId) {
50
61
  const attributes = {
51
62
  [opentelemetry_1.OTelAttribute.TENANT_ID]: action.tenantId,
@@ -215,6 +226,7 @@ class HatchetInstrumentor extends InstrumentationBase {
215
226
  var _a;
216
227
  const enhancedMetadata = Object.assign({}, ((_a = options.additionalMetadata) !== null && _a !== void 0 ? _a : {}));
217
228
  injectContext(enhancedMetadata);
229
+ injectSourceInfo(enhancedMetadata);
218
230
  const enhancedOptions = Object.assign(Object.assign({}, options), { additionalMetadata: enhancedMetadata });
219
231
  const result = original.call(this, type, input, enhancedOptions);
220
232
  return result.finally(() => {
@@ -247,6 +259,7 @@ class HatchetInstrumentor extends InstrumentationBase {
247
259
  var _a;
248
260
  const enhancedMetadata = Object.assign({}, ((_a = input.additionalMetadata) !== null && _a !== void 0 ? _a : {}));
249
261
  injectContext(enhancedMetadata);
262
+ injectSourceInfo(enhancedMetadata);
250
263
  return Object.assign(Object.assign({}, input), { additionalMetadata: enhancedMetadata });
251
264
  });
252
265
  const result = original.call(this, type, enhancedInputs, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "1.19.0",
3
+ "version": "1.19.2-alpha.0",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -48,7 +48,7 @@
48
48
  "dependencies": {
49
49
  "@bufbuild/protobuf": "^2.11.0",
50
50
  "@types/qs": "^6.15.0",
51
- "abort-controller-x": "^0.4.3",
51
+ "abort-controller-x": "^0.5.0",
52
52
  "axios": "^1.13.5",
53
53
  "long": "^5.3.1",
54
54
  "nice-grpc": "^2.1.14",
@@ -61,10 +61,11 @@
61
61
  "zod-to-json-schema": "^3.24.1"
62
62
  },
63
63
  "optionalDependencies": {
64
+ "@grpc/grpc-js": "^1.14.3",
64
65
  "@opentelemetry/api": "^1.9.0",
65
66
  "@opentelemetry/core": "^2.0.0",
66
- "@opentelemetry/exporter-trace-otlp-grpc": "^0.208.0",
67
- "@opentelemetry/instrumentation": "^0.208.0",
67
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.214.0",
68
+ "@opentelemetry/instrumentation": "^0.214.0",
68
69
  "@opentelemetry/sdk-trace-base": "^2.0.0",
69
70
  "prom-client": "^15.1.3"
70
71
  },
@@ -95,10 +95,10 @@ class InternalWorker {
95
95
  this.labels = options.labels || {};
96
96
  this.enableHealthServer = (_b = (_a = client.config.healthcheck) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : false;
97
97
  this.healthPort = (_d = (_c = client.config.healthcheck) === null || _c === void 0 ? void 0 : _c.port) !== null && _d !== void 0 ? _d : 8001;
98
- process.on('SIGTERM', () => this.exitGracefully(true));
99
- process.on('SIGINT', () => this.exitGracefully(true));
100
98
  this.killing = false;
101
99
  this.handle_kill = options.handleKill === undefined ? true : options.handleKill;
100
+ process.on('SIGTERM', () => this.exitGracefully(this.handle_kill));
101
+ process.on('SIGINT', () => this.exitGracefully(this.handle_kill));
102
102
  this.logger = client.config.logger(`Worker/${this.name}`, this.client.config.log_level);
103
103
  if (this.enableHealthServer && this.healthPort) {
104
104
  this.initializeHealthServer();
package/v1/declaration.js CHANGED
@@ -63,9 +63,12 @@ class BaseWorkflowDeclaration {
63
63
  if (!this.client) {
64
64
  throw UNBOUND_ERR;
65
65
  }
66
- // set the parent run context
67
66
  const parentRunContext = parent_run_context_vars_1.parentRunContextManager.getContext();
68
- parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(Array.isArray(input) ? input.length : 1);
67
+ // Snapshot the child index BEFORE incrementing — getContext() returns a mutable
68
+ // reference, so any later increment would corrupt this value.
69
+ const childIndex = parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.childIndex;
70
+ const inputCount = Array.isArray(input) ? input.length : 1;
71
+ parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(inputCount);
69
72
  if (!parentRunContext && ((options === null || options === void 0 ? void 0 : options.childKey) || (options === null || options === void 0 ? void 0 : options.sticky))) {
70
73
  this.client.admin.logger.warn('ignoring childKey or sticky because run is not being spawned from a parent task');
71
74
  }
@@ -79,18 +82,17 @@ class BaseWorkflowDeclaration {
79
82
  : undefined,
80
83
  warn: (message) => this.client.admin.logger.warn(message),
81
84
  });
82
- parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(Array.isArray(input) ? input.length : 1);
83
- const runOpts = Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { parentId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentId, parentTaskRunExternalId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentTaskRunExternalId, childIndex: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.childIndex, sticky: (options === null || options === void 0 ? void 0 : options.sticky) ? parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.desiredWorkerId : undefined, childKey: options === null || options === void 0 ? void 0 : options.childKey });
85
+ const runOpts = Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { parentId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentId, parentTaskRunExternalId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentTaskRunExternalId, childIndex, sticky: (options === null || options === void 0 ? void 0 : options.sticky) ? parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.desiredWorkerId : undefined, childKey: options === null || options === void 0 ? void 0 : options.childKey });
84
86
  if (Array.isArray(input)) {
85
87
  let resp = [];
86
88
  for (let i = 0; i < input.length; i += 500) {
87
89
  const batch = input.slice(i, i + 500);
88
- const batchResp = yield this.client.admin.runWorkflows(batch.map((inp) => {
90
+ const batchResp = yield this.client.admin.runWorkflows(batch.map((inp, batchIdx) => {
89
91
  var _a;
90
92
  return ({
91
93
  workflowName: this.definition.name,
92
94
  input: inp,
93
- options: Object.assign(Object.assign({}, runOpts), { childIndex: ((_a = runOpts.childIndex) !== null && _a !== void 0 ? _a : 0) + i }),
95
+ options: Object.assign(Object.assign({}, runOpts), { childIndex: ((_a = runOpts.childIndex) !== null && _a !== void 0 ? _a : 0) + i + batchIdx }),
94
96
  });
95
97
  }));
96
98
  resp = resp.concat(batchResp);
@@ -16,18 +16,16 @@ class ParentRunContextManager {
16
16
  var _a;
17
17
  const parentRunContext = this.getContext();
18
18
  if (parentRunContext) {
19
- parentRunContext.parentId = opts.parentId;
20
- parentRunContext.parentTaskRunExternalId = opts.parentTaskRunExternalId;
21
- parentRunContext.childIndex = ((_a = parentRunContext.childIndex) !== null && _a !== void 0 ? _a : 0) + 1;
22
- this.setContext(parentRunContext);
19
+ this.setContext(Object.assign(Object.assign({}, parentRunContext), { parentId: opts.parentId, parentTaskRunExternalId: opts.parentTaskRunExternalId, childIndex: ((_a = parentRunContext.childIndex) !== null && _a !== void 0 ? _a : 0) + 1 }));
23
20
  }
24
21
  }
25
22
  incrementChildIndex(n) {
26
23
  var _a;
27
24
  const parentRunContext = this.getContext();
28
25
  if (parentRunContext) {
29
- parentRunContext.childIndex = ((_a = parentRunContext.childIndex) !== null && _a !== void 0 ? _a : 0) + n;
30
- this.setContext(parentRunContext);
26
+ // Build a fresh object to avoid mutating the live store reference, which
27
+ // would corrupt any values snapshotted before this call.
28
+ this.setContext(Object.assign(Object.assign({}, parentRunContext), { childIndex: ((_a = parentRunContext.childIndex) !== null && _a !== void 0 ? _a : 0) + n }));
31
29
  }
32
30
  }
33
31
  getContext() {
package/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const HATCHET_VERSION = "1.19.0";
1
+ export declare const HATCHET_VERSION = "1.19.2-alpha.0";
package/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HATCHET_VERSION = void 0;
4
- exports.HATCHET_VERSION = '1.19.0';
4
+ exports.HATCHET_VERSION = '1.19.2-alpha.0';