unified-notification-core 0.1.2 → 0.1.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.6
4
+
5
+ - Add CommonJS `require` export conditions for the package root and schema
6
+ entrypoints so bundled CommonJS consumers can resolve UNC without package
7
+ manager patches.
8
+ - Add a built-package CommonJS export smoke test before packing.
9
+
10
+ ## 0.1.5
11
+
12
+ - Add provider-agnostic `channelPolicies` with durable per-channel rate windows
13
+ and circuit-breaker cooldowns backed by the new `unc_dispatch_state` schema
14
+ table.
15
+ - Add `NotificationDeliveryError({ retryAfterMs })` so adapters can pass
16
+ provider throttle hints without coupling UNC to provider SDKs; retry-after
17
+ schedules the delivery retry and opens a shared channel cooldown.
18
+ - Report `dispatchUntilIdle()` stop reason `rate-limited` with `deferredUntil`
19
+ when due rows exist but channel policy defers claiming.
20
+ - Keep channel-policy deferrals attempt-free: deferred rows remain pending or
21
+ retrying and other channels can still dispatch in the same worker call.
22
+
23
+ ## 0.1.4
24
+
25
+ - Add `dispatchUntilIdle()` as an explicit bounded drain helper with stable
26
+ worker identity, batch/deadline limits, and high-failure stop defaults so
27
+ application workers do not need to hand-roll dispatch loops.
28
+ - Batch-finalize built-in `in_app` deliveries after claim instead of invoking
29
+ per-row provider-style finalization.
30
+ - Run test files serially to avoid PGlite setup contention in the default
31
+ package check.
32
+
33
+ ## 0.1.3
34
+
35
+ - Dispatch every due delivery created or reused by `publishAndDispatch()` by
36
+ draining its own publication in bounded delivery-id claim pages. The public
37
+ `dispatchDue()` worker limit remains capped per call.
38
+
3
39
  ## 0.1.2
4
40
 
5
41
  - Validate runtime `preferencePolicy` values and dispatch limits before any
package/README.md CHANGED
@@ -60,6 +60,9 @@ npm install unified-notification-core drizzle-orm
60
60
  The package supports Drizzle `0.45.x` with PostgreSQL-compatible drivers,
61
61
  including `node-postgres`, `postgres.js`, and PGlite.
62
62
 
63
+ Both public entrypoints support ESM `import` and CommonJS `require`:
64
+ `unified-notification-core` and `unified-notification-core/schema`.
65
+
63
66
  ## Add the schema
64
67
 
65
68
  Export the UNC tables from the schema entrypoint already read by Drizzle Kit:
@@ -74,6 +77,7 @@ export const {
74
77
  notifications,
75
78
  notificationDeliveries,
76
79
  notificationPreferences,
80
+ notificationDispatchState,
77
81
  } = notificationSchema;
78
82
  ```
79
83
 
@@ -106,6 +110,13 @@ schema diff through the application's normal reviewed migration workflow. UNC
106
110
  does not create the index at runtime; correctness is preserved before the index
107
111
  is applied, but legacy fallback reads can be slower.
108
112
 
113
+ Upgrading to `0.1.5` adds the `unc_dispatch_state` table, or the same suffix
114
+ under a custom prefix. That table stores provider-agnostic channel rate-limit
115
+ windows and cooldowns. Generate and apply the schema diff through the
116
+ application's normal reviewed migration workflow before enabling
117
+ `channelPolicies` or adapter `retryAfterMs` hints. UNC never creates the table
118
+ at runtime.
119
+
109
120
  ## Define channels
110
121
 
111
122
  Channel names are plain text, not a PostgreSQL enum. Adding a future channel
@@ -148,7 +159,10 @@ const result = await notificationCore.publishAndDispatch({
148
159
  ```
149
160
 
150
161
  `publish()` only persists. `publishAndDispatch()` persists and immediately
151
- attempts due deliveries. Both use the same durable outbox records.
162
+ attempts every due delivery from that publication. Internally it drains large
163
+ publications in bounded delivery-id claim pages, so broadcasts above 1,000
164
+ deliveries are not left pending just because a single claim wave is capped. Both
165
+ methods use the same durable outbox records.
152
166
 
153
167
  Publication validates the complete JSON payload before opening its transaction.
154
168
  `data`, channel-specific values, and other persisted payload properties must be
@@ -190,25 +204,38 @@ recipients preserve first-seen input order and channels remain unique.
190
204
 
191
205
  A core constructed with a Drizzle `PgTransaction` is publish-only. This lets an
192
206
  application commit its own row and `publish()` atomically. Do not call
193
- `publishAndDispatch()` or `dispatchDue()` on that core: both fail before writing
194
- or invoking an adapter. After the outer transaction commits, dispatch with a
195
- core constructed from the top-level `PgDatabase`.
207
+ `publishAndDispatch()`, `dispatchUntilIdle()`, or `dispatchDue()` on that core:
208
+ all fail before writing or invoking an adapter. After the outer transaction
209
+ commits, dispatch with a core constructed from the top-level `PgDatabase`.
196
210
 
197
- For scheduled delivery or retries, call `dispatchDue()` from infrastructure the
198
- application already owns:
211
+ For scheduled delivery, retries, or queue-style workers, call
212
+ `dispatchUntilIdle()` from infrastructure the application already owns:
199
213
 
200
214
  ```ts
201
- await notificationCore.dispatchDue({
215
+ const result = await notificationCore.dispatchUntilIdle({
202
216
  workerId: process.env.HOSTNAME,
203
217
  limit: 100,
204
218
  concurrency: 10,
219
+ maxBatches: 25,
220
+ deadlineMs: 30_000,
205
221
  });
206
222
  ```
207
223
 
208
224
  `dispatchDue()` accepts `limit` from 1 through 1000 and `concurrency` from 1
209
- through 100. `publishAndDispatch()` accepts the same concurrency range. Runtime
210
- values must be finite positive integers; invalid values fail before publishing,
211
- claiming, or calling a provider.
225
+ through 100; the limit is a per-call worker claim cap. `dispatchUntilIdle()`
226
+ uses the same limit and concurrency boundaries, keeps one stable worker id for
227
+ its drain, stops when no due rows remain, and also stops on `maxBatches`,
228
+ `deadlineMs`, a high-failure batch, or a channel policy deferral. By default a
229
+ batch stops the drain when at least 80% of attempted deliveries fail or
230
+ schedule a retry, which prevents a broken provider from being hammered in a
231
+ tight loop. When due rows exist but a channel rate limit or cooldown blocks
232
+ claiming them, the stop reason is `rate-limited` and `deferredUntil` reports
233
+ the earliest known channel wake-up time. `publishAndDispatch()` accepts the
234
+ same concurrency range and uses capped internal claim pages until every due
235
+ delivery from its own publication has been attempted once, unless a configured
236
+ channel policy defers some rows. Runtime values must be finite positive
237
+ integers; invalid values fail before publishing, claiming, or calling a
238
+ provider.
212
239
 
213
240
  This can run from a cron handler, queue consumer, scheduled function, or an
214
241
  application-owned interval. The package starts no timer and exposes no port.
@@ -218,6 +245,58 @@ Concurrent workers claim rows with `FOR UPDATE SKIP LOCKED`; abandoned
218
245
  a separate claim token, so two attempts from the same worker cannot finalize
219
246
  each other's rows.
220
247
 
248
+ ## Channel dispatch policies
249
+
250
+ UNC can enforce provider-agnostic channel policy without knowing the provider
251
+ SDK. Configure static channel rate windows and circuit-breaker cooldowns when
252
+ creating the core:
253
+
254
+ ```ts
255
+ const notificationCore = createNotificationCore<AppChannel>({
256
+ db,
257
+ adapters,
258
+ channelPolicies: {
259
+ sms: {
260
+ rateLimit: { max: 30, windowMs: 60_000 },
261
+ circuitBreaker: {
262
+ failureRatio: 0.8,
263
+ minAttempts: 20,
264
+ cooldownMs: 5 * 60_000,
265
+ },
266
+ },
267
+ email: {
268
+ rateLimit: { max: 500, windowMs: 60_000 },
269
+ },
270
+ },
271
+ });
272
+ ```
273
+
274
+ Rate limits are durable per channel and shared by concurrent workers through
275
+ the `unc_dispatch_state` table. A row that is deferred by channel policy is not
276
+ claimed and does not consume an attempt. Other channels keep dispatching in the
277
+ same worker call.
278
+
279
+ Circuit breakers are also channel-scoped and durable. After a batch for one
280
+ channel reaches the configured failure ratio and minimum attempted deliveries,
281
+ UNC opens that channel's cooldown. Claimed rows still finalize normally as
282
+ `sent`, `retrying`, or `failed`; the cooldown only prevents another immediate
283
+ wave from hammering the same provider boundary.
284
+
285
+ Adapters can also return provider throttle information without coupling UNC to
286
+ the provider:
287
+
288
+ ```ts
289
+ throw new NotificationDeliveryError("rate_limited", "Provider throttled", {
290
+ retryAfterMs: 120_000,
291
+ });
292
+ ```
293
+
294
+ `retryAfterMs` schedules the failed delivery's next attempt and opens the same
295
+ durable channel cooldown for fresh due rows. It is a finite non-negative number
296
+ no greater than 30 days. It does not replace provider-specific credentials,
297
+ contact lookup, account management, or webhooks; those remain in the adapter and
298
+ application.
299
+
221
300
  ## Preferences
222
301
 
223
302
  Preferences are overrides, not a copied matrix. This keeps storage small when
@@ -357,10 +436,11 @@ throw new NotificationDeliveryError(
357
436
 
358
437
  `NotificationDeliveryError` accepts omitted options or a plain/null-prototype
359
438
  options record. If `retryable` is present it must be an exact boolean; only
360
- omission defaults it to `true`. The code is trimmed, non-empty, PostgreSQL-safe,
361
- and at most 191 characters. The message is non-empty, PostgreSQL-safe, and at
362
- most 10,000 characters. Options are descriptor-captured once before the Error
363
- is constructed.
439
+ omission defaults it to `true`. If `retryAfterMs` is present it must be a finite
440
+ non-negative number no greater than 30 days. The code is trimmed, non-empty,
441
+ PostgreSQL-safe, and at most 191 characters. The message is non-empty,
442
+ PostgreSQL-safe, and at most 10,000 characters. Options are descriptor-captured
443
+ once before the Error is constructed.
364
444
 
365
445
  Unknown errors are retryable. The default backoff is 1 minute, 5 minutes,
366
446
  15 minutes, 1 hour, then 6 hours. Configure `retryDelayMs` and
@@ -451,6 +531,8 @@ and its `DispatchResult` reports the durable state it observed.
451
531
  - No background timers or service runtime.
452
532
  - No assumption that recipient ids are UUIDs.
453
533
  - No assumption that every notification is in-app.
534
+ - Provider-agnostic channel rate/cooldown state is stored in UNC tables, not in
535
+ process memory.
454
536
  - Provider callbacks are invoked only by a top-level-database core, after the
455
537
  claim transaction commits.
456
538
  - Preferences disabled at publication are recorded as `skipped` deliveries for
package/dist/core.d.ts CHANGED
@@ -2,6 +2,35 @@ import { type PgDatabase } from "drizzle-orm/pg-core";
2
2
  import { type NotificationSchema } from "./schema.js";
3
3
  import { PREFERENCE_WILDCARD, type DeliveryAdapters, type DispatchResult, type NotificationLogger, type InboxCursor, type InboxPage, type JsonObject, type PreferenceDefaults, type PreferenceOverride, type PublishInput, type PublishedNotification, type ResolvedPreference } from "./types.js";
4
4
  type AnyPgDatabase = PgDatabase<any, any, any>;
5
+ export type DispatchUntilIdleOptions = {
6
+ limit?: number;
7
+ workerId?: string;
8
+ concurrency?: number;
9
+ maxBatches?: number;
10
+ deadlineMs?: number;
11
+ stopOnFailureRatio?: number;
12
+ stopOnFailureCount?: number;
13
+ };
14
+ export type DispatchUntilIdleStopReason = "idle" | "maxBatches" | "deadline" | "failure-threshold" | "rate-limited";
15
+ export type DispatchUntilIdleResult<TChannel extends string = string> = {
16
+ batches: number;
17
+ reason: DispatchUntilIdleStopReason;
18
+ dispatched: Array<DispatchResult<TChannel>>;
19
+ deferredUntil?: Date;
20
+ };
21
+ export type ChannelRateLimitPolicy = {
22
+ max: number;
23
+ windowMs: number;
24
+ };
25
+ export type ChannelCircuitBreakerPolicy = {
26
+ failureRatio?: number;
27
+ minAttempts?: number;
28
+ cooldownMs?: number;
29
+ };
30
+ export type ChannelDispatchPolicy = {
31
+ rateLimit?: ChannelRateLimitPolicy;
32
+ circuitBreaker?: ChannelCircuitBreakerPolicy;
33
+ };
5
34
  export type NotificationCoreConfig<TChannel extends string, TData extends JsonObject = JsonObject> = {
6
35
  db: AnyPgDatabase;
7
36
  schema?: NotificationSchema;
@@ -10,6 +39,7 @@ export type NotificationCoreConfig<TChannel extends string, TData extends JsonOb
10
39
  preferenceDefaults?: PreferenceDefaults<TChannel>;
11
40
  defaultPreferenceEnabled?: boolean;
12
41
  defaultMaxAttempts?: number;
42
+ channelPolicies?: Partial<Record<TChannel, ChannelDispatchPolicy>>;
13
43
  retryDelayMs?: (attempt: number, error: unknown) => number | Promise<number>;
14
44
  lockTimeoutMs?: number;
15
45
  now?: () => Date;
@@ -31,6 +61,7 @@ export declare class UnifiedNotificationCore<TChannel extends string, TData exte
31
61
  workerId?: string;
32
62
  concurrency?: number;
33
63
  }): Promise<Array<DispatchResult<TChannel>>>;
64
+ dispatchUntilIdle(options?: DispatchUntilIdleOptions): Promise<DispatchUntilIdleResult<TChannel>>;
34
65
  setPreference(preference: PreferenceOverride<TChannel>): Promise<void>;
35
66
  setPreferences(recipientId: string, preferences: ReadonlyArray<Omit<PreferenceOverride<TChannel>, "recipientId">>): Promise<void>;
36
67
  clearPreference(input: {
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}