@nuetzliches/croniq-runner 0.1.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +172 -0
  3. package/dist/abort.d.ts +7 -0
  4. package/dist/abort.d.ts.map +1 -0
  5. package/dist/abort.js +31 -0
  6. package/dist/abort.js.map +1 -0
  7. package/dist/client.d.ts +32 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +147 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/context.d.ts +82 -0
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/context.js +52 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/deferred.d.ts +18 -0
  16. package/dist/deferred.d.ts.map +1 -0
  17. package/dist/deferred.js +40 -0
  18. package/dist/deferred.js.map +1 -0
  19. package/dist/dispatcher.d.ts +33 -0
  20. package/dist/dispatcher.d.ts.map +1 -0
  21. package/dist/dispatcher.js +159 -0
  22. package/dist/dispatcher.js.map +1 -0
  23. package/dist/duration.d.ts +2 -0
  24. package/dist/duration.d.ts.map +1 -0
  25. package/dist/duration.js +23 -0
  26. package/dist/duration.js.map +1 -0
  27. package/dist/enrichment.d.ts +15 -0
  28. package/dist/enrichment.d.ts.map +1 -0
  29. package/dist/enrichment.js +30 -0
  30. package/dist/enrichment.js.map +1 -0
  31. package/dist/handler.d.ts +35 -0
  32. package/dist/handler.d.ts.map +1 -0
  33. package/dist/handler.js +47 -0
  34. package/dist/handler.js.map +1 -0
  35. package/dist/identity.d.ts +23 -0
  36. package/dist/identity.d.ts.map +1 -0
  37. package/dist/identity.js +64 -0
  38. package/dist/identity.js.map +1 -0
  39. package/dist/index.d.ts +11 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +6 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/log-writer.d.ts +38 -0
  44. package/dist/log-writer.d.ts.map +1 -0
  45. package/dist/log-writer.js +153 -0
  46. package/dist/log-writer.js.map +1 -0
  47. package/dist/logger.d.ts +27 -0
  48. package/dist/logger.d.ts.map +1 -0
  49. package/dist/logger.js +65 -0
  50. package/dist/logger.js.map +1 -0
  51. package/dist/options.d.ts +89 -0
  52. package/dist/options.d.ts.map +1 -0
  53. package/dist/options.js +50 -0
  54. package/dist/options.js.map +1 -0
  55. package/dist/protocol.d.ts +54 -0
  56. package/dist/protocol.d.ts.map +1 -0
  57. package/dist/protocol.js +8 -0
  58. package/dist/protocol.js.map +1 -0
  59. package/dist/runner.d.ts +40 -0
  60. package/dist/runner.d.ts.map +1 -0
  61. package/dist/runner.js +226 -0
  62. package/dist/runner.js.map +1 -0
  63. package/dist/url.d.ts +10 -0
  64. package/dist/url.d.ts.map +1 -0
  65. package/dist/url.js +20 -0
  66. package/dist/url.js.map +1 -0
  67. package/package.json +63 -0
@@ -0,0 +1,153 @@
1
+ import { deferred, sleep } from './deferred.js';
2
+ /**
3
+ * Streaming log writer. Backed by a bounded in-memory buffer and a single
4
+ * background flusher coroutine; mirrors the .NET / Rust SDKs:
5
+ *
6
+ * - Batch by count: flush when {@link ResolvedLogWriterOptions.batchSizeThreshold} events accumulate.
7
+ * - Batch by time: flush at least every {@link ResolvedLogWriterOptions.batchTimeThresholdMs} ms.
8
+ * - Drain-before-ack: {@link dispose} waits up to `shutdownTimeoutMs` for the buffer to flush.
9
+ * - Backpressure: {@link write} awaits when the buffer is at capacity.
10
+ *
11
+ * Enrichment runs at POST time (`job_key`, `runner_id`, `runner_tags`).
12
+ */
13
+ export class StreamingLogWriter {
14
+ #client;
15
+ #executionId;
16
+ #enrichment;
17
+ #opts;
18
+ #logger;
19
+ #buffer = [];
20
+ #pendingFlushes = [];
21
+ /** Resolved when a slot frees up in the bounded buffer. */
22
+ #spaceAvailable = null;
23
+ /** Resolved when new events arrive (wakes the flusher early). */
24
+ #eventsAvailable = null;
25
+ #closed = false;
26
+ #disposed = false;
27
+ #flusherTask;
28
+ constructor(client, executionId, enrichment, opts, logger) {
29
+ this.#client = client;
30
+ this.#executionId = executionId;
31
+ this.#enrichment = enrichment;
32
+ this.#opts = opts;
33
+ this.#logger = logger;
34
+ this.#flusherTask = this.#runFlusher();
35
+ }
36
+ async write(level, message, fields) {
37
+ const event = fields ? { level, message, fields } : { level, message };
38
+ return this.writeEvent(event);
39
+ }
40
+ async writeEvent(event) {
41
+ while (!this.#closed && this.#buffer.length >= this.#opts.channelCapacity) {
42
+ this.#spaceAvailable ??= deferred();
43
+ await this.#spaceAvailable.promise;
44
+ }
45
+ if (this.#closed)
46
+ return;
47
+ this.#buffer.push(event);
48
+ this.#wake();
49
+ }
50
+ flush() {
51
+ if (this.#closed && this.#buffer.length === 0)
52
+ return Promise.resolve();
53
+ const d = deferred();
54
+ this.#pendingFlushes.push(d);
55
+ this.#wake();
56
+ return d.promise;
57
+ }
58
+ async dispose() {
59
+ if (this.#disposed)
60
+ return;
61
+ this.#disposed = true;
62
+ this.#closed = true;
63
+ this.#wake();
64
+ // Release any writers parked on a full buffer so they unblock and observe `closed`.
65
+ this.#releaseWriters();
66
+ let timedOut = false;
67
+ const timeoutController = new AbortController();
68
+ const timeout = sleep(this.#opts.shutdownTimeoutMs, timeoutController.signal).then(() => { timedOut = true; }, () => { });
69
+ await Promise.race([this.#flusherTask, timeout]);
70
+ timeoutController.abort();
71
+ if (timedOut) {
72
+ this.#logger.warn(`log_writer drain timed out after ${this.#opts.shutdownTimeoutMs}ms (execution ${this.#executionId})`, { execution_id: this.#executionId });
73
+ }
74
+ }
75
+ #wake() {
76
+ if (this.#eventsAvailable) {
77
+ const d = this.#eventsAvailable;
78
+ this.#eventsAvailable = null;
79
+ d.resolve();
80
+ }
81
+ }
82
+ #releaseWriters() {
83
+ if (this.#spaceAvailable) {
84
+ const d = this.#spaceAvailable;
85
+ this.#spaceAvailable = null;
86
+ d.resolve();
87
+ }
88
+ }
89
+ async #runFlusher() {
90
+ try {
91
+ while (!this.#closed || this.#buffer.length > 0 || this.#pendingFlushes.length > 0) {
92
+ // Wait for one of: new events arrived, the time-threshold tick fires,
93
+ // or the writer was closed. The deferred is re-created each iteration
94
+ // so callers awakening it have a fresh promise to settle.
95
+ if (this.#buffer.length === 0 && this.#pendingFlushes.length === 0 && !this.#closed) {
96
+ this.#eventsAvailable = deferred();
97
+ const tickController = new AbortController();
98
+ const tick = sleep(this.#opts.batchTimeThresholdMs, tickController.signal).catch(() => undefined);
99
+ await Promise.race([this.#eventsAvailable.promise, tick]);
100
+ tickController.abort();
101
+ this.#eventsAvailable = null;
102
+ }
103
+ // Drain whatever has accumulated. We pull *everything* — the
104
+ // batch-size threshold is honoured per-POST inside flushAll().
105
+ if (this.#buffer.length > 0) {
106
+ const batch = this.#buffer;
107
+ this.#buffer = [];
108
+ this.#releaseWriters();
109
+ await this.#flushAll(batch);
110
+ }
111
+ if (this.#pendingFlushes.length > 0) {
112
+ // Drain any events that arrived while we were posting the prior batch.
113
+ if (this.#buffer.length > 0) {
114
+ const more = this.#buffer;
115
+ this.#buffer = [];
116
+ this.#releaseWriters();
117
+ await this.#flushAll(more);
118
+ }
119
+ const resolvers = this.#pendingFlushes;
120
+ this.#pendingFlushes = [];
121
+ for (const r of resolvers)
122
+ r.resolve();
123
+ }
124
+ }
125
+ }
126
+ catch (err) {
127
+ this.#logger.error(`log_writer flusher crashed (execution ${this.#executionId})`, { error: String(err) });
128
+ }
129
+ finally {
130
+ // Reject any remaining flushers so callers don't hang.
131
+ for (const r of this.#pendingFlushes)
132
+ r.resolve();
133
+ this.#pendingFlushes = [];
134
+ this.#releaseWriters();
135
+ }
136
+ }
137
+ async #flushAll(events) {
138
+ const max = this.#opts.maxBatchPerPost;
139
+ for (let i = 0; i < events.length; i += max) {
140
+ const chunk = events.slice(i, i + max).map((e) => this.#enrichment.enrich(e));
141
+ try {
142
+ // Use a fresh AbortController per POST so client cancellation is
143
+ // localised — a slow batch should not bring down later batches.
144
+ const ac = new AbortController();
145
+ await this.#client.pushEvents(this.#executionId, chunk, ac.signal);
146
+ }
147
+ catch (err) {
148
+ this.#logger.warn(`log_writer: batch POST failed — ${chunk.length} events dropped (execution ${this.#executionId})`, { error: String(err), execution_id: this.#executionId, dropped: chunk.length });
149
+ }
150
+ }
151
+ }
152
+ }
153
+ //# sourceMappingURL=log-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-writer.js","sourceRoot":"","sources":["../src/log-writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { WorkEventLevel } from './protocol.js';
2
+ export type LogLevel = WorkEventLevel;
3
+ export interface Logger {
4
+ trace(message: string, fields?: Record<string, unknown>): void;
5
+ debug(message: string, fields?: Record<string, unknown>): void;
6
+ info(message: string, fields?: Record<string, unknown>): void;
7
+ warn(message: string, fields?: Record<string, unknown>): void;
8
+ error(message: string, fields?: Record<string, unknown>): void;
9
+ }
10
+ /**
11
+ * Console-backed logger that emits at or above {@link minLevel}.
12
+ *
13
+ * The runner's internal diagnostics default to `warn` so SDK noise stays
14
+ * out of an application's stdout/stderr unless something is going wrong.
15
+ * Job handlers receive a separate per-execution `Logger` whose minLevel
16
+ * defaults to `info`.
17
+ */
18
+ export declare function consoleLogger(minLevel?: LogLevel, prefix?: string): Logger;
19
+ /** Logger that drops every message — useful for tests. */
20
+ export declare const noopLogger: Logger;
21
+ /**
22
+ * Wraps a logger so every emitted record carries the given extra fields,
23
+ * merged with whatever the caller passes in (caller wins). Used to scope a
24
+ * handler-side logger with `execution_id`, `job_key`, `runner_id`, `attempt`.
25
+ */
26
+ export declare function scopedLogger(base: Logger, extra: Record<string, unknown>): Logger;
27
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,MAAM,QAAQ,GAAG,cAAc,CAAC;AAEtC,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAChE;AAUD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,GAAE,QAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBlF;AAED,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,MAMxB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CASjF"}
package/dist/logger.js ADDED
@@ -0,0 +1,65 @@
1
+ const ORDER = {
2
+ trace: 0,
3
+ debug: 1,
4
+ info: 2,
5
+ warn: 3,
6
+ error: 4,
7
+ };
8
+ /**
9
+ * Console-backed logger that emits at or above {@link minLevel}.
10
+ *
11
+ * The runner's internal diagnostics default to `warn` so SDK noise stays
12
+ * out of an application's stdout/stderr unless something is going wrong.
13
+ * Job handlers receive a separate per-execution `Logger` whose minLevel
14
+ * defaults to `info`.
15
+ */
16
+ export function consoleLogger(minLevel = 'warn', prefix) {
17
+ const threshold = ORDER[minLevel];
18
+ const tag = prefix ? `[${prefix}] ` : '';
19
+ const emit = (level, message, fields) => {
20
+ if (ORDER[level] < threshold)
21
+ return;
22
+ const line = fields && Object.keys(fields).length > 0
23
+ ? `${tag}${level}: ${message} ${JSON.stringify(fields)}`
24
+ : `${tag}${level}: ${message}`;
25
+ // Map to console method, but funnel everything to stderr for warn/error
26
+ // so application stdout stays clean for actual job output.
27
+ // eslint-disable-next-line no-console
28
+ if (level === 'error' || level === 'warn')
29
+ console.error(line);
30
+ // eslint-disable-next-line no-console
31
+ else
32
+ console.log(line);
33
+ };
34
+ return {
35
+ trace: (m, f) => emit('trace', m, f),
36
+ debug: (m, f) => emit('debug', m, f),
37
+ info: (m, f) => emit('info', m, f),
38
+ warn: (m, f) => emit('warn', m, f),
39
+ error: (m, f) => emit('error', m, f),
40
+ };
41
+ }
42
+ /** Logger that drops every message — useful for tests. */
43
+ export const noopLogger = {
44
+ trace: () => { },
45
+ debug: () => { },
46
+ info: () => { },
47
+ warn: () => { },
48
+ error: () => { },
49
+ };
50
+ /**
51
+ * Wraps a logger so every emitted record carries the given extra fields,
52
+ * merged with whatever the caller passes in (caller wins). Used to scope a
53
+ * handler-side logger with `execution_id`, `job_key`, `runner_id`, `attempt`.
54
+ */
55
+ export function scopedLogger(base, extra) {
56
+ const merge = (fields) => ({ ...extra, ...(fields ?? {}) });
57
+ return {
58
+ trace: (m, f) => base.trace(m, merge(f)),
59
+ debug: (m, f) => base.debug(m, merge(f)),
60
+ info: (m, f) => base.info(m, merge(f)),
61
+ warn: (m, f) => base.warn(m, merge(f)),
62
+ error: (m, f) => base.error(m, merge(f)),
63
+ };
64
+ }
65
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import type { Logger } from './logger.js';
2
+ export interface LogWriterOptions {
3
+ /** Bounded queue capacity. Backpressure kicks in when full. Default 256. */
4
+ channelCapacity?: number;
5
+ /** Flush when this many events have accumulated. Default 32. */
6
+ batchSizeThreshold?: number;
7
+ /** Flush at least this often, even if the size threshold isn't reached. Default 200 ms. */
8
+ batchTimeThresholdMs?: number;
9
+ /** Maximum events per outgoing HTTP POST. Default 100. */
10
+ maxBatchPerPost?: number;
11
+ /** Maximum time the runner waits for queued events to flush during per-execution drain. Default 5 s. */
12
+ shutdownTimeoutMs?: number;
13
+ }
14
+ export interface ResolvedLogWriterOptions {
15
+ channelCapacity: number;
16
+ batchSizeThreshold: number;
17
+ batchTimeThresholdMs: number;
18
+ maxBatchPerPost: number;
19
+ shutdownTimeoutMs: number;
20
+ }
21
+ export interface CroniqRunnerOptions {
22
+ /** Base URL of the Croniq server, e.g. `http://localhost:4000`. */
23
+ serverUrl: string;
24
+ /**
25
+ * Stable runner identifier. If omitted, the SDK resolves it via
26
+ * `RUNNER_ID` env var → state file under {@link runnerDataDir} →
27
+ * a newly generated `{prefix}-{hex8}` persisted to the state file.
28
+ */
29
+ runnerId?: string;
30
+ /** Prefix used when generating a fresh runner ID. Default `"runner"`. */
31
+ runnerIdPrefix?: string;
32
+ /**
33
+ * Directory the SDK reads/writes the persistent runner-id file in.
34
+ * Honors `CRONIQ_RUNNER_DATA_DIR` when omitted. Defaults to
35
+ * `$XDG_STATE_HOME/croniq-runner` (or platform equivalent).
36
+ */
37
+ runnerDataDir?: string;
38
+ /** API key used for `Authorization: ApiKey {key}`. Takes precedence over {@link bearerToken}. */
39
+ apiKey?: string;
40
+ /** Bearer token used for `Authorization: Bearer {token}`. */
41
+ bearerToken?: string;
42
+ /**
43
+ * Capabilities the runner advertises (e.g. `"billing"`, `"reporting"`).
44
+ * Used by the server for job routing (`require` / `prefer` in the Croniqfile).
45
+ */
46
+ capabilities?: string[];
47
+ /**
48
+ * Free-form tags the runner declares about itself. Filter-only — does
49
+ * NOT influence routing (capabilities do that). Convention is
50
+ * `key=value` strings (e.g. `"env=prod"`, `"lang=typescript"`).
51
+ */
52
+ tags?: string[];
53
+ /** Maximum concurrent in-flight executions. Default 5, range [1, 1024]. */
54
+ maxInflight?: number;
55
+ /** Per-request timeout for the long-poll work endpoint. Default 35 000 ms. */
56
+ pollTimeoutMs?: number;
57
+ /** Interval at which the runner sends lease-renewal heartbeats. Default 15 000 ms. */
58
+ renewIntervalMs?: number;
59
+ /** Maximum time the runner waits for in-flight handlers during graceful shutdown. Default 30 000 ms. */
60
+ drainTimeoutMs?: number;
61
+ /** Backoff after a failed poll request. Default 5 000 ms. */
62
+ pollRetryDelayMs?: number;
63
+ /** Idle delay when the runner is at `maxInflight` capacity. Default 500 ms. */
64
+ capacityBackoffMs?: number;
65
+ /** Streaming log-writer tunables. */
66
+ logWriter?: LogWriterOptions;
67
+ /** Optional logger for SDK-level diagnostics. Defaults to a console logger that emits warn/error only. */
68
+ logger?: Logger;
69
+ }
70
+ export interface ResolvedRunnerOptions {
71
+ serverUrl: string;
72
+ runnerId: string | undefined;
73
+ runnerIdPrefix: string;
74
+ runnerDataDir: string | undefined;
75
+ apiKey: string | undefined;
76
+ bearerToken: string | undefined;
77
+ capabilities: string[];
78
+ tags: string[];
79
+ maxInflight: number;
80
+ pollTimeoutMs: number;
81
+ renewIntervalMs: number;
82
+ drainTimeoutMs: number;
83
+ pollRetryDelayMs: number;
84
+ capacityBackoffMs: number;
85
+ logWriter: ResolvedLogWriterOptions;
86
+ logger: Logger;
87
+ }
88
+ export declare function resolveOptions(input: CroniqRunnerOptions, defaultLogger: Logger): ResolvedRunnerOptions;
89
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2FAA2F;IAC3F,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wGAAwG;IACxG,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,sFAAsF;IACtF,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,wGAAwG;IACxG,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,qCAAqC;IACrC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAE7B,0GAA0G;IAC1G,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,wBAAwB,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;CAChB;AAUD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,GAAG,qBAAqB,CA0CvG"}
@@ -0,0 +1,50 @@
1
+ import { trimTrailingSlashes } from './url.js';
2
+ const DEFAULT_LOG_WRITER = {
3
+ channelCapacity: 256,
4
+ batchSizeThreshold: 32,
5
+ batchTimeThresholdMs: 200,
6
+ maxBatchPerPost: 100,
7
+ shutdownTimeoutMs: 5_000,
8
+ };
9
+ export function resolveOptions(input, defaultLogger) {
10
+ if (!input.serverUrl || typeof input.serverUrl !== 'string') {
11
+ throw new TypeError('CroniqRunnerOptions.serverUrl is required');
12
+ }
13
+ try {
14
+ // eslint-disable-next-line no-new
15
+ new URL(input.serverUrl);
16
+ }
17
+ catch {
18
+ throw new TypeError(`CroniqRunnerOptions.serverUrl is not a valid URL: ${input.serverUrl}`);
19
+ }
20
+ const maxInflight = input.maxInflight ?? 5;
21
+ if (!Number.isInteger(maxInflight) || maxInflight < 1 || maxInflight > 1024) {
22
+ throw new RangeError(`CroniqRunnerOptions.maxInflight must be an integer in [1, 1024], got ${maxInflight}`);
23
+ }
24
+ const logWriter = {
25
+ channelCapacity: input.logWriter?.channelCapacity ?? DEFAULT_LOG_WRITER.channelCapacity,
26
+ batchSizeThreshold: input.logWriter?.batchSizeThreshold ?? DEFAULT_LOG_WRITER.batchSizeThreshold,
27
+ batchTimeThresholdMs: input.logWriter?.batchTimeThresholdMs ?? DEFAULT_LOG_WRITER.batchTimeThresholdMs,
28
+ maxBatchPerPost: input.logWriter?.maxBatchPerPost ?? DEFAULT_LOG_WRITER.maxBatchPerPost,
29
+ shutdownTimeoutMs: input.logWriter?.shutdownTimeoutMs ?? DEFAULT_LOG_WRITER.shutdownTimeoutMs,
30
+ };
31
+ return {
32
+ serverUrl: trimTrailingSlashes(input.serverUrl),
33
+ runnerId: input.runnerId,
34
+ runnerIdPrefix: input.runnerIdPrefix ?? 'runner',
35
+ runnerDataDir: input.runnerDataDir,
36
+ apiKey: input.apiKey,
37
+ bearerToken: input.bearerToken,
38
+ capabilities: [...(input.capabilities ?? [])],
39
+ tags: [...(input.tags ?? [])],
40
+ maxInflight,
41
+ pollTimeoutMs: input.pollTimeoutMs ?? 35_000,
42
+ renewIntervalMs: input.renewIntervalMs ?? 15_000,
43
+ drainTimeoutMs: input.drainTimeoutMs ?? 30_000,
44
+ pollRetryDelayMs: input.pollRetryDelayMs ?? 5_000,
45
+ capacityBackoffMs: input.capacityBackoffMs ?? 500,
46
+ logWriter,
47
+ logger: input.logger ?? defaultLogger,
48
+ };
49
+ }
50
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AA2G/C,MAAM,kBAAkB,GAA6B;IACnD,eAAe,EAAE,GAAG;IACpB,kBAAkB,EAAE,EAAE;IACtB,oBAAoB,EAAE,GAAG;IACzB,eAAe,EAAE,GAAG;IACpB,iBAAiB,EAAE,KAAK;CACzB,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,KAA0B,EAAE,aAAqB;IAC9E,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC5D,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC;QACH,kCAAkC;QAClC,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,SAAS,CAAC,qDAAqD,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QAC5E,MAAM,IAAI,UAAU,CAAC,wEAAwE,WAAW,EAAE,CAAC,CAAC;IAC9G,CAAC;IAED,MAAM,SAAS,GAA6B;QAC1C,eAAe,EAAE,KAAK,CAAC,SAAS,EAAE,eAAe,IAAI,kBAAkB,CAAC,eAAe;QACvF,kBAAkB,EAAE,KAAK,CAAC,SAAS,EAAE,kBAAkB,IAAI,kBAAkB,CAAC,kBAAkB;QAChG,oBAAoB,EAAE,KAAK,CAAC,SAAS,EAAE,oBAAoB,IAAI,kBAAkB,CAAC,oBAAoB;QACtG,eAAe,EAAE,KAAK,CAAC,SAAS,EAAE,eAAe,IAAI,kBAAkB,CAAC,eAAe;QACvF,iBAAiB,EAAE,KAAK,CAAC,SAAS,EAAE,iBAAiB,IAAI,kBAAkB,CAAC,iBAAiB;KAC9F,CAAC;IAEF,OAAO;QACL,SAAS,EAAE,mBAAmB,CAAC,KAAK,CAAC,SAAS,CAAC;QAC/C,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,QAAQ;QAChD,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC7B,WAAW;QACX,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,MAAM;QAC5C,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,MAAM;QAChD,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,MAAM;QAC9C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,KAAK;QACjD,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,IAAI,GAAG;QACjD,SAAS;QACT,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,aAAa;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,54 @@
1
+ export interface PollRequest {
2
+ runner_id: string;
3
+ capabilities: string[];
4
+ max_inflight: number;
5
+ inflight: string[];
6
+ instance_id?: string;
7
+ tags: string[];
8
+ }
9
+ export interface WorkAssignment {
10
+ execution_id: string;
11
+ job_key: string;
12
+ fire_at: string;
13
+ attempt: number;
14
+ metadata: unknown;
15
+ timeout?: string;
16
+ }
17
+ export interface PollResponse {
18
+ work: WorkAssignment[];
19
+ cancel: string[];
20
+ }
21
+ export type AckStatus = 'success' | 'failure';
22
+ export interface AckRequest {
23
+ runner_id: string;
24
+ execution_id: string;
25
+ status: AckStatus;
26
+ error?: string;
27
+ duration_ms?: number;
28
+ attempt: number;
29
+ }
30
+ export interface RenewRequest {
31
+ runner_id: string;
32
+ execution_id: string;
33
+ }
34
+ export interface RegisterJobRequest {
35
+ job_key: string;
36
+ schedule: string;
37
+ timezone?: string;
38
+ timeout?: string;
39
+ runner_id?: string;
40
+ capabilities: string[];
41
+ description?: string;
42
+ }
43
+ export interface RegisterJobResponse {
44
+ job_key: string;
45
+ trigger_id?: string;
46
+ status?: 'registered' | 'skipped_dsl_precedence';
47
+ }
48
+ export type WorkEventLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
49
+ export interface WorkEvent {
50
+ level?: WorkEventLevel;
51
+ message: string;
52
+ fields?: Record<string, string>;
53
+ }
54
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,GAAG,wBAAwB,CAAC;CAClD;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3E,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC"}
@@ -0,0 +1,8 @@
1
+ // Wire-protocol types for the Croniq runner API.
2
+ //
3
+ // Field names are snake_case to match the JSON shape in `openapi.yaml`.
4
+ // These types are sent and received verbatim over HTTP — no field
5
+ // transformation happens at the client boundary, so consumer code that
6
+ // touches `metadata` will see the original snake_case keys the server sent.
7
+ export {};
8
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,wEAAwE;AACxE,kEAAkE;AAClE,uEAAuE;AACvE,4EAA4E"}
@@ -0,0 +1,40 @@
1
+ import { type JobHandler, type JobRegistrationOptions } from './handler.js';
2
+ import { type CroniqRunnerOptions } from './options.js';
3
+ /**
4
+ * The Croniq runner: polls the server for work, dispatches handlers
5
+ * concurrently up to {@link CroniqRunnerOptions.maxInflight}, renews leases
6
+ * for in-flight executions, and reports completion.
7
+ *
8
+ * Call {@link run} to drive the loop yourself. Wire `SIGTERM`/`SIGINT` to
9
+ * the AbortController you pass in for graceful shutdown.
10
+ */
11
+ export declare class CroniqRunner {
12
+ #private;
13
+ constructor(options: CroniqRunnerOptions);
14
+ /**
15
+ * Register a handler for a specific `job_key`. If {@link JobRegistrationOptions.schedule}
16
+ * is set, the runner calls `POST /v1/jobs/register` for the job at startup
17
+ * (DSL precedence still applies server-side).
18
+ */
19
+ handle(jobKey: string, handler: JobHandler, opts?: JobRegistrationOptions): this;
20
+ /** Register a fallback handler for any job key that has no specific handler. */
21
+ setDefaultHandler(handler: JobHandler): this;
22
+ /** The stable runner ID, available after {@link run} has started. */
23
+ get runnerId(): string;
24
+ /** Snapshot of currently in-flight execution IDs. Diagnostic only. */
25
+ get inflight(): readonly string[];
26
+ /**
27
+ * Run the poll/dispatch/ack loop until {@link signal} aborts. Returns when
28
+ * the token signals AND all in-flight executions have either finished or
29
+ * the drain timeout elapses.
30
+ */
31
+ run(signal?: AbortSignal): Promise<void>;
32
+ /**
33
+ * Signal graceful shutdown without waiting. Cancels new polls; in-flight
34
+ * handlers keep running until they complete or the drain-timeout elapses.
35
+ */
36
+ requestDrain(): void;
37
+ }
38
+ /** Convenience factory. Equivalent to `new CroniqRunner(options)`. */
39
+ export declare function createRunner(options: CroniqRunnerOptions): CroniqRunner;
40
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAkB,KAAK,mBAAmB,EAA8B,MAAM,cAAc,CAAC;AAGpG;;;;;;;GAOG;AACH,qBAAa,YAAY;;gBAaX,OAAO,EAAE,mBAAmB;IAYxC;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,sBAAsB,GAAG,IAAI;IAKhF,gFAAgF;IAChF,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAK5C,qEAAqE;IACrE,IAAI,QAAQ,IAAI,MAAM,CAGrB;IAED,sEAAsE;IACtE,IAAI,QAAQ,IAAI,SAAS,MAAM,EAAE,CAEhC;IAED;;;;OAIG;IACG,GAAG,CAAC,MAAM,GAAE,WAA0C,GAAG,OAAO,CAAC,IAAI,CAAC;IA4C5E;;;OAGG;IACH,YAAY,IAAI,IAAI;CAoHrB;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAEvE"}