Skip to content

Commit 9f9f794

Browse files
jwulfCopilot
andcommitted
fix(config): add signedInt schema type for CAMUNDA_WORKER_REQUEST_TIMEOUT
CAMUNDA_WORKER_REQUEST_TIMEOUT supports negative values (immediate completion semantics), but was typed as 'string' in the schema, making CamundaOptions.config accept string instead of number for this key and bypassing input validation entirely. Introduce a 'signedInt' schema type with a dedicated parser that accepts base-10 integers with an optional leading minus sign. This: - Types the config override as number in TypeScript - Validates input (rejects 'abc', '5.0', etc.) - Allows negative values like -1 Also fix the worker defaults comment to mention both createJobWorker and createThreadedJobWorker. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 74dd50d commit 9f9f794

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

src/runtime/configSchema.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ export const SCHEMA = {
209209
default: false,
210210
doc: 'Alias for CAMUNDA_SUPPORT_LOG_ENABLED (deprecated).',
211211
},
212-
// Worker defaults (heritable to all workers created via createJobWorker)
212+
// Worker defaults (heritable to all workers created via createJobWorker/createThreadedJobWorker)
213213
CAMUNDA_WORKER_TIMEOUT: {
214214
type: 'int',
215215
doc: 'Default job timeout in ms for all workers. Individual JobWorkerConfig.jobTimeoutMs overrides this.',
@@ -219,8 +219,8 @@ export const SCHEMA = {
219219
doc: 'Default max parallel jobs for all workers. Individual JobWorkerConfig.maxParallelJobs overrides this.',
220220
},
221221
CAMUNDA_WORKER_REQUEST_TIMEOUT: {
222-
type: 'string',
223-
doc: 'Default long-poll timeout in ms for all workers (signed integer string; negative values are valid — they cause activation to complete immediately when no jobs are available). Individual JobWorkerConfig.pollTimeoutMs overrides this.',
222+
type: 'signedInt',
223+
doc: 'Default long-poll timeout in ms for all workers. Negative values cause activation to complete immediately when no jobs are available. Individual JobWorkerConfig.pollTimeoutMs overrides this.',
224224
},
225225
CAMUNDA_WORKER_NAME: {
226226
type: 'string',
@@ -239,7 +239,7 @@ type PrimitiveType<T> = T extends { type: 'string' }
239239
? string
240240
: T extends { type: 'boolean' }
241241
? boolean
242-
: T extends { type: 'int' }
242+
: T extends { type: 'int' | 'signedInt' }
243243
? number
244244
: T extends { type: 'enum'; choices: readonly (infer C)[] }
245245
? C

src/runtime/unifiedConfiguration.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,23 @@ function parseInteger(raw: string, key: string, errors: ConfigErrorDetail[]): nu
190190
return undefined;
191191
}
192192

193+
// Signed integer parser (allows negative values)
194+
function parseSignedInteger(
195+
raw: string,
196+
key: string,
197+
errors: ConfigErrorDetail[]
198+
): number | undefined {
199+
const v = raw.trim();
200+
if (v === '') return undefined;
201+
if (/^-?[0-9]+$/.test(v)) return parseInt(v, 10);
202+
errors.push({
203+
code: ConfigErrorCode.CONFIG_INVALID_INTEGER,
204+
key,
205+
message: `Invalid integer '${raw}'. Only base-10 integers (optionally negative) allowed.`,
206+
});
207+
return undefined;
208+
}
209+
193210
// Validation mini-language parser (strict per design)
194211
function parseValidation(
195212
raw: string,
@@ -291,6 +308,13 @@ export function hydrateConfig(options: HydrateOptions = {}): HydratedConfigurati
291308
return parsed;
292309
};
293310
}
311+
function signedIntParserFactory(key: string) {
312+
return (v: string) => {
313+
const parsed = parseSignedInteger(v, key, parseErrors);
314+
if (parsed === undefined) return undefined;
315+
return parsed;
316+
};
317+
}
294318
function enumParserFactory(key: string, choices: readonly string[]) {
295319
// Case-insensitive parsing. Canonicalize to schema-declared casing style.
296320
// If all choices are lowercase => return lowercase value.
@@ -334,6 +358,10 @@ export function hydrateConfig(options: HydrateOptions = {}): HydratedConfigurati
334358
const base: any = { parser: intParserFactory(k), ...baseOpt };
335359
if (entry.default !== undefined) base.default = entry.default;
336360
typedEnvSchema[k] = base;
361+
} else if (entry.type === 'signedInt') {
362+
const base: any = { parser: signedIntParserFactory(k), ...baseOpt };
363+
if (entry.default !== undefined) base.default = entry.default;
364+
typedEnvSchema[k] = base;
337365
} else if (entry.type === 'enum') {
338366
const base: any = { parser: enumParserFactory(k, entry.choices || []), ...baseOpt };
339367
if (entry.default !== undefined) base.default = entry.default;

0 commit comments

Comments
 (0)