@chidchanun/bcp 0.2.8 → 0.2.10

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 CHANGED
@@ -1,14 +1,14 @@
1
1
  # BCP Framework
2
2
 
3
- BCP Framework is a React full-stack framework for file-based routing, SSR, SPA navigation, server data loading, guarded application flows, API routes, authentication, authorization, database access, background jobs, observability, validation, uploads, storage and standalone Node.js production deployment.
3
+ BCP Framework is a React full-stack framework for file-based routing, SSR, SPA navigation, server data loading, guarded application flows, API routes, authentication, authorization, database access, background jobs, recurring scheduling, observability, validation, uploads, storage and standalone Node.js production deployment.
4
4
 
5
- > **Development target:** `0.2.8Background Jobs Platform`
5
+ > **Development target:** `0.2.10Durable Jobs Platform`
6
6
  >
7
- > `0.2.8` is an unreleased development target until local validation, RC checks, tagging and npm publication complete.
7
+ > `0.2.10` is an unreleased development target until local validation, RC checks, tagging and npm publication complete.
8
8
 
9
9
  ## 0.2 platform
10
10
 
11
- `0.2.0` established the Framework Platform baseline, `0.2.1` added the Documentation Platform, `0.2.2` added Configuration & Environment v2, `0.2.3` added Database Platform v2, `0.2.4` added Application Packaging, `0.2.5` added Authentication Platform v2, `0.2.6` added Authorization & Security v2, `0.2.7` added Observability Platform v2, and `0.2.8` adds a provider-neutral background-job queue/worker contract with delayed work, retry/backoff, cancellation and process-local reference storage.
11
+ `0.2.0` established the Framework Platform baseline, `0.2.1` added the Documentation Platform, `0.2.2` added Configuration & Environment v2, `0.2.3` added Database Platform v2, `0.2.4` added Application Packaging, `0.2.5` added Authentication Platform v2, `0.2.6` added Authorization & Security v2, `0.2.7` added Observability Platform v2, `0.2.8` added Background Jobs Platform, `0.2.9` added recurring scheduling, and `0.2.10` adds durable worker leases, DLQ maintenance and Redis-compatible queue/scheduler adapters.
12
12
 
13
13
  Machine-readable platform contracts:
14
14
 
@@ -35,7 +35,9 @@ docs/api-manifest.json
35
35
  | Authorization | Auth/guest/role/permission route guards, flat permissions and resource-aware policies |
36
36
  | Request security | Same-origin validation and signed CSRF tokens for unsafe mutations |
37
37
  | Middleware | Middleware System v2 with onion execution |
38
- | Background jobs | Adapter contract, in-memory queue, delayed jobs, retries/backoff, cancellation and concurrent workers |
38
+ | Background jobs | Delayed jobs, retries/backoff, cancellation, concurrent workers, visibility leases, heartbeat, stale recovery and DLQ |
39
+ | Scheduling | Recurring interval jobs, UTC cron, schedule-store leases and deterministic scheduled run IDs |
40
+ | Durable jobs | Redis-compatible queue/schedule adapters, retention cleanup, requeue and queue statistics |
39
41
  | Observability | Structured logs, counters/gauges/histograms, Prometheus output, request metrics and health/readiness checks |
40
42
  | Validation | Typed validators and structured validation errors |
41
43
  | Error handling | HTTP error helpers and consistent error responses |
@@ -130,8 +132,6 @@ Read more:
130
132
 
131
133
  ## Database Platform v2 — 0.2.3
132
134
 
133
- Application code uses one server-only database entrypoint across supported SQL providers:
134
-
135
135
  ```ts
136
136
  import {
137
137
  db,
@@ -147,16 +147,6 @@ postgresql
147
147
  sqlite
148
148
  ```
149
149
 
150
- Lifecycle control:
151
-
152
- ```ts
153
- await db.connect();
154
-
155
- // application work
156
-
157
- await db.disconnect();
158
- ```
159
-
160
150
  Migration CLI:
161
151
 
162
152
  ```bash
@@ -179,23 +169,10 @@ Create a fresh production build and deployment package:
179
169
  bcp package
180
170
  ```
181
171
 
182
- Output:
172
+ Output is written under:
183
173
 
184
174
  ```text
185
175
  .bcp-framework/package/
186
- ├─ client/
187
- ├─ server/
188
- │ └─ server.mjs
189
- ├─ public/ # when present
190
- ├─ manifest.json
191
- ├─ package.json
192
- ├─ package-lock.json # when a safe npm v3 production lock can be derived
193
- ├─ bcp.package.json
194
- ├─ bcp.deployment.json
195
- ├─ bcp.env.json
196
- ├─ Dockerfile
197
- ├─ .dockerignore
198
- └─ README.md
199
176
  ```
200
177
 
201
178
  Read more:
@@ -205,35 +182,17 @@ Read more:
205
182
 
206
183
  ## Authentication Platform v2 — 0.2.5
207
184
 
208
- Stateless signed JWT-cookie authentication remains supported:
209
-
210
185
  ```ts
211
186
  import {
212
187
  auth,
213
- login,
214
- logout,
215
- } from "bcp/auth";
216
- ```
217
-
218
- Applications that need centralized revocation can add a server-side session store:
219
-
220
- ```ts
221
- import {
222
188
  createAuth,
223
189
  createMemoryAuthSessionStore,
190
+ login,
191
+ logout,
224
192
  } from "bcp/auth";
225
-
226
- const sessionStore =
227
- createMemoryAuthSessionStore();
228
-
229
- export const appAuth =
230
- createAuth({
231
- store: sessionStore,
232
- idleTimeout: 60 * 30,
233
- });
234
193
  ```
235
194
 
236
- With a store configured, authentication requires both a valid signed JWT cookie and an active `sid` record. The built-in memory store is intended for development/tests; production multi-instance deployments should implement `AuthSessionStore` with shared storage.
195
+ Stateless signed JWT-cookie authentication remains supported. Applications that need centralized revocation can configure an `AuthSessionStore`.
237
196
 
238
197
  Read more:
239
198
 
@@ -243,55 +202,12 @@ Read more:
243
202
 
244
203
  ## Authorization & Security v2 — 0.2.6
245
204
 
246
- Use flat permissions directly from `bcp/auth`:
247
-
248
205
  ```ts
249
206
  import {
207
+ authorize,
250
208
  hasPermission,
251
209
  requirePermission,
252
210
  } from "bcp/auth";
253
-
254
- hasPermission(
255
- user,
256
- "users.read"
257
- );
258
-
259
- await requirePermission(
260
- [
261
- "users.read",
262
- "users.write",
263
- ],
264
- {
265
- match: "all",
266
- }
267
- );
268
- ```
269
-
270
- Resource-aware policies:
271
-
272
- ```ts
273
- import {
274
- authorize,
275
- defineAuthorizationPolicy,
276
- } from "bcp/auth";
277
-
278
- const updateProject =
279
- defineAuthorizationPolicy(
280
- ({
281
- user,
282
- resource,
283
- }) =>
284
- resource.ownerId ===
285
- user.id
286
- );
287
-
288
- await authorize(
289
- updateProject,
290
- {
291
- user,
292
- resource: project,
293
- }
294
- );
295
211
  ```
296
212
 
297
213
  Request-security helpers are exposed from `bcp/server`:
@@ -308,56 +224,18 @@ Read more: [Authorization & Security v2](docs/authorization-security.md)
308
224
 
309
225
  ## Observability Platform v2 — 0.2.7
310
226
 
311
- Create one application metrics registry:
312
-
313
227
  ```ts
314
228
  import {
229
+ createHealthRegistry,
315
230
  createMetricsRegistry,
316
- } from "bcp/observability";
317
-
318
- export const metrics =
319
- createMetricsRegistry();
320
- ```
321
-
322
- Supported metric types:
323
-
324
- ```text
325
- counter
326
- gauge
327
- histogram
328
- ```
329
-
330
- Expose Prometheus-compatible text:
331
-
332
- ```ts
333
- import {
334
231
  createMetricsResponse,
335
232
  } from "bcp/observability";
336
-
337
- export function GET() {
338
- return createMetricsResponse(
339
- metrics
340
- );
341
- }
342
- ```
343
-
344
- Health/readiness registry:
345
-
346
- ```ts
347
- import {
348
- createHealthRegistry,
349
- } from "bcp/observability";
350
-
351
- export const health =
352
- createHealthRegistry();
353
233
  ```
354
234
 
355
235
  Read more: [Observability Platform v2](docs/observability.md)
356
236
 
357
237
  ## Background Jobs Platform — 0.2.8
358
238
 
359
- Create a server-side queue:
360
-
361
239
  ```ts
362
240
  import {
363
241
  createJobQueue,
@@ -367,7 +245,7 @@ export const jobs =
367
245
  createJobQueue();
368
246
  ```
369
247
 
370
- Register a handler:
248
+ Register work:
371
249
 
372
250
  ```ts
373
251
  jobs.register<{
@@ -382,7 +260,7 @@ jobs.register<{
382
260
  );
383
261
  ```
384
262
 
385
- Enqueue immediately or with a delay:
263
+ Enqueue work:
386
264
 
387
265
  ```ts
388
266
  await jobs.enqueue(
@@ -397,24 +275,153 @@ await jobs.enqueue(
397
275
  );
398
276
  ```
399
277
 
400
- Start concurrent workers:
278
+ Read more: [Background Jobs Platform](docs/background-jobs.md)
279
+
280
+ ## Job Scheduling Platform — 0.2.9
281
+
282
+ ```ts
283
+ import {
284
+ createJobScheduler,
285
+ } from "bcp/jobs";
286
+
287
+ export const scheduler =
288
+ createJobScheduler({
289
+ queue: jobs,
290
+ });
291
+ ```
292
+
293
+ Interval schedule:
294
+
295
+ ```ts
296
+ await scheduler.schedule(
297
+ "cache.cleanup",
298
+ {},
299
+ {
300
+ id: "cache-cleanup",
301
+ everyMs: 5 * 60 * 1000,
302
+ }
303
+ );
304
+ ```
305
+
306
+ UTC cron schedule:
307
+
308
+ ```ts
309
+ await scheduler.schedule(
310
+ "report.weekday",
311
+ {},
312
+ {
313
+ cron: "30 9 * * 1-5",
314
+ }
315
+ );
316
+ ```
317
+
318
+ Read more: [Job Scheduling Platform](docs/job-scheduling.md)
319
+
320
+ ## Durable Jobs Platform — 0.2.10
321
+
322
+ Workers now support visibility leases, heartbeat renewal and stale-running recovery when the configured adapter implements those capabilities:
401
323
 
402
324
  ```ts
403
325
  const worker =
404
326
  jobs.startWorker({
327
+ workerId: "email-worker",
405
328
  concurrency: 4,
329
+ visibilityTimeoutMs: 30_000,
330
+ heartbeatIntervalMs: 10_000,
406
331
  pollIntervalMs: 250,
407
332
  });
333
+ ```
334
+
335
+ Retry-exhausted jobs can be inspected and requeued:
336
+
337
+ ```ts
338
+ const failed =
339
+ await jobs.deadLetters();
340
+
341
+ await jobs.requeueDeadLetter(
342
+ failed[0].id,
343
+ {
344
+ delayMs: 5_000,
345
+ resetAttempts: true,
346
+ }
347
+ );
348
+ ```
349
+
350
+ Operational helpers:
351
+
352
+ ```ts
353
+ await jobs.recoverStale({
354
+ limit: 100,
355
+ });
356
+
357
+ const stats =
358
+ await jobs.stats();
359
+
360
+ await jobs.cleanup({
361
+ before:
362
+ Date.now() -
363
+ 7 * 24 * 60 * 60 * 1000,
364
+ });
365
+ ```
366
+
367
+ ### Redis-compatible durable queue
368
+
369
+ BCP does not install a Redis client library. Supply an application-owned client that implements:
370
+
371
+ ```ts
372
+ interface RedisCommandClient {
373
+ sendCommand(
374
+ command: string[]
375
+ ): Promise<unknown>;
376
+ }
377
+ ```
378
+
379
+ Then create the adapters:
380
+
381
+ ```ts
382
+ import {
383
+ createJobQueue,
384
+ createJobScheduler,
385
+ createRedisJobQueueAdapter,
386
+ createRedisJobScheduleStore,
387
+ } from "bcp/jobs";
388
+
389
+ const queueAdapter =
390
+ createRedisJobQueueAdapter({
391
+ client: redisCommandClient,
392
+ namespace: "my-app:{jobs}",
393
+ });
394
+
395
+ export const jobs =
396
+ createJobQueue({
397
+ adapter: queueAdapter,
398
+ });
399
+
400
+ const scheduleStore =
401
+ createRedisJobScheduleStore({
402
+ client: redisCommandClient,
403
+ namespace: "my-app:{jobs}",
404
+ });
408
405
 
409
- // graceful shutdown
410
- await worker.stop();
406
+ export const scheduler =
407
+ createJobScheduler({
408
+ queue: jobs,
409
+ store: scheduleStore,
410
+ ownerId: "scheduler-a",
411
+ });
411
412
  ```
412
413
 
413
- The default in-memory adapter is process-local and is intended for development/tests/prototypes. Durable multi-process deployments should implement `JobQueueAdapter` against shared infrastructure. Adapter `reserve()` must atomically claim work.
414
+ The Redis reference adapters use atomic Lua operations for reservations, visibility leases, heartbeat, stale recovery, DLQ requeue and scheduler leasing. The default namespace is `bcp:{jobs}` so keys share one Redis Cluster hash slot.
414
415
 
415
- Retry behavior is configurable with fixed or callback-based backoff. The default is capped exponential backoff. Jobs can also be cancelled and inspected with `get()` / `list()`.
416
+ A typical application may configure its Redis client with:
416
417
 
417
- Read more: [Background Jobs Platform](docs/background-jobs.md)
418
+ ```dotenv
419
+ REDIS_URL=redis://localhost:6379
420
+ ```
421
+
422
+ BCP does not read `REDIS_URL` automatically; connection creation, TLS/Cluster settings and credentials remain application-owned.
423
+
424
+ Read more: [Durable Jobs Platform](docs/durable-jobs.md)
418
425
 
419
426
  ## Public entrypoints
420
427
 
@@ -479,27 +486,21 @@ bcp generate middleware
479
486
  bcp generate migration create_users
480
487
  ```
481
488
 
482
- ## Application model
489
+ ## Production model
483
490
 
484
491
  ```text
485
- Browser
486
-
487
- Origin / CSRF / middleware / cache
488
-
489
- Authentication + authorization guard
490
-
491
- Loader / action / API route
492
-
493
- React SSR
494
-
495
- Hydration / SPA navigation
492
+ Browser / API clients
493
+
494
+ security + middleware + auth
495
+
496
+ loaders / actions / API routes
497
+
498
+ SSR / application responses
496
499
 
497
500
  Operational side channels:
498
- background jobs + structured logs + metrics + health/readiness
501
+ shared jobs + scheduler + structured logs + metrics + health/readiness
499
502
  ```
500
503
 
501
- ## Production build
502
-
503
504
  Raw standalone build:
504
505
 
505
506
  ```bash
@@ -513,8 +514,6 @@ Deployment package:
513
514
  bcp package
514
515
  ```
515
516
 
516
- Both current targets remain Node.js `standalone-node` applications.
517
-
518
517
  ## Documentation Platform
519
518
 
520
519
  The framework repository is the documentation source of truth.
@@ -541,7 +540,7 @@ npm run test:e2e
541
540
  npm run rc:check
542
541
  ```
543
542
 
544
- `0.2.8` adds Background Jobs Platform unit and prepared-package smoke checks covering delayed work, retries/backoff, cancellation, worker concurrency, server-only boundaries and the public `bcp/jobs` package surface.
543
+ `0.2.10` adds Durable Jobs Platform unit and prepared-package smoke checks covering visibility leases, heartbeat renewal, stale recovery, DLQ/requeue, retention/statistics, Redis queue/scheduler command contracts and the compiled `bcp/jobs` runtime.
545
544
 
546
545
  Do not tag or publish until the final release commit passes the complete RC sequence.
547
546
 
@@ -564,12 +563,14 @@ Do not tag or publish until the final release commit passes the complete RC sequ
564
563
  | `0.2.6` | Authorization & Security v2 |
565
564
  | `0.2.7` | Observability Platform v2 |
566
565
  | `0.2.8` | Background Jobs Platform |
566
+ | `0.2.9` | Job Scheduling Platform |
567
+ | `0.2.10` | Durable Jobs Platform |
567
568
 
568
569
  ## Roadmap
569
570
 
570
- `0.2.8Background Jobs Platform` establishes a provider-neutral queue/worker contract on top of the existing server runtime and lifecycle model.
571
+ `0.2.10Durable Jobs Platform` establishes shared production queue/scheduler adapters and worker recovery semantics while keeping the provider-neutral `bcp/jobs` contract.
571
572
 
572
- Later `0.2.x` work can add durable queue providers, recurring schedules, distributed leases or workflow orchestration without changing the base enqueue/worker contract. Native `.exe`, desktop and mobile compilation remain later roadmap work.
573
+ Later `0.2.x` work can add workflow orchestration, transactional outbox helpers or additional durable providers without changing the base queue/scheduler model. Native `.exe`, desktop and mobile compilation remain later roadmap work.
573
574
 
574
575
  ## License
575
576