@hatchet-dev/typescript-sdk 1.26.1 → 1.26.2

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.
@@ -111,7 +111,7 @@ class AdminClient {
111
111
  limit,
112
112
  duration,
113
113
  });
114
- }), this.logger);
114
+ }), this.logger, this.config.retrier);
115
115
  }
116
116
  catch (e) {
117
117
  throw (0, hatchet_error_1.toHatchetError)(e);
@@ -54,14 +54,14 @@ class EventClient {
54
54
  priority: options.priority,
55
55
  scope: options.scope,
56
56
  };
57
- try {
58
- const e = this.retrier(() => __awaiter(this, void 0, void 0, function* () { return this.client.push(req); }), this.logger);
57
+ return this.retrier(() => __awaiter(this, void 0, void 0, function* () { return this.client.push(req); }), this.logger, this.config.retrier)
58
+ .then((result) => {
59
59
  this.logger.info(`Event pushed: ${namespacedType}`);
60
- return e;
61
- }
62
- catch (e) {
60
+ return result;
61
+ })
62
+ .catch((e) => {
63
63
  throw (0, hatchet_error_1.toHatchetError)(e);
64
- }
64
+ });
65
65
  }
66
66
  /**
67
67
  * @important This method is instrumented by HatchetInstrumentor._patchBulkPushEvent.
@@ -85,14 +85,14 @@ class EventClient {
85
85
  const req = {
86
86
  events,
87
87
  };
88
- try {
89
- const res = this.retrier(() => __awaiter(this, void 0, void 0, function* () { return this.client.bulkPush(req); }), this.logger);
88
+ return this.retrier(() => __awaiter(this, void 0, void 0, function* () { return this.client.bulkPush(req); }), this.logger, this.config.retrier)
89
+ .then((result) => {
90
90
  this.logger.info(`Bulk events pushed for type: ${namespacedType}`);
91
- return res;
92
- }
93
- catch (e) {
91
+ return result;
92
+ })
93
+ .catch((e) => {
94
94
  throw (0, hatchet_error_1.toHatchetError)(e);
95
- }
95
+ });
96
96
  }
97
97
  putLog(taskRunExternalId, log, level, taskRetryCount, metadata) {
98
98
  return __awaiter(this, void 0, void 0, function* () {
@@ -2,6 +2,12 @@ import { ChannelCredentials } from 'nice-grpc';
2
2
  import { z } from 'zod/v4';
3
3
  import type { Context } from '../../v1/client/worker/context';
4
4
  import { Logger, LogLevel } from '../../util/logger';
5
+ export declare const RetrierConfigSchema: z.ZodObject<{
6
+ maxAttempts: z.ZodOptional<z.ZodNumber>;
7
+ initialInterval: z.ZodOptional<z.ZodNumber>;
8
+ maxJitter: z.ZodOptional<z.ZodNumber>;
9
+ }, z.core.$strip>;
10
+ export type RetrierConfig = z.infer<typeof RetrierConfigSchema>;
5
11
  declare const ClientTLSConfigSchema: z.ZodObject<{
6
12
  tls_strategy: z.ZodOptional<z.ZodEnum<{
7
13
  tls: "tls";
@@ -60,6 +66,11 @@ export declare const ClientConfigSchema: z.ZodObject<{
60
66
  cancellation_warning_threshold: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
61
67
  grpc_max_recv_message_length: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
62
68
  grpc_max_send_message_length: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
69
+ retrier: z.ZodOptional<z.ZodObject<{
70
+ maxAttempts: z.ZodOptional<z.ZodNumber>;
71
+ initialInterval: z.ZodOptional<z.ZodNumber>;
72
+ maxJitter: z.ZodOptional<z.ZodNumber>;
73
+ }, z.core.$strip>>;
63
74
  }, z.core.$strip>;
64
75
  export type LogConstructor = (context: string, logLevel?: LogLevel) => Logger;
65
76
  /**
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ClientConfigSchema = exports.OpenTelemetryConfigSchema = void 0;
3
+ exports.ClientConfigSchema = exports.OpenTelemetryConfigSchema = exports.RetrierConfigSchema = void 0;
4
4
  const v4_1 = require("zod/v4");
5
+ exports.RetrierConfigSchema = v4_1.z.object({
6
+ maxAttempts: v4_1.z.number().int().positive().optional(),
7
+ initialInterval: v4_1.z.number().positive().optional(),
8
+ maxJitter: v4_1.z.number().nonnegative().optional(),
9
+ });
5
10
  const ClientTLSConfigSchema = v4_1.z.object({
6
11
  tls_strategy: v4_1.z.enum(['tls', 'mtls', 'none']).optional(),
7
12
  cert_file: v4_1.z.string().optional(),
@@ -65,4 +70,5 @@ exports.ClientConfigSchema = v4_1.z.object({
65
70
  .positive()
66
71
  .optional()
67
72
  .default(4 * 1024 * 1024),
73
+ retrier: exports.RetrierConfigSchema.optional(),
68
74
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "1.26.1",
3
+ "version": "1.26.2",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -6,6 +6,7 @@ interface LoadClientConfigOptions {
6
6
  export declare class ConfigLoader {
7
7
  static loadClientConfig(override?: Partial<ClientConfig>, config?: LoadClientConfigOptions): Partial<ClientConfig>;
8
8
  private static parseIntEnv;
9
+ private static parseFloatEnv;
9
10
  private static parseJsonArray;
10
11
  static get default_yaml_config_path(): string;
11
12
  static createCredentials(config: ClientConfig['tls_config']): ChannelCredentials;
@@ -44,7 +44,7 @@ const token_1 = require("./token");
44
44
  const DEFAULT_CONFIG_FILE = '.hatchet.yaml';
45
45
  class ConfigLoader {
46
46
  static loadClientConfig(override, config) {
47
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18;
47
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30;
48
48
  const yaml = this.loadYamlConfig(config === null || config === void 0 ? void 0 : config.path);
49
49
  const tlsConfig = (_a = override === null || override === void 0 ? void 0 : override.tls_config) !== null && _a !== void 0 ? _a : {
50
50
  tls_strategy: (_d = (_c = (_b = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _b === void 0 ? void 0 : _b.tls_strategy) !== null && _c !== void 0 ? _c : this.env('HATCHET_CLIENT_TLS_STRATEGY')) !== null && _d !== void 0 ? _d : 'tls',
@@ -74,7 +74,7 @@ class ConfigLoader {
74
74
  apiUrl =
75
75
  (_x = (_w = (_v = override === null || override === void 0 ? void 0 : override.api_url) !== null && _v !== void 0 ? _v : yaml === null || yaml === void 0 ? void 0 : yaml.api_url) !== null && _w !== void 0 ? _w : this.env('HATCHET_CLIENT_API_URL')) !== null && _x !== void 0 ? _x : addresses.serverUrl;
76
76
  }
77
- catch (_19) {
77
+ catch (_31) {
78
78
  grpcBroadcastAddress =
79
79
  (_z = (_y = override === null || override === void 0 ? void 0 : override.host_port) !== null && _y !== void 0 ? _y : yaml === null || yaml === void 0 ? void 0 : yaml.host_port) !== null && _z !== void 0 ? _z : this.env('HATCHET_CLIENT_HOST_PORT');
80
80
  apiUrl = (_1 = (_0 = override === null || override === void 0 ? void 0 : override.api_url) !== null && _0 !== void 0 ? _0 : yaml === null || yaml === void 0 ? void 0 : yaml.api_url) !== null && _1 !== void 0 ? _1 : this.env('HATCHET_CLIENT_API_URL');
@@ -90,21 +90,13 @@ class ConfigLoader {
90
90
  };
91
91
  const grpcMaxRecvMessageLength = (_8 = (_7 = (_6 = override === null || override === void 0 ? void 0 : override.grpc_max_recv_message_length) !== null && _6 !== void 0 ? _6 : yaml === null || yaml === void 0 ? void 0 : yaml.grpc_max_recv_message_length) !== null && _7 !== void 0 ? _7 : this.parseIntEnv('HATCHET_CLIENT_GRPC_MAX_RECV_MESSAGE_LENGTH')) !== null && _8 !== void 0 ? _8 : 4 * 1024 * 1024;
92
92
  const grpcMaxSendMessageLength = (_11 = (_10 = (_9 = override === null || override === void 0 ? void 0 : override.grpc_max_send_message_length) !== null && _9 !== void 0 ? _9 : yaml === null || yaml === void 0 ? void 0 : yaml.grpc_max_send_message_length) !== null && _10 !== void 0 ? _10 : this.parseIntEnv('HATCHET_CLIENT_GRPC_MAX_SEND_MESSAGE_LENGTH')) !== null && _11 !== void 0 ? _11 : 4 * 1024 * 1024;
93
- return {
94
- token: (_13 = (_12 = override === null || override === void 0 ? void 0 : override.token) !== null && _12 !== void 0 ? _12 : yaml === null || yaml === void 0 ? void 0 : yaml.token) !== null && _13 !== void 0 ? _13 : this.env('HATCHET_CLIENT_TOKEN'),
95
- host_port: grpcBroadcastAddress,
96
- api_url: apiUrl,
97
- tls_config: tlsConfig,
98
- healthcheck: healthCheckConfig,
99
- log_level: (_16 = (_15 = (_14 = override === null || override === void 0 ? void 0 : override.log_level) !== null && _14 !== void 0 ? _14 : yaml === null || yaml === void 0 ? void 0 : yaml.log_level) !== null && _15 !== void 0 ? _15 : this.env('HATCHET_CLIENT_LOG_LEVEL')) !== null && _16 !== void 0 ? _16 : 'INFO',
100
- tenant_id: tenantId,
101
- namespace: namespace ? `${namespace}`.toLowerCase() : '',
102
- otel: otelConfig,
103
- grpc_max_recv_message_length: grpcMaxRecvMessageLength,
104
- grpc_max_send_message_length: grpcMaxSendMessageLength,
105
- cancellation_grace_period: (_17 = override === null || override === void 0 ? void 0 : override.cancellation_grace_period) !== null && _17 !== void 0 ? _17 : yaml === null || yaml === void 0 ? void 0 : yaml.cancellation_grace_period,
106
- cancellation_warning_threshold: (_18 = override === null || override === void 0 ? void 0 : override.cancellation_warning_threshold) !== null && _18 !== void 0 ? _18 : yaml === null || yaml === void 0 ? void 0 : yaml.cancellation_warning_threshold,
93
+ const retrierConfig = {
94
+ maxAttempts: (_15 = (_13 = (_12 = override === null || override === void 0 ? void 0 : override.retrier) === null || _12 === void 0 ? void 0 : _12.maxAttempts) !== null && _13 !== void 0 ? _13 : (_14 = yaml === null || yaml === void 0 ? void 0 : yaml.retrier) === null || _14 === void 0 ? void 0 : _14.maxAttempts) !== null && _15 !== void 0 ? _15 : this.parseIntEnv('HATCHET_CLIENT_RETRIER_MAX_ATTEMPTS'),
95
+ initialInterval: (_19 = (_17 = (_16 = override === null || override === void 0 ? void 0 : override.retrier) === null || _16 === void 0 ? void 0 : _16.initialInterval) !== null && _17 !== void 0 ? _17 : (_18 = yaml === null || yaml === void 0 ? void 0 : yaml.retrier) === null || _18 === void 0 ? void 0 : _18.initialInterval) !== null && _19 !== void 0 ? _19 : this.parseFloatEnv('HATCHET_CLIENT_RETRIER_INITIAL_INTERVAL'),
96
+ maxJitter: (_23 = (_21 = (_20 = override === null || override === void 0 ? void 0 : override.retrier) === null || _20 === void 0 ? void 0 : _20.maxJitter) !== null && _21 !== void 0 ? _21 : (_22 = yaml === null || yaml === void 0 ? void 0 : yaml.retrier) === null || _22 === void 0 ? void 0 : _22.maxJitter) !== null && _23 !== void 0 ? _23 : this.parseIntEnv('HATCHET_CLIENT_RETRIER_MAX_JITTER'),
107
97
  };
98
+ const hasRetrier = Object.values(retrierConfig).some((v) => v !== undefined);
99
+ return Object.assign({ token: (_25 = (_24 = override === null || override === void 0 ? void 0 : override.token) !== null && _24 !== void 0 ? _24 : yaml === null || yaml === void 0 ? void 0 : yaml.token) !== null && _25 !== void 0 ? _25 : this.env('HATCHET_CLIENT_TOKEN'), host_port: grpcBroadcastAddress, api_url: apiUrl, tls_config: tlsConfig, healthcheck: healthCheckConfig, log_level: (_28 = (_27 = (_26 = override === null || override === void 0 ? void 0 : override.log_level) !== null && _26 !== void 0 ? _26 : yaml === null || yaml === void 0 ? void 0 : yaml.log_level) !== null && _27 !== void 0 ? _27 : this.env('HATCHET_CLIENT_LOG_LEVEL')) !== null && _28 !== void 0 ? _28 : 'INFO', tenant_id: tenantId, namespace: namespace ? `${namespace}`.toLowerCase() : '', otel: otelConfig, grpc_max_recv_message_length: grpcMaxRecvMessageLength, grpc_max_send_message_length: grpcMaxSendMessageLength, cancellation_grace_period: (_29 = override === null || override === void 0 ? void 0 : override.cancellation_grace_period) !== null && _29 !== void 0 ? _29 : yaml === null || yaml === void 0 ? void 0 : yaml.cancellation_grace_period, cancellation_warning_threshold: (_30 = override === null || override === void 0 ? void 0 : override.cancellation_warning_threshold) !== null && _30 !== void 0 ? _30 : yaml === null || yaml === void 0 ? void 0 : yaml.cancellation_warning_threshold }, (hasRetrier ? { retrier: retrierConfig } : {}));
108
100
  }
109
101
  static parseIntEnv(envName) {
110
102
  const value = this.env(envName);
@@ -115,6 +107,16 @@ class ConfigLoader {
115
107
  }
116
108
  return parseInt(value, 10);
117
109
  }
110
+ static parseFloatEnv(envName) {
111
+ const value = this.env(envName);
112
+ if (value === undefined || value === '')
113
+ return undefined;
114
+ const parsed = parseFloat(value.trim());
115
+ if (isNaN(parsed) || parsed <= 0) {
116
+ throw new Error(`Invalid value for ${envName}: "${value}". Expected a positive number.`);
117
+ }
118
+ return parsed;
119
+ }
118
120
  static parseJsonArray(value) {
119
121
  try {
120
122
  const parsed = JSON.parse(value);
package/util/retrier.d.ts CHANGED
@@ -1,2 +1,11 @@
1
1
  import { Logger } from './logger';
2
- export declare function retrier<T>(fn: () => Promise<T>, logger: Logger, retries?: number, interval?: number, shouldRetry?: (e: unknown) => boolean): Promise<T>;
2
+ export declare const DEFAULT_RETRY_INTERVAL = 0.1;
3
+ export declare const DEFAULT_RETRY_COUNT = 8;
4
+ export declare const DEFAULT_MAX_JITTER = 100;
5
+ export interface RetrierConfig {
6
+ maxAttempts?: number;
7
+ initialInterval?: number;
8
+ maxJitter?: number;
9
+ shouldRetry?: (e: unknown) => boolean;
10
+ }
11
+ export declare function retrier<T>(fn: () => Promise<T>, logger: Logger, config?: RetrierConfig): Promise<T>;
package/util/retrier.js CHANGED
@@ -12,13 +12,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.DEFAULT_MAX_JITTER = exports.DEFAULT_RETRY_COUNT = exports.DEFAULT_RETRY_INTERVAL = void 0;
15
16
  exports.retrier = retrier;
16
17
  const sleep_1 = __importDefault(require("./sleep"));
17
- const DEFAULT_RETRY_INTERVAL = 0.1; // seconds
18
- const DEFAULT_RETRY_COUNT = 8;
19
- const MAX_JITTER = 100; // milliseconds
20
- function retrier(fn_1, logger_1) {
21
- return __awaiter(this, arguments, void 0, function* (fn, logger, retries = DEFAULT_RETRY_COUNT, interval = DEFAULT_RETRY_INTERVAL, shouldRetry = () => true) {
18
+ exports.DEFAULT_RETRY_INTERVAL = 0.1; // seconds
19
+ exports.DEFAULT_RETRY_COUNT = 8;
20
+ exports.DEFAULT_MAX_JITTER = 100; // milliseconds
21
+ function retrier(fn, logger, config) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ var _a, _b, _c, _d;
24
+ const retries = Math.max(1, (_a = config === null || config === void 0 ? void 0 : config.maxAttempts) !== null && _a !== void 0 ? _a : exports.DEFAULT_RETRY_COUNT);
25
+ const interval = (_b = config === null || config === void 0 ? void 0 : config.initialInterval) !== null && _b !== void 0 ? _b : exports.DEFAULT_RETRY_INTERVAL;
26
+ const maxJitter = (_c = config === null || config === void 0 ? void 0 : config.maxJitter) !== null && _c !== void 0 ? _c : exports.DEFAULT_MAX_JITTER;
27
+ const shouldRetry = (_d = config === null || config === void 0 ? void 0 : config.shouldRetry) !== null && _d !== void 0 ? _d : (() => true);
22
28
  let lastError;
23
29
  for (let i = 0; i < retries; i++) {
24
30
  try {
@@ -30,11 +36,11 @@ function retrier(fn_1, logger_1) {
30
36
  }
31
37
  lastError = e instanceof Error ? e : new Error(String(e));
32
38
  logger.error(`Error: ${lastError.message}`);
33
- // Calculate exponential backoff with random jitter
34
- const exponentialDelay = interval * 2 ** i * 1000;
35
- const jitter = Math.random() * MAX_JITTER;
36
- const totalDelay = exponentialDelay + jitter;
37
- yield (0, sleep_1.default)(totalDelay);
39
+ if (i < retries - 1) {
40
+ const exponentialDelay = interval * 2 ** i * 1000;
41
+ const jitter = Math.random() * maxJitter;
42
+ yield (0, sleep_1.default)(exponentialDelay + jitter);
43
+ }
38
44
  }
39
45
  }
40
46
  throw lastError;
@@ -184,7 +184,7 @@ class AdminClient {
184
184
  trailerMetadata = trailer;
185
185
  },
186
186
  });
187
- }), this.logger, undefined, undefined, (e) => !isNiceGrpcAlreadyExists(e));
187
+ }), this.logger, Object.assign(Object.assign({}, this.config.retrier), { shouldRetry: (e) => !isNiceGrpcAlreadyExists(e) }));
188
188
  const id = resp.workflowRunId;
189
189
  const ref = new workflow_run_ref_1.default(id, this.listenerClient, this.runs, options === null || options === void 0 ? void 0 : options.parentId, options === null || options === void 0 ? void 0 : options._standaloneTaskName);
190
190
  yield ref.getWorkflowRunId();
@@ -242,8 +242,8 @@ class AdminClient {
242
242
  bulkTrailerMetadata = trailer;
243
243
  },
244
244
  });
245
- }), this.logger, undefined, undefined, (e) => !isNiceGrpcAlreadyExists(e) &&
246
- !(isGrpcServiceError(e) && e.code === grpc_js_1.status.ALREADY_EXISTS));
245
+ }), this.logger, Object.assign(Object.assign({}, this.config.retrier), { shouldRetry: (e) => !isNiceGrpcAlreadyExists(e) &&
246
+ !(isGrpcServiceError(e) && e.code === grpc_js_1.status.ALREADY_EXISTS) }));
247
247
  this.logger.debug(`batch ${batchIndex + 1} of ${batches.length}`);
248
248
  // Map the results back to their original indices
249
249
  const batchResults = bulkTriggerWorkflowResponse.workflowRunIds.map((resp, index) => {
@@ -277,7 +277,7 @@ class AdminClient {
277
277
  limit,
278
278
  duration,
279
279
  };
280
- yield (0, retrier_1.retrier)(() => __awaiter(this, void 0, void 0, function* () { return this.workflowsGrpc.putRateLimit(request); }), this.logger);
280
+ yield (0, retrier_1.retrier)(() => __awaiter(this, void 0, void 0, function* () { return this.workflowsGrpc.putRateLimit(request); }), this.logger, this.config.retrier);
281
281
  });
282
282
  }
283
283
  }
package/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const HATCHET_VERSION = "1.26.1";
1
+ export declare const HATCHET_VERSION = "1.26.2";
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.26.1';
4
+ exports.HATCHET_VERSION = '1.26.2';