@boopkit/cap-background-jobs 0.2.6 → 0.3.1

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.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # @boopkit/cap-background-jobs
2
+
3
+ **Part of [Boop](https://www.npmjs.com/package/@boopkit/cli)** — a bootstrap platform for AI-first builders. `boop init` scaffolds a running Node/TypeScript web app from composable **capabilities**, each one bundling the code, dependencies, middleware wiring, and agent skills needed for a feature. You pick the capabilities; `boop add` handles the rest.
4
+
5
+ `cap-background-jobs` adds async job processing via RabbitMQ (CloudAMQP). You get a publish/listen API, a dedicated worker process, a scheduler CLI for cron-triggered jobs, and automatic retry/dead-letter topology per queue. Use it for anything that shouldn't block an HTTP response: image processing, outbound email, nightly reconciles, third-party webhooks.
6
+
7
+ ## What You Get
8
+
9
+ ### Scaffold files
10
+
11
+ Copied into your project on install:
12
+
13
+ - `src/worker.ts` — worker process entry point. Boots services, registers consumers, handles graceful shutdown
14
+ - `src/scheduler.ts` — CLI for publishing scheduled triggers, filtered by `--interval` and `--job`
15
+ - `src/controllers/example-job.controller.ts` — copyable template for message consumers (auto-ACK pattern)
16
+ - `tests/controllers/example-job.controller.test.ts` — example consumer tests
17
+ - `reference/background-jobs.ref.md` — infrastructure topology, ACK modes, Heroku setup
18
+
19
+ ### Scripts added to `package.json`
20
+
21
+ | Script | Command | Purpose |
22
+ |--------|---------|---------|
23
+ | `worker` | `tsx src/worker.ts` | Start the background job worker process |
24
+ | `scheduler` | `tsx src/scheduler.ts` | Publish trigger messages to job queues (`run-jobs`, `publish`, `list` subcommands) |
25
+
26
+ ### Skills installed
27
+
28
+ - `design.background-jobs.skill.md` — teaches agents how to add a consumer, choose between auto- and manual-ACK, add scheduled jobs, and handle retries.
29
+
30
+ ### Post-install
31
+
32
+ 1. Provision CloudAMQP (or any RabbitMQ instance) and add `CLOUDAMQP_URL` to `.env`
33
+ 2. Set `QUEUE_PREFIX=dev/<yourname>` to isolate your queues from other developers sharing the instance
34
+ 3. Add `worker: npm run worker` to your `Procfile`
35
+ 4. Configure your external scheduler (e.g. Heroku Scheduler) to run `npm run scheduler -- run-jobs --interval <tag>` on the desired cadence
36
+
37
+ `boop status` reminds you of these steps after install.
38
+
39
+ ## Requirements
40
+
41
+ **Other capabilities:**
42
+
43
+ - `cap-services` — the message queue is registered as `services.message-queue` via the service map
44
+
45
+ **npm dependencies added to your project:**
46
+
47
+ - `amqplib` — RabbitMQ client
48
+ - `minimist` — scheduler CLI argument parsing
49
+
50
+ **External services:**
51
+
52
+ - **RabbitMQ** — CloudAMQP is the easiest path on Heroku (`heroku addons:create cloudamqp`, which sets `CLOUDAMQP_URL` automatically). Any RabbitMQ broker works — local Docker, self-hosted, or AWS MQ — point `CLOUDAMQP_URL` at it.
53
+
54
+ **Environment variables:**
55
+
56
+ | Variable | Required | Description |
57
+ |----------|----------|-------------|
58
+ | `CLOUDAMQP_URL` | Yes (at boot) | RabbitMQ connection URL (`amqp://...` or `amqps://...`) |
59
+ | `QUEUE_PREFIX` | No | Queue name prefix for environment isolation (e.g. `dev/mike`). Leave empty in production |
60
+ | `MAX_MESSAGE_RETRIES` | No | Max retry attempts before dead-lettering (default: `5`) |
61
+
62
+ ## Usage
63
+
64
+ Three moving parts — web publishes, scheduler publishes on a cron, worker consumes. All share one `MessageQueueService` instance registered in the service map.
65
+
66
+ ### Publish a job
67
+
68
+ From a route handler, service, or anywhere in the web process:
69
+
70
+ ```ts
71
+ import { services } from '@services';
72
+
73
+ app.post('/upload', async (req, res) => {
74
+ const upload = await services.uploads.create(req.body);
75
+
76
+ // Enqueue async processing — returns immediately
77
+ await services.messageQueue.publish('process-upload', {
78
+ task: 'process-upload',
79
+ data: { uploadId: upload.id, userId: req.user.id },
80
+ });
81
+
82
+ res.status(202).json({ id: upload.id });
83
+ });
84
+ ```
85
+
86
+ The publish connection is lazy — it only opens when you actually publish. Your web dynos stay cheap.
87
+
88
+ ### Consume a job
89
+
90
+ **1.** Copy `src/controllers/example-job.controller.ts` to `src/controllers/process-upload.controller.ts` and replace the handler body:
91
+
92
+ ```ts
93
+ export const QUEUE_NAME = 'process-upload';
94
+
95
+ export async function onMessage(msg: unknown): Promise<boolean> {
96
+ const payload = validatePayload(msg);
97
+
98
+ try {
99
+ await services.uploads.process(payload.data.uploadId);
100
+ return true; // ACK — success
101
+ } catch (err) {
102
+ console.error('[process-upload] failed:', err);
103
+ return false; // retry with exponential backoff
104
+ }
105
+ }
106
+ ```
107
+
108
+ **2.** Register the consumer in `src/worker.ts`:
109
+
110
+ ```ts
111
+ import * as processUploadController from './controllers/process-upload.controller';
112
+
113
+ const consumers = [
114
+ { queue: exampleJobController.QUEUE_NAME, handler: exampleJobController.onMessage },
115
+ { queue: processUploadController.QUEUE_NAME, handler: processUploadController.onMessage },
116
+ ];
117
+ ```
118
+
119
+ **3.** Run the worker locally:
120
+
121
+ ```bash
122
+ npm run worker
123
+ ```
124
+
125
+ On first listen, the service asserts the queue topology: main queue, `.retry` queue (TTL-backed redelivery), and `.failed` dead-letter queue. Failed handlers retry with exponential backoff (4s → 60s, capped) up to `MAX_MESSAGE_RETRIES`, then land in the DLQ for inspection.
126
+
127
+ ### Error classification
128
+
129
+ Return value from the handler decides routing:
130
+
131
+ | Return | Result |
132
+ |--------|--------|
133
+ | `return true` | ACK — success, or permanent failure that retrying won't fix |
134
+ | `return false` | Retry with backoff |
135
+ | `throw` | Retry, then DLQ after max retries |
136
+
137
+ ### Scheduled jobs
138
+
139
+ Add an entry to the `jobs` array in `src/scheduler.ts`:
140
+
141
+ ```ts
142
+ const jobs: JobConfig[] = [
143
+ { name: 'nightly-sync', queue: 'sync-accounts', interval: '60-minutes',
144
+ payload: { task: 'nightly-sync' } },
145
+ ];
146
+ ```
147
+
148
+ Then configure your external scheduler:
149
+
150
+ ```bash
151
+ # Run all jobs tagged 60-minutes
152
+ npm run scheduler -- run-jobs --interval 60-minutes
153
+
154
+ # Run a specific job on demand
155
+ npm run scheduler -- run-jobs --job nightly-sync
156
+
157
+ # Publish an ad-hoc message
158
+ npm run scheduler -- publish --queue sync-accounts --task manual-run
159
+ ```
160
+
161
+ ### Manual ACK
162
+
163
+ For batch commits or transaction coordination, opt into manual ACK:
164
+
165
+ ```ts
166
+ await services.messageQueue.listen('batch-job', async (msg, ack, nack) => {
167
+ try {
168
+ await processBatch(msg);
169
+ ack();
170
+ } catch {
171
+ nack();
172
+ }
173
+ }, { manualAck: true });
174
+ ```
175
+
176
+ First call to `ack()` or `nack()` wins — subsequent calls are silent no-ops.
177
+
178
+ See `reference/background-jobs.ref.md` in your scaffolded project for the full topology diagram, connection lifecycle, and Heroku deployment guide.
179
+
180
+ ## Added by
181
+
182
+ Not included by default. Add to an existing project with:
183
+
184
+ ```bash
185
+ boop add background-jobs
186
+ ```
package/capability.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "application",
5
5
  "package": "@boopkit/cap-background-jobs",
6
6
  "requires": ["services"],
7
- "dependencies": ["amqplib@^0.10", "minimist@^1.2"],
7
+ "dependencies": ["amqplib@^0.10", "minimist@^1.2", "@boopkit/logger", "winston@^3"],
8
8
  "devDependencies": ["@types/amqplib@^0.10", "@types/minimist@^1.2"],
9
9
  "env": [
10
10
  { "name": "CLOUDAMQP_URL", "description": "CloudAMQP connection URL (amqp://...)", "required": "boot" },
@@ -42,6 +42,6 @@ interface ListenOpts {
42
42
  * or throws without settling → retry/DLQ after max retries.
43
43
  */
44
44
  declare function listen(queue: string, handler: (...args: any[]) => Promise<any>, opts?: ListenOpts): Promise<void>;
45
- /** Close all tracked connections (publish + listeners). */
45
+ /** Close all tracked connections (publish + listener). */
46
46
  declare function close(): Promise<void>;
47
47
  //# sourceMappingURL=message-queue.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.service.d.ts","sourceRoot":"","sources":["../src/message-queue.service.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAmBrE,QAAA,MAAM,mBAAmB;;;;;;CAMxB,CAAC;AAEF,eAAe,mBAAmB,CAAC;AAEnC;;;;GAIG;AACH,iBAAS,IAAI,IAAI,IAAI,CAQpB;AAED;;;;GAIG;AACH,iBAAe,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BxE;AAED,4BAA4B;AAC5B,UAAU,UAAU;IAClB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AAEH,iBAAe,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EhH;AAED,2DAA2D;AAC3D,iBAAe,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAwBpC"}
1
+ {"version":3,"file":"message-queue.service.d.ts","sourceRoot":"","sources":["../src/message-queue.service.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAyBrE,QAAA,MAAM,mBAAmB;;;;;;CAMxB,CAAC;AAEF,eAAe,mBAAmB,CAAC;AAEnC;;;;GAIG;AACH,iBAAS,IAAI,IAAI,IAAI,CAQpB;AAED;;;;GAIG;AACH,iBAAe,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BxE;AAED,4BAA4B;AAC5B,UAAU,UAAU;IAClB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AAEH,iBAAe,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EhH;AAED,0DAA0D;AAC1D,iBAAe,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAqCpC"}
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const amqplib_1 = __importDefault(require("amqplib"));
8
+ const logger_1 = require("@boopkit/logger");
9
+ const logger = (0, logger_1.createLogger)('background-jobs');
8
10
  const BACKOFF_BASE_MS = 4000;
9
11
  const BACKOFF_MAX_MS = 60000;
10
12
  /** Read env lazily — package imports run before dotenv/app boot. */
@@ -15,6 +17,8 @@ const connections = [];
15
17
  /** Lazy-initialized publish connection and confirm channel. */
16
18
  let publishConnection = null;
17
19
  let publishChannel = null;
20
+ /** Lazy-initialized shared listener connection. */
21
+ let listenerConnection = null;
18
22
  const MessageQueueService = {
19
23
  name: 'message-queue',
20
24
  init,
@@ -58,7 +62,7 @@ async function publish(queue, payload) {
58
62
  return true;
59
63
  }
60
64
  catch (err) {
61
- console.error(`[message-queue] publish error on "${queue}":`, err);
65
+ logger.error(`publish error on "${queue}"`, { err });
62
66
  resetPublishConnection();
63
67
  return false;
64
68
  }
@@ -80,8 +84,7 @@ async function publish(queue, payload) {
80
84
  */
81
85
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
86
  async function listen(queue, handler, opts) {
83
- const connection = await amqplib_1.default.connect(process.env.CLOUDAMQP_URL);
84
- connections.push(connection);
87
+ const connection = await getListenerConnection();
85
88
  const channel = await connection.createChannel();
86
89
  const { mainQueue, retryQueue, failedQueue } = await assertTopology(channel, queue);
87
90
  if (opts?.prefetch != null) {
@@ -97,7 +100,7 @@ async function listen(queue, handler, opts) {
97
100
  }
98
101
  catch {
99
102
  // Poison message — ACK to prevent infinite redelivery
100
- console.error(`[message-queue] unparseable message on "${queue}", sending to DLQ`);
103
+ logger.error(`unparseable message on "${queue}", sending to DLQ`);
101
104
  channel.nack(raw, false, false);
102
105
  return;
103
106
  }
@@ -106,7 +109,7 @@ async function listen(queue, handler, opts) {
106
109
  let settled = false;
107
110
  const guardedAck = () => {
108
111
  if (settled) {
109
- console.warn(`[message-queue] duplicate ack on "${queue}" — ignored`);
112
+ logger.warn(`duplicate ack on "${queue}" — ignored`);
110
113
  return;
111
114
  }
112
115
  settled = true;
@@ -114,7 +117,7 @@ async function listen(queue, handler, opts) {
114
117
  };
115
118
  const guardedNack = async () => {
116
119
  if (settled) {
117
- console.warn(`[message-queue] duplicate nack on "${queue}" — ignored`);
120
+ logger.warn(`duplicate nack on "${queue}" — ignored`);
118
121
  return;
119
122
  }
120
123
  settled = true;
@@ -123,12 +126,12 @@ async function listen(queue, handler, opts) {
123
126
  try {
124
127
  await handler(parsed, guardedAck, guardedNack);
125
128
  if (!settled) {
126
- console.warn(`[message-queue] handler resolved without settling on "${queue}" — treating as failure`);
129
+ logger.warn(`handler resolved without settling on "${queue}" — treating as failure`);
127
130
  await retryOrDLQ(channel, raw, retryCount, retryQueue, failedQueue);
128
131
  }
129
132
  }
130
133
  catch (err) {
131
- console.error(`[message-queue] handler threw on "${queue}":`, err);
134
+ logger.error(`handler threw on "${queue}"`, { err });
132
135
  if (!settled) {
133
136
  await retryOrDLQ(channel, raw, retryCount, retryQueue, failedQueue);
134
137
  }
@@ -146,15 +149,15 @@ async function listen(queue, handler, opts) {
146
149
  }
147
150
  }
148
151
  catch (err) {
149
- console.error(`[message-queue] handler threw on "${queue}":`, err);
152
+ logger.error(`handler threw on "${queue}"`, { err });
150
153
  await retryOrDLQ(channel, raw, retryCount, retryQueue, failedQueue);
151
154
  }
152
155
  }
153
156
  }, { noAck: false });
154
157
  }
155
- /** Close all tracked connections (publish + listeners). */
158
+ /** Close all tracked connections (publish + listener). */
156
159
  async function close() {
157
- // Close the publish connection explicitly (resetPublishConnection is fire-and-forget)
160
+ // Close the publish connection explicitly
158
161
  if (publishConnection) {
159
162
  const conn = publishConnection;
160
163
  publishConnection = null;
@@ -169,6 +172,20 @@ async function close() {
169
172
  // Already closed — ignore
170
173
  }
171
174
  }
175
+ // Close the shared listener connection explicitly
176
+ if (listenerConnection) {
177
+ const conn = listenerConnection;
178
+ listenerConnection = null;
179
+ const idx = connections.indexOf(conn);
180
+ if (idx !== -1)
181
+ connections.splice(idx, 1);
182
+ try {
183
+ await conn.close();
184
+ }
185
+ catch {
186
+ // Already closed — ignore
187
+ }
188
+ }
172
189
  const closing = connections.map(async (conn) => {
173
190
  try {
174
191
  await conn.close();
@@ -187,6 +204,27 @@ function prefixedName(name) {
187
204
  const prefix = getQueuePrefix();
188
205
  return prefix ? `${prefix}/${name}` : name;
189
206
  }
207
+ /** Lazy-create or return the shared listener connection. */
208
+ async function getListenerConnection() {
209
+ if (listenerConnection)
210
+ return listenerConnection;
211
+ const conn = await amqplib_1.default.connect(process.env.CLOUDAMQP_URL);
212
+ connections.push(conn);
213
+ listenerConnection = conn;
214
+ conn.on('error', () => resetListenerConnection());
215
+ conn.on('close', () => resetListenerConnection());
216
+ return conn;
217
+ }
218
+ /** Clear cached listener connection so the next listen() call reconnects. */
219
+ function resetListenerConnection() {
220
+ if (listenerConnection) {
221
+ listenerConnection.close().catch(() => { });
222
+ const idx = connections.indexOf(listenerConnection);
223
+ if (idx !== -1)
224
+ connections.splice(idx, 1);
225
+ }
226
+ listenerConnection = null;
227
+ }
190
228
  /** Lazy-create or return the existing publish confirm channel. */
191
229
  async function getPublishChannel() {
192
230
  if (publishChannel)
@@ -262,7 +300,7 @@ function computeBackoff(retryCount) {
262
300
  async function retryOrDLQ(channel, raw, retryCount, retryQueue, failedQueue) {
263
301
  const maxRetries = getMaxRetries();
264
302
  if (retryCount >= maxRetries) {
265
- console.error(`[message-queue] max retries (${maxRetries}) exceeded, moving to DLQ: ${failedQueue}`);
303
+ logger.error(`[message-queue] max retries (${maxRetries}) exceeded, moving to DLQ: ${failedQueue}`);
266
304
  channel.publish('', failedQueue, raw.content, {
267
305
  persistent: true,
268
306
  headers: { ...raw.properties.headers, 'x-retry-count': retryCount },
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.service.js","sourceRoot":"","sources":["../src/message-queue.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"message-queue.service.js","sourceRoot":"","sources":["../src/message-queue.service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boopkit/cap-background-jobs",
3
- "version": "0.2.6",
3
+ "version": "0.3.1",
4
4
  "description": "Background job processing with RabbitMQ for boopkit-scaffolded projects",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,8 +20,10 @@
20
20
  "build": "tsc -p tsconfig.json"
21
21
  },
22
22
  "dependencies": {
23
+ "@boopkit/logger": "^0.3.0",
23
24
  "amqplib": "^0.10.0",
24
- "minimist": "^1.2.8"
25
+ "minimist": "^1.2.8",
26
+ "winston": "^3.17.0"
25
27
  },
26
28
  "devDependencies": {
27
29
  "@types/amqplib": "^0.10.0",
@@ -11,6 +11,10 @@
11
11
  * uncaught throw → retry, then DLQ after max retries
12
12
  */
13
13
 
14
+ import { createLogger } from '@boopkit/logger';
15
+
16
+ const logger = createLogger('background-jobs');
17
+
14
18
  /** Queue name constant — used by worker.ts to register this consumer. */
15
19
  export const QUEUE_NAME = 'example-job';
16
20
 
@@ -27,7 +31,7 @@ export async function onMessage(msg: unknown): Promise<boolean> {
27
31
  payload = validatePayload(msg);
28
32
  } catch (err) {
29
33
  // Poison message — bad shape, retrying won't help
30
- console.error('[example-job] invalid payload — ACKing to prevent retry loop', {
34
+ logger.error('invalid payload — ACKing to prevent retry loop', {
31
35
  error: (err as Error).message,
32
36
  });
33
37
  return true;
@@ -37,11 +41,11 @@ export async function onMessage(msg: unknown): Promise<boolean> {
37
41
  try {
38
42
  // Replace this with your actual service call, e.g.:
39
43
  // await services.myService.process(payload.task, payload.data);
40
- console.log('[example-job] processed:', payload.task);
44
+ logger.info(`processed: ${payload.task}`);
41
45
  return true;
42
46
  } catch (err) {
43
47
  // Transient error — retry with backoff
44
- console.error('[example-job] processing failed — retrying', {
48
+ logger.error('processing failed — retrying', {
45
49
  error: (err as Error).message,
46
50
  });
47
51
  return false;
@@ -1,8 +1,10 @@
1
1
  /** @boopkit/cap-background-jobs — Scheduler entry point for triggering background jobs. */
2
2
 
3
- import { loadServices } from '@services';
3
+ import { createLogger } from '@boopkit/logger';
4
+ // @ts-ignore - services scaffolded by cap-services
5
+ import { loadServices } from './services';
4
6
  import minimist from 'minimist';
5
- import MessageQueueService from './services/message-queue.service';
7
+ import { MessageQueueService } from '@boopkit/cap-background-jobs';
6
8
 
7
9
  interface JobConfig {
8
10
  /** Human-readable job name (used for --job filtering). */
@@ -33,6 +35,8 @@ const jobs: JobConfig[] = [
33
35
  },
34
36
  ];
35
37
 
38
+ const logger = createLogger('background-jobs');
39
+
36
40
  /**
37
41
  * Publish trigger messages for jobs matching the given filters.
38
42
  */
@@ -48,8 +52,8 @@ async function runJobs(
48
52
  selected = selected.filter((j) => j.name === opts.job);
49
53
  }
50
54
 
51
- console.log(
52
- `[scheduler] ${selected.length} job(s) selected` +
55
+ logger.info(
56
+ `${selected.length} job(s) selected` +
53
57
  (opts.interval ? ` for interval "${opts.interval}"` : '') +
54
58
  (opts.job ? ` matching job "${opts.job}"` : ''),
55
59
  );
@@ -57,14 +61,15 @@ async function runJobs(
57
61
  for (const job of selected) {
58
62
  const ok = await MessageQueueService.publish(job.queue, job.payload);
59
63
  if (ok) {
60
- console.log(`[scheduler] published to "${job.queue}": ${job.payload.task}`);
64
+ logger.info(`published to "${job.queue}": ${job.payload.task}`);
61
65
  } else {
62
- console.error(`[scheduler] failed to publish to "${job.queue}"`);
66
+ logger.error(`failed to publish to "${job.queue}"`);
63
67
  }
64
68
  }
65
69
  }
66
70
 
67
71
  function printUsage(): void {
72
+ // printUsage stays as console.log — it's CLI help text, not operational logging
68
73
  console.log(`Usage: npm run scheduler -- <command> [options]
69
74
 
70
75
  Commands:
@@ -101,9 +106,9 @@ async function main(args: string[], opts: Record<string, unknown>): Promise<void
101
106
  }
102
107
 
103
108
  case 'list': {
104
- console.log('[scheduler] registered jobs:');
109
+ logger.info('registered jobs:');
105
110
  for (const job of jobs) {
106
- console.log(` ${job.name} queue=${job.queue} interval=${job.interval}`);
111
+ logger.info(` ${job.name} queue=${job.queue} interval=${job.interval}`);
107
112
  }
108
113
  break;
109
114
  }
@@ -111,7 +116,7 @@ async function main(args: string[], opts: Record<string, unknown>): Promise<void
111
116
  case 'publish': {
112
117
  const queue = opts.queue as string | undefined;
113
118
  if (!queue) {
114
- console.error('[scheduler] --queue is required for publish command');
119
+ logger.error('--queue is required for publish command');
115
120
  process.exit(1);
116
121
  }
117
122
  const task = (opts.task as string) ?? 'cli';
@@ -120,22 +125,22 @@ async function main(args: string[], opts: Record<string, unknown>): Promise<void
120
125
  try {
121
126
  data = JSON.parse(opts.data as string);
122
127
  } catch {
123
- console.error('[scheduler] --data must be valid JSON');
128
+ logger.error('--data must be valid JSON');
124
129
  process.exit(1);
125
130
  }
126
131
  }
127
132
  const ok = await MessageQueueService.publish(queue, { task, data });
128
133
  if (ok) {
129
- console.log(`[scheduler] published to "${queue}": ${task}`);
134
+ logger.info(`published to "${queue}": ${task}`);
130
135
  } else {
131
- console.error(`[scheduler] failed to publish to "${queue}"`);
136
+ logger.error(`failed to publish to "${queue}"`);
132
137
  process.exit(1);
133
138
  }
134
139
  break;
135
140
  }
136
141
 
137
142
  default:
138
- console.error(`[scheduler] unknown command: ${command}`);
143
+ logger.error(`unknown command: ${command}`);
139
144
  printUsage();
140
145
  process.exit(1);
141
146
  }
@@ -146,6 +151,6 @@ async function main(args: string[], opts: Record<string, unknown>): Promise<void
146
151
 
147
152
  const argv = minimist(process.argv.slice(2));
148
153
  main(argv._, argv).catch((err) => {
149
- console.error('[scheduler] failed:', err);
154
+ logger.error('failed', { err });
150
155
  process.exit(1);
151
156
  });
@@ -0,0 +1,4 @@
1
+ // Dummy services index for scaffold — replaced by cap-services when scaffolded
2
+ export function loadServices(): Promise<void> {
3
+ return Promise.resolve();
4
+ }
@@ -1,9 +1,13 @@
1
1
  /** @boopkit/cap-background-jobs — Worker entry point for background job processing. */
2
2
 
3
- import { loadServices } from '@services';
4
- import MessageQueueService from './services/message-queue.service';
3
+ import { createLogger } from '@boopkit/logger';
4
+ // @ts-ignore - services scaffolded by cap-services
5
+ import { loadServices } from './services';
6
+ import { MessageQueueService } from '@boopkit/cap-background-jobs';
5
7
  import * as exampleJobController from './controllers/example-job.controller';
6
8
 
9
+ const logger = createLogger('background-jobs');
10
+
7
11
  // Static consumer registration — add new {queue, handler} entries here
8
12
  const consumers = [
9
13
  { queue: exampleJobController.QUEUE_NAME, handler: exampleJobController.onMessage },
@@ -19,29 +23,29 @@ async function boot() {
19
23
  await MessageQueueService.listen(consumer.queue, consumer.handler);
20
24
  }
21
25
 
22
- console.log(`[worker] listening on ${consumers.length} queue(s)`);
26
+ logger.info(`listening on ${consumers.length} queue(s)`);
23
27
  }
24
28
 
25
29
  async function shutdown(signal: string) {
26
30
  if (shuttingDown) return;
27
31
  shuttingDown = true;
28
32
 
29
- console.log(`[worker] ${signal} received — starting graceful shutdown`);
33
+ logger.info(`${signal} received — starting graceful shutdown`);
30
34
 
31
35
  // Drain in-flight messages with timeout
32
36
  const drainTimer = setTimeout(() => {
33
- console.error('[worker] drain timeout exceeded — forcing exit');
37
+ logger.error('drain timeout exceeded — forcing exit');
34
38
  process.exit(1);
35
39
  }, DRAIN_TIMEOUT_MS);
36
40
 
37
41
  try {
38
42
  await MessageQueueService.close();
39
43
  clearTimeout(drainTimer);
40
- console.log('[worker] shutdown complete');
44
+ logger.info('shutdown complete');
41
45
  process.exit(0);
42
46
  } catch (err) {
43
47
  clearTimeout(drainTimer);
44
- console.error('[worker] error during shutdown:', err);
48
+ logger.error('error during shutdown', { err });
45
49
  process.exit(1);
46
50
  }
47
51
  }
@@ -50,7 +54,7 @@ process.on('SIGINT', () => shutdown('SIGINT'));
50
54
  process.on('SIGTERM', () => shutdown('SIGTERM'));
51
55
 
52
56
  boot().catch((err) => {
53
- console.error('[worker] boot failed:', err);
57
+ logger.error('boot failed', { err });
54
58
  process.exit(1);
55
59
  });
56
60