@outbox-event-bus/postgres-drizzle-outbox 2.0.3 → 2.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.
package/README.md CHANGED
@@ -194,13 +194,13 @@ async function createUser(user: any) {
194
194
  return await db.transaction(async (tx) => {
195
195
  return await als.run(tx, async () => {
196
196
  await tx.insert(users).values(user);
197
-
197
+
198
198
  // Bus automatically uses transaction from ALS
199
- await bus.emit({
200
- type: 'user.created',
201
- payload: user
199
+ await bus.emit({
200
+ type: 'user.created',
201
+ payload: user
202
202
  });
203
-
203
+
204
204
  return user;
205
205
  });
206
206
  });
@@ -210,6 +210,40 @@ async function createUser(user: any) {
210
210
  > [!TIP]
211
211
  > AsyncLocalStorage eliminates the need to pass transactions through your call stack, improving code clarity.
212
212
 
213
+ ### 4. Typed Schema Support
214
+
215
+ `PostgresDrizzleOutbox` accepts a generic schema type parameter, so you can pass your typed Drizzle database instance directly without casting:
216
+
217
+ ```typescript
218
+ import { drizzle } from 'drizzle-orm/postgres-js';
219
+ import postgres from 'postgres';
220
+ import * as schema from './schema';
221
+ import { PostgresDrizzleOutbox } from '@outbox-event-bus/postgres-drizzle-outbox';
222
+
223
+ const client = postgres(process.env.DATABASE_URL!);
224
+ const db = drizzle(client, { schema });
225
+
226
+ // Schema type is inferred — no need to cast db
227
+ const outbox = new PostgresDrizzleOutbox({
228
+ db,
229
+ getTransaction: () => transactionManager.getCurrentTransaction()
230
+ });
231
+ ```
232
+
233
+ The `createDrizzleTransactionStorage` helper also supports typed schemas:
234
+
235
+ ```typescript
236
+ import { createDrizzleTransactionStorage } from '@outbox-event-bus/postgres-drizzle-outbox';
237
+ import * as schema from './schema';
238
+
239
+ const { withTransaction, getTransaction } = createDrizzleTransactionStorage<typeof schema>();
240
+
241
+ const outbox = new PostgresDrizzleOutbox({
242
+ db,
243
+ getTransaction
244
+ });
245
+ ```
246
+
213
247
  ## Custom Table Schemas
214
248
 
215
249
  The adapter supports custom table definitions, enabling:
package/dist/index.cjs CHANGED
@@ -148,18 +148,44 @@ var PostgresDrizzleOutbox = class {
148
148
 
149
149
  //#endregion
150
150
  //#region src/transaction-storage.ts
151
+ function createDrizzleTransactionStorage() {
152
+ const storage = new node_async_hooks.AsyncLocalStorage();
153
+ async function withTransaction(db, fn) {
154
+ return db.transaction(async (tx) => {
155
+ return storage.run(tx, () => fn(tx));
156
+ });
157
+ }
158
+ function getTransaction() {
159
+ return storage.getStore();
160
+ }
161
+ return {
162
+ storage,
163
+ withTransaction,
164
+ getTransaction
165
+ };
166
+ }
167
+ /**
168
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
169
+ */
151
170
  const drizzleTransactionStorage = new node_async_hooks.AsyncLocalStorage();
171
+ /**
172
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
173
+ */
152
174
  async function withDrizzleTransaction(db, fn) {
153
175
  return db.transaction(async (tx) => {
154
176
  return drizzleTransactionStorage.run(tx, () => fn(tx));
155
177
  });
156
178
  }
179
+ /**
180
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
181
+ */
157
182
  function getDrizzleTransaction() {
158
183
  return () => drizzleTransactionStorage.getStore();
159
184
  }
160
185
 
161
186
  //#endregion
162
187
  exports.PostgresDrizzleOutbox = PostgresDrizzleOutbox;
188
+ exports.createDrizzleTransactionStorage = createDrizzleTransactionStorage;
163
189
  exports.drizzleTransactionStorage = drizzleTransactionStorage;
164
190
  exports.getDrizzleTransaction = getDrizzleTransaction;
165
191
  exports.outboxEvents = outboxEvents;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["PollingService","EventStatus","failedEvent: FailedBusEvent","error: unknown","AsyncLocalStorage"],"sources":["../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":["import {\n integer,\n jsonb,\n pgEnum,\n pgTable,\n text,\n timestamp,\n uuid,\n} from \"drizzle-orm/pg-core\"\n\n\nexport const outboxStatusEnum = pgEnum(\"outbox_status\", [\n \"created\",\n \"active\",\n \"completed\",\n \"failed\",\n])\n\nexport const outboxEvents = pgTable(\"outbox_events\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull().default(\"created\"),\n retryCount: integer(\"retry_count\").notNull().default(0),\n lastError: text(\"last_error\"),\n nextRetryAt: timestamp(\"next_retry_at\"),\n createdOn: timestamp(\"created_on\").notNull().defaultNow(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\"),\n keepAlive: timestamp(\"keep_alive\"),\n expireInSeconds: integer(\"expire_in_seconds\").notNull().default(300),\n})\n\nexport const outboxEventsArchive = pgTable(\"outbox_events_archive\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull(),\n retryCount: integer(\"retry_count\").notNull(),\n lastError: text(\"last_error\"),\n createdOn: timestamp(\"created_on\").notNull(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\").notNull(),\n})\n","import { and, eq, inArray, lt, or, sql } from \"drizzle-orm\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\nimport {\n type BusEvent,\n type ErrorHandler,\n EventStatus,\n type FailedBusEvent,\n formatErrorMessage,\n type IOutbox,\n type OutboxConfig,\n PollingService,\n reportEventError,\n} from \"outbox-event-bus\"\nimport { outboxEvents, outboxEventsArchive } from \"./schema\"\n\nexport interface PostgresDrizzleOutboxConfig extends OutboxConfig {\n db: PostgresJsDatabase<Record<string, unknown>>\n getTransaction?: (() => PostgresJsDatabase<Record<string, unknown>> | undefined) | undefined\n tables?: {\n outboxEvents: typeof outboxEvents\n outboxEventsArchive: typeof outboxEventsArchive\n }\n}\n\nexport class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record<string, unknown>>> {\n private readonly config: Required<PostgresDrizzleOutboxConfig>\n private readonly poller: PollingService\n\n constructor(config: PostgresDrizzleOutboxConfig) {\n this.config = {\n batchSize: config.batchSize ?? 50,\n pollIntervalMs: config.pollIntervalMs ?? 1000,\n maxRetries: config.maxRetries ?? 5,\n baseBackoffMs: config.baseBackoffMs ?? 1000,\n processingTimeoutMs: config.processingTimeoutMs ?? 30000,\n maxErrorBackoffMs: config.maxErrorBackoffMs ?? 30000,\n db: config.db,\n getTransaction: config.getTransaction,\n tables: config.tables ?? {\n outboxEvents,\n outboxEventsArchive,\n },\n }\n\n this.poller = new PollingService({\n pollIntervalMs: this.config.pollIntervalMs,\n baseBackoffMs: this.config.baseBackoffMs,\n maxErrorBackoffMs: this.config.maxErrorBackoffMs,\n processBatch: (handler) => this.processBatch(handler),\n })\n }\n\n async publish(\n events: BusEvent[],\n transaction?: PostgresJsDatabase<Record<string, unknown>>\n ): Promise<void> {\n const executor = transaction ?? this.config.getTransaction?.() ?? this.config.db\n\n await executor.insert(this.config.tables.outboxEvents).values(\n events.map((event) => ({\n id: event.id,\n type: event.type,\n payload: event.payload,\n occurredAt: event.occurredAt,\n status: EventStatus.CREATED,\n }))\n )\n }\n\n async getFailedEvents(): Promise<FailedBusEvent[]> {\n const events = await this.config.db\n .select()\n .from(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.status, EventStatus.FAILED))\n .orderBy(sql`${this.config.tables.outboxEvents.occurredAt} DESC`)\n .limit(100)\n\n return events.map((event) => {\n const failedEvent: FailedBusEvent = {\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n retryCount: event.retryCount,\n }\n if (event.lastError) failedEvent.error = event.lastError\n if (event.startedOn) failedEvent.lastAttemptAt = event.startedOn\n return failedEvent\n })\n }\n\n async retryEvents(eventIds: string[]): Promise<void> {\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.CREATED,\n retryCount: 0,\n nextRetryAt: null,\n lastError: null,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n }\n\n start(handler: (event: BusEvent) => Promise<void>, onError: ErrorHandler): void {\n this.poller.start(handler, onError)\n }\n\n async stop(): Promise<void> {\n await this.poller.stop()\n }\n\n private async processBatch(handler: (event: BusEvent) => Promise<void>) {\n const now = new Date()\n\n const lockedEvents = await this.config.db.transaction(async (transaction) => {\n const events = await transaction\n .select()\n .from(this.config.tables.outboxEvents)\n .where(\n or(\n eq(this.config.tables.outboxEvents.status, EventStatus.CREATED),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.FAILED),\n lt(this.config.tables.outboxEvents.retryCount, this.config.maxRetries),\n lt(this.config.tables.outboxEvents.nextRetryAt, now)\n ),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.ACTIVE),\n lt(\n this.config.tables.outboxEvents.keepAlive,\n sql`${now.toISOString()}::timestamp - make_interval(secs => ${this.config.tables.outboxEvents.expireInSeconds})`\n )\n )\n )\n )\n .limit(this.config.batchSize)\n .for(\"update\", { skipLocked: true })\n\n if (events.length === 0) return []\n\n const eventIds = events.map((event) => event.id)\n\n await transaction\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.ACTIVE,\n startedOn: now,\n keepAlive: now,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n\n return events\n })\n\n if (lockedEvents.length === 0) return\n\n // 2. Process events outside of the transaction\n for (const event of lockedEvents) {\n try {\n await handler(event)\n\n // use the main db connection for individual updates to avoid long transactions\n await this.config.db.transaction(async (transaction) => {\n await transaction.insert(this.config.tables.outboxEventsArchive).values({\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n status: EventStatus.COMPLETED,\n retryCount: event.retryCount,\n createdOn: event.createdOn,\n startedOn: now,\n completedOn: new Date(),\n })\n await transaction\n .delete(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n })\n } catch (error: unknown) {\n const retryCount = event.retryCount + 1\n reportEventError(this.poller.onError, error, event, retryCount, this.config.maxRetries)\n\n const delay = this.poller.calculateBackoff(retryCount)\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.FAILED,\n retryCount,\n lastError: formatErrorMessage(error),\n nextRetryAt: new Date(Date.now() + delay),\n })\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n }\n }\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\n\nexport const drizzleTransactionStorage = new AsyncLocalStorage<\n PostgresJsDatabase<Record<string, unknown>>\n>()\n\nexport async function withDrizzleTransaction<T>(\n db: PostgresJsDatabase<Record<string, unknown>>,\n fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>\n): Promise<T> {\n return db.transaction(async (tx) => {\n return drizzleTransactionStorage.run(tx, () => fn(tx))\n })\n}\n\nexport function getDrizzleTransaction(): () =>\n | PostgresJsDatabase<Record<string, unknown>>\n | undefined {\n return () => drizzleTransactionStorage.getStore()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["PollingService","EventStatus","failedEvent: FailedBusEvent","error: unknown","AsyncLocalStorage"],"sources":["../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":["import {\n integer,\n jsonb,\n pgEnum,\n pgTable,\n text,\n timestamp,\n uuid,\n} from \"drizzle-orm/pg-core\"\n\n\nexport const outboxStatusEnum = pgEnum(\"outbox_status\", [\n \"created\",\n \"active\",\n \"completed\",\n \"failed\",\n])\n\nexport const outboxEvents = pgTable(\"outbox_events\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull().default(\"created\"),\n retryCount: integer(\"retry_count\").notNull().default(0),\n lastError: text(\"last_error\"),\n nextRetryAt: timestamp(\"next_retry_at\"),\n createdOn: timestamp(\"created_on\").notNull().defaultNow(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\"),\n keepAlive: timestamp(\"keep_alive\"),\n expireInSeconds: integer(\"expire_in_seconds\").notNull().default(300),\n})\n\nexport const outboxEventsArchive = pgTable(\"outbox_events_archive\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull(),\n retryCount: integer(\"retry_count\").notNull(),\n lastError: text(\"last_error\"),\n createdOn: timestamp(\"created_on\").notNull(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\").notNull(),\n})\n","import { and, eq, inArray, lt, or, sql } from \"drizzle-orm\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\nimport {\n type BusEvent,\n type ErrorHandler,\n EventStatus,\n type FailedBusEvent,\n formatErrorMessage,\n type IOutbox,\n type OutboxConfig,\n PollingService,\n reportEventError,\n} from \"outbox-event-bus\"\nimport { outboxEvents, outboxEventsArchive } from \"./schema\"\n\nexport interface PostgresDrizzleOutboxConfig<TSchema extends Record<string, unknown> = Record<string, unknown>> extends OutboxConfig {\n db: PostgresJsDatabase<TSchema>\n getTransaction?: (() => PostgresJsDatabase<TSchema> | undefined) | undefined\n tables?: {\n outboxEvents: typeof outboxEvents\n outboxEventsArchive: typeof outboxEventsArchive\n }\n}\n\nexport class PostgresDrizzleOutbox<TSchema extends Record<string, unknown> = Record<string, unknown>> implements IOutbox<PostgresJsDatabase<TSchema>> {\n private readonly config: Required<PostgresDrizzleOutboxConfig<TSchema>>\n private readonly poller: PollingService\n\n constructor(config: PostgresDrizzleOutboxConfig<TSchema>) {\n this.config = {\n batchSize: config.batchSize ?? 50,\n pollIntervalMs: config.pollIntervalMs ?? 1000,\n maxRetries: config.maxRetries ?? 5,\n baseBackoffMs: config.baseBackoffMs ?? 1000,\n processingTimeoutMs: config.processingTimeoutMs ?? 30000,\n maxErrorBackoffMs: config.maxErrorBackoffMs ?? 30000,\n db: config.db,\n getTransaction: config.getTransaction,\n tables: config.tables ?? {\n outboxEvents,\n outboxEventsArchive,\n },\n }\n\n this.poller = new PollingService({\n pollIntervalMs: this.config.pollIntervalMs,\n baseBackoffMs: this.config.baseBackoffMs,\n maxErrorBackoffMs: this.config.maxErrorBackoffMs,\n processBatch: (handler) => this.processBatch(handler),\n })\n }\n\n async publish(\n events: BusEvent[],\n transaction?: PostgresJsDatabase<TSchema>\n ): Promise<void> {\n const executor = transaction ?? this.config.getTransaction?.() ?? this.config.db\n\n await executor.insert(this.config.tables.outboxEvents).values(\n events.map((event) => ({\n id: event.id,\n type: event.type,\n payload: event.payload,\n occurredAt: event.occurredAt,\n status: EventStatus.CREATED,\n }))\n )\n }\n\n async getFailedEvents(): Promise<FailedBusEvent[]> {\n const events = await this.config.db\n .select()\n .from(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.status, EventStatus.FAILED))\n .orderBy(sql`${this.config.tables.outboxEvents.occurredAt} DESC`)\n .limit(100)\n\n return events.map((event) => {\n const failedEvent: FailedBusEvent = {\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n retryCount: event.retryCount,\n }\n if (event.lastError) failedEvent.error = event.lastError\n if (event.startedOn) failedEvent.lastAttemptAt = event.startedOn\n return failedEvent\n })\n }\n\n async retryEvents(eventIds: string[]): Promise<void> {\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.CREATED,\n retryCount: 0,\n nextRetryAt: null,\n lastError: null,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n }\n\n start(handler: (event: BusEvent) => Promise<void>, onError: ErrorHandler): void {\n this.poller.start(handler, onError)\n }\n\n async stop(): Promise<void> {\n await this.poller.stop()\n }\n\n private async processBatch(handler: (event: BusEvent) => Promise<void>) {\n const now = new Date()\n\n const lockedEvents = await this.config.db.transaction(async (transaction) => {\n const events = await transaction\n .select()\n .from(this.config.tables.outboxEvents)\n .where(\n or(\n eq(this.config.tables.outboxEvents.status, EventStatus.CREATED),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.FAILED),\n lt(this.config.tables.outboxEvents.retryCount, this.config.maxRetries),\n lt(this.config.tables.outboxEvents.nextRetryAt, now)\n ),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.ACTIVE),\n lt(\n this.config.tables.outboxEvents.keepAlive,\n sql`${now.toISOString()}::timestamp - make_interval(secs => ${this.config.tables.outboxEvents.expireInSeconds})`\n )\n )\n )\n )\n .limit(this.config.batchSize)\n .for(\"update\", { skipLocked: true })\n\n if (events.length === 0) return []\n\n const eventIds = events.map((event) => event.id)\n\n await transaction\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.ACTIVE,\n startedOn: now,\n keepAlive: now,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n\n return events\n })\n\n if (lockedEvents.length === 0) return\n\n // 2. Process events outside of the transaction\n for (const event of lockedEvents) {\n try {\n await handler(event)\n\n // use the main db connection for individual updates to avoid long transactions\n await this.config.db.transaction(async (transaction) => {\n await transaction.insert(this.config.tables.outboxEventsArchive).values({\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n status: EventStatus.COMPLETED,\n retryCount: event.retryCount,\n createdOn: event.createdOn,\n startedOn: now,\n completedOn: new Date(),\n })\n await transaction\n .delete(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n })\n } catch (error: unknown) {\n const retryCount = event.retryCount + 1\n reportEventError(this.poller.onError, error, event, retryCount, this.config.maxRetries)\n\n const delay = this.poller.calculateBackoff(retryCount)\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.FAILED,\n retryCount,\n lastError: formatErrorMessage(error),\n nextRetryAt: new Date(Date.now() + delay),\n })\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n }\n }\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\n\nexport function createDrizzleTransactionStorage<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n>() {\n const storage = new AsyncLocalStorage<PostgresJsDatabase<TSchema>>()\n\n async function withTransaction<T>(\n db: PostgresJsDatabase<TSchema>,\n fn: (tx: PostgresJsDatabase<TSchema>) => Promise<T>\n ): Promise<T> {\n return db.transaction(async (tx) => {\n return storage.run(tx, () => fn(tx))\n })\n }\n\n function getTransaction(): PostgresJsDatabase<TSchema> | undefined {\n return storage.getStore()\n }\n\n return { storage, withTransaction, getTransaction }\n}\n\n/**\n * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.\n */\nexport const drizzleTransactionStorage = new AsyncLocalStorage<\n PostgresJsDatabase<Record<string, unknown>>\n>()\n\n/**\n * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.\n */\nexport async function withDrizzleTransaction<T>(\n db: PostgresJsDatabase<Record<string, unknown>>,\n fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>\n): Promise<T> {\n return db.transaction(async (tx) => {\n return drizzleTransactionStorage.run(tx, () => fn(tx))\n })\n}\n\n/**\n * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.\n */\nexport function getDrizzleTransaction(): () =>\n | PostgresJsDatabase<Record<string, unknown>>\n | undefined {\n return () => drizzleTransactionStorage.getStore()\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -454,19 +454,19 @@ declare const outboxEventsArchive: drizzle_orm_pg_core0.PgTableWithColumns<{
454
454
  }>;
455
455
  //#endregion
456
456
  //#region src/postgres-drizzle-outbox.d.ts
457
- interface PostgresDrizzleOutboxConfig extends OutboxConfig {
458
- db: PostgresJsDatabase<Record<string, unknown>>;
459
- getTransaction?: (() => PostgresJsDatabase<Record<string, unknown>> | undefined) | undefined;
457
+ interface PostgresDrizzleOutboxConfig<TSchema extends Record<string, unknown> = Record<string, unknown>> extends OutboxConfig {
458
+ db: PostgresJsDatabase<TSchema>;
459
+ getTransaction?: (() => PostgresJsDatabase<TSchema> | undefined) | undefined;
460
460
  tables?: {
461
461
  outboxEvents: typeof outboxEvents;
462
462
  outboxEventsArchive: typeof outboxEventsArchive;
463
463
  };
464
464
  }
465
- declare class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record<string, unknown>>> {
465
+ declare class PostgresDrizzleOutbox<TSchema extends Record<string, unknown> = Record<string, unknown>> implements IOutbox<PostgresJsDatabase<TSchema>> {
466
466
  private readonly config;
467
467
  private readonly poller;
468
- constructor(config: PostgresDrizzleOutboxConfig);
469
- publish(events: BusEvent[], transaction?: PostgresJsDatabase<Record<string, unknown>>): Promise<void>;
468
+ constructor(config: PostgresDrizzleOutboxConfig<TSchema>);
469
+ publish(events: BusEvent[], transaction?: PostgresJsDatabase<TSchema>): Promise<void>;
470
470
  getFailedEvents(): Promise<FailedBusEvent[]>;
471
471
  retryEvents(eventIds: string[]): Promise<void>;
472
472
  start(handler: (event: BusEvent) => Promise<void>, onError: ErrorHandler): void;
@@ -475,9 +475,23 @@ declare class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record
475
475
  }
476
476
  //#endregion
477
477
  //#region src/transaction-storage.d.ts
478
+ declare function createDrizzleTransactionStorage<TSchema extends Record<string, unknown> = Record<string, unknown>>(): {
479
+ storage: AsyncLocalStorage<PostgresJsDatabase<TSchema>>;
480
+ withTransaction: <T>(db: PostgresJsDatabase<TSchema>, fn: (tx: PostgresJsDatabase<TSchema>) => Promise<T>) => Promise<T>;
481
+ getTransaction: () => PostgresJsDatabase<TSchema> | undefined;
482
+ };
483
+ /**
484
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
485
+ */
478
486
  declare const drizzleTransactionStorage: AsyncLocalStorage<PostgresJsDatabase<Record<string, unknown>>>;
487
+ /**
488
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
489
+ */
479
490
  declare function withDrizzleTransaction<T>(db: PostgresJsDatabase<Record<string, unknown>>, fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>): Promise<T>;
491
+ /**
492
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
493
+ */
480
494
  declare function getDrizzleTransaction(): () => PostgresJsDatabase<Record<string, unknown>> | undefined;
481
495
  //#endregion
482
- export { PostgresDrizzleOutbox, PostgresDrizzleOutboxConfig, drizzleTransactionStorage, getDrizzleTransaction, outboxEvents, outboxEventsArchive, outboxStatusEnum, withDrizzleTransaction };
496
+ export { PostgresDrizzleOutbox, PostgresDrizzleOutboxConfig, createDrizzleTransactionStorage, drizzleTransactionStorage, getDrizzleTransaction, outboxEvents, outboxEventsArchive, outboxStatusEnum, withDrizzleTransaction };
483
497
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../../core/src/errors/errors.ts","../../../core/src/types/types.ts","../../../core/src/types/interfaces.ts","../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../../core/src/errors/errors.ts","../../../core/src/types/types.ts","../../../core/src/types/interfaces.ts","../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -454,19 +454,19 @@ declare const outboxEventsArchive: drizzle_orm_pg_core0.PgTableWithColumns<{
454
454
  }>;
455
455
  //#endregion
456
456
  //#region src/postgres-drizzle-outbox.d.ts
457
- interface PostgresDrizzleOutboxConfig extends OutboxConfig {
458
- db: PostgresJsDatabase<Record<string, unknown>>;
459
- getTransaction?: (() => PostgresJsDatabase<Record<string, unknown>> | undefined) | undefined;
457
+ interface PostgresDrizzleOutboxConfig<TSchema extends Record<string, unknown> = Record<string, unknown>> extends OutboxConfig {
458
+ db: PostgresJsDatabase<TSchema>;
459
+ getTransaction?: (() => PostgresJsDatabase<TSchema> | undefined) | undefined;
460
460
  tables?: {
461
461
  outboxEvents: typeof outboxEvents;
462
462
  outboxEventsArchive: typeof outboxEventsArchive;
463
463
  };
464
464
  }
465
- declare class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record<string, unknown>>> {
465
+ declare class PostgresDrizzleOutbox<TSchema extends Record<string, unknown> = Record<string, unknown>> implements IOutbox<PostgresJsDatabase<TSchema>> {
466
466
  private readonly config;
467
467
  private readonly poller;
468
- constructor(config: PostgresDrizzleOutboxConfig);
469
- publish(events: BusEvent[], transaction?: PostgresJsDatabase<Record<string, unknown>>): Promise<void>;
468
+ constructor(config: PostgresDrizzleOutboxConfig<TSchema>);
469
+ publish(events: BusEvent[], transaction?: PostgresJsDatabase<TSchema>): Promise<void>;
470
470
  getFailedEvents(): Promise<FailedBusEvent[]>;
471
471
  retryEvents(eventIds: string[]): Promise<void>;
472
472
  start(handler: (event: BusEvent) => Promise<void>, onError: ErrorHandler): void;
@@ -475,9 +475,23 @@ declare class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record
475
475
  }
476
476
  //#endregion
477
477
  //#region src/transaction-storage.d.ts
478
+ declare function createDrizzleTransactionStorage<TSchema extends Record<string, unknown> = Record<string, unknown>>(): {
479
+ storage: AsyncLocalStorage<PostgresJsDatabase<TSchema>>;
480
+ withTransaction: <T>(db: PostgresJsDatabase<TSchema>, fn: (tx: PostgresJsDatabase<TSchema>) => Promise<T>) => Promise<T>;
481
+ getTransaction: () => PostgresJsDatabase<TSchema> | undefined;
482
+ };
483
+ /**
484
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
485
+ */
478
486
  declare const drizzleTransactionStorage: AsyncLocalStorage<PostgresJsDatabase<Record<string, unknown>>>;
487
+ /**
488
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
489
+ */
479
490
  declare function withDrizzleTransaction<T>(db: PostgresJsDatabase<Record<string, unknown>>, fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>): Promise<T>;
491
+ /**
492
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
493
+ */
480
494
  declare function getDrizzleTransaction(): () => PostgresJsDatabase<Record<string, unknown>> | undefined;
481
495
  //#endregion
482
- export { PostgresDrizzleOutbox, PostgresDrizzleOutboxConfig, drizzleTransactionStorage, getDrizzleTransaction, outboxEvents, outboxEventsArchive, outboxStatusEnum, withDrizzleTransaction };
496
+ export { PostgresDrizzleOutbox, PostgresDrizzleOutboxConfig, createDrizzleTransactionStorage, drizzleTransactionStorage, getDrizzleTransaction, outboxEvents, outboxEventsArchive, outboxStatusEnum, withDrizzleTransaction };
483
497
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../core/src/errors/errors.ts","../../../core/src/types/types.ts","../../../core/src/types/interfaces.ts","../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../core/src/errors/errors.ts","../../../core/src/types/types.ts","../../../core/src/types/interfaces.ts","../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -148,16 +148,41 @@ var PostgresDrizzleOutbox = class {
148
148
 
149
149
  //#endregion
150
150
  //#region src/transaction-storage.ts
151
+ function createDrizzleTransactionStorage() {
152
+ const storage = new AsyncLocalStorage();
153
+ async function withTransaction(db, fn) {
154
+ return db.transaction(async (tx) => {
155
+ return storage.run(tx, () => fn(tx));
156
+ });
157
+ }
158
+ function getTransaction() {
159
+ return storage.getStore();
160
+ }
161
+ return {
162
+ storage,
163
+ withTransaction,
164
+ getTransaction
165
+ };
166
+ }
167
+ /**
168
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
169
+ */
151
170
  const drizzleTransactionStorage = new AsyncLocalStorage();
171
+ /**
172
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
173
+ */
152
174
  async function withDrizzleTransaction(db, fn) {
153
175
  return db.transaction(async (tx) => {
154
176
  return drizzleTransactionStorage.run(tx, () => fn(tx));
155
177
  });
156
178
  }
179
+ /**
180
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
181
+ */
157
182
  function getDrizzleTransaction() {
158
183
  return () => drizzleTransactionStorage.getStore();
159
184
  }
160
185
 
161
186
  //#endregion
162
- export { PostgresDrizzleOutbox, drizzleTransactionStorage, getDrizzleTransaction, outboxEvents, outboxEventsArchive, outboxStatusEnum, withDrizzleTransaction };
187
+ export { PostgresDrizzleOutbox, createDrizzleTransactionStorage, drizzleTransactionStorage, getDrizzleTransaction, outboxEvents, outboxEventsArchive, outboxStatusEnum, withDrizzleTransaction };
163
188
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["failedEvent: FailedBusEvent","error: unknown"],"sources":["../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":["import {\n integer,\n jsonb,\n pgEnum,\n pgTable,\n text,\n timestamp,\n uuid,\n} from \"drizzle-orm/pg-core\"\n\n\nexport const outboxStatusEnum = pgEnum(\"outbox_status\", [\n \"created\",\n \"active\",\n \"completed\",\n \"failed\",\n])\n\nexport const outboxEvents = pgTable(\"outbox_events\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull().default(\"created\"),\n retryCount: integer(\"retry_count\").notNull().default(0),\n lastError: text(\"last_error\"),\n nextRetryAt: timestamp(\"next_retry_at\"),\n createdOn: timestamp(\"created_on\").notNull().defaultNow(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\"),\n keepAlive: timestamp(\"keep_alive\"),\n expireInSeconds: integer(\"expire_in_seconds\").notNull().default(300),\n})\n\nexport const outboxEventsArchive = pgTable(\"outbox_events_archive\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull(),\n retryCount: integer(\"retry_count\").notNull(),\n lastError: text(\"last_error\"),\n createdOn: timestamp(\"created_on\").notNull(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\").notNull(),\n})\n","import { and, eq, inArray, lt, or, sql } from \"drizzle-orm\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\nimport {\n type BusEvent,\n type ErrorHandler,\n EventStatus,\n type FailedBusEvent,\n formatErrorMessage,\n type IOutbox,\n type OutboxConfig,\n PollingService,\n reportEventError,\n} from \"outbox-event-bus\"\nimport { outboxEvents, outboxEventsArchive } from \"./schema\"\n\nexport interface PostgresDrizzleOutboxConfig extends OutboxConfig {\n db: PostgresJsDatabase<Record<string, unknown>>\n getTransaction?: (() => PostgresJsDatabase<Record<string, unknown>> | undefined) | undefined\n tables?: {\n outboxEvents: typeof outboxEvents\n outboxEventsArchive: typeof outboxEventsArchive\n }\n}\n\nexport class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record<string, unknown>>> {\n private readonly config: Required<PostgresDrizzleOutboxConfig>\n private readonly poller: PollingService\n\n constructor(config: PostgresDrizzleOutboxConfig) {\n this.config = {\n batchSize: config.batchSize ?? 50,\n pollIntervalMs: config.pollIntervalMs ?? 1000,\n maxRetries: config.maxRetries ?? 5,\n baseBackoffMs: config.baseBackoffMs ?? 1000,\n processingTimeoutMs: config.processingTimeoutMs ?? 30000,\n maxErrorBackoffMs: config.maxErrorBackoffMs ?? 30000,\n db: config.db,\n getTransaction: config.getTransaction,\n tables: config.tables ?? {\n outboxEvents,\n outboxEventsArchive,\n },\n }\n\n this.poller = new PollingService({\n pollIntervalMs: this.config.pollIntervalMs,\n baseBackoffMs: this.config.baseBackoffMs,\n maxErrorBackoffMs: this.config.maxErrorBackoffMs,\n processBatch: (handler) => this.processBatch(handler),\n })\n }\n\n async publish(\n events: BusEvent[],\n transaction?: PostgresJsDatabase<Record<string, unknown>>\n ): Promise<void> {\n const executor = transaction ?? this.config.getTransaction?.() ?? this.config.db\n\n await executor.insert(this.config.tables.outboxEvents).values(\n events.map((event) => ({\n id: event.id,\n type: event.type,\n payload: event.payload,\n occurredAt: event.occurredAt,\n status: EventStatus.CREATED,\n }))\n )\n }\n\n async getFailedEvents(): Promise<FailedBusEvent[]> {\n const events = await this.config.db\n .select()\n .from(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.status, EventStatus.FAILED))\n .orderBy(sql`${this.config.tables.outboxEvents.occurredAt} DESC`)\n .limit(100)\n\n return events.map((event) => {\n const failedEvent: FailedBusEvent = {\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n retryCount: event.retryCount,\n }\n if (event.lastError) failedEvent.error = event.lastError\n if (event.startedOn) failedEvent.lastAttemptAt = event.startedOn\n return failedEvent\n })\n }\n\n async retryEvents(eventIds: string[]): Promise<void> {\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.CREATED,\n retryCount: 0,\n nextRetryAt: null,\n lastError: null,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n }\n\n start(handler: (event: BusEvent) => Promise<void>, onError: ErrorHandler): void {\n this.poller.start(handler, onError)\n }\n\n async stop(): Promise<void> {\n await this.poller.stop()\n }\n\n private async processBatch(handler: (event: BusEvent) => Promise<void>) {\n const now = new Date()\n\n const lockedEvents = await this.config.db.transaction(async (transaction) => {\n const events = await transaction\n .select()\n .from(this.config.tables.outboxEvents)\n .where(\n or(\n eq(this.config.tables.outboxEvents.status, EventStatus.CREATED),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.FAILED),\n lt(this.config.tables.outboxEvents.retryCount, this.config.maxRetries),\n lt(this.config.tables.outboxEvents.nextRetryAt, now)\n ),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.ACTIVE),\n lt(\n this.config.tables.outboxEvents.keepAlive,\n sql`${now.toISOString()}::timestamp - make_interval(secs => ${this.config.tables.outboxEvents.expireInSeconds})`\n )\n )\n )\n )\n .limit(this.config.batchSize)\n .for(\"update\", { skipLocked: true })\n\n if (events.length === 0) return []\n\n const eventIds = events.map((event) => event.id)\n\n await transaction\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.ACTIVE,\n startedOn: now,\n keepAlive: now,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n\n return events\n })\n\n if (lockedEvents.length === 0) return\n\n // 2. Process events outside of the transaction\n for (const event of lockedEvents) {\n try {\n await handler(event)\n\n // use the main db connection for individual updates to avoid long transactions\n await this.config.db.transaction(async (transaction) => {\n await transaction.insert(this.config.tables.outboxEventsArchive).values({\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n status: EventStatus.COMPLETED,\n retryCount: event.retryCount,\n createdOn: event.createdOn,\n startedOn: now,\n completedOn: new Date(),\n })\n await transaction\n .delete(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n })\n } catch (error: unknown) {\n const retryCount = event.retryCount + 1\n reportEventError(this.poller.onError, error, event, retryCount, this.config.maxRetries)\n\n const delay = this.poller.calculateBackoff(retryCount)\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.FAILED,\n retryCount,\n lastError: formatErrorMessage(error),\n nextRetryAt: new Date(Date.now() + delay),\n })\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n }\n }\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\n\nexport const drizzleTransactionStorage = new AsyncLocalStorage<\n PostgresJsDatabase<Record<string, unknown>>\n>()\n\nexport async function withDrizzleTransaction<T>(\n db: PostgresJsDatabase<Record<string, unknown>>,\n fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>\n): Promise<T> {\n return db.transaction(async (tx) => {\n return drizzleTransactionStorage.run(tx, () => fn(tx))\n })\n}\n\nexport function getDrizzleTransaction(): () =>\n | PostgresJsDatabase<Record<string, unknown>>\n | undefined {\n return () => drizzleTransactionStorage.getStore()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["failedEvent: FailedBusEvent","error: unknown"],"sources":["../src/schema.ts","../src/postgres-drizzle-outbox.ts","../src/transaction-storage.ts"],"sourcesContent":["import {\n integer,\n jsonb,\n pgEnum,\n pgTable,\n text,\n timestamp,\n uuid,\n} from \"drizzle-orm/pg-core\"\n\n\nexport const outboxStatusEnum = pgEnum(\"outbox_status\", [\n \"created\",\n \"active\",\n \"completed\",\n \"failed\",\n])\n\nexport const outboxEvents = pgTable(\"outbox_events\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull().default(\"created\"),\n retryCount: integer(\"retry_count\").notNull().default(0),\n lastError: text(\"last_error\"),\n nextRetryAt: timestamp(\"next_retry_at\"),\n createdOn: timestamp(\"created_on\").notNull().defaultNow(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\"),\n keepAlive: timestamp(\"keep_alive\"),\n expireInSeconds: integer(\"expire_in_seconds\").notNull().default(300),\n})\n\nexport const outboxEventsArchive = pgTable(\"outbox_events_archive\", {\n id: uuid(\"id\").primaryKey(),\n type: text(\"type\").notNull(),\n payload: jsonb(\"payload\").notNull(),\n occurredAt: timestamp(\"occurred_at\").notNull(),\n status: outboxStatusEnum(\"status\").notNull(),\n retryCount: integer(\"retry_count\").notNull(),\n lastError: text(\"last_error\"),\n createdOn: timestamp(\"created_on\").notNull(),\n startedOn: timestamp(\"started_on\"),\n completedOn: timestamp(\"completed_on\").notNull(),\n})\n","import { and, eq, inArray, lt, or, sql } from \"drizzle-orm\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\nimport {\n type BusEvent,\n type ErrorHandler,\n EventStatus,\n type FailedBusEvent,\n formatErrorMessage,\n type IOutbox,\n type OutboxConfig,\n PollingService,\n reportEventError,\n} from \"outbox-event-bus\"\nimport { outboxEvents, outboxEventsArchive } from \"./schema\"\n\nexport interface PostgresDrizzleOutboxConfig<TSchema extends Record<string, unknown> = Record<string, unknown>> extends OutboxConfig {\n db: PostgresJsDatabase<TSchema>\n getTransaction?: (() => PostgresJsDatabase<TSchema> | undefined) | undefined\n tables?: {\n outboxEvents: typeof outboxEvents\n outboxEventsArchive: typeof outboxEventsArchive\n }\n}\n\nexport class PostgresDrizzleOutbox<TSchema extends Record<string, unknown> = Record<string, unknown>> implements IOutbox<PostgresJsDatabase<TSchema>> {\n private readonly config: Required<PostgresDrizzleOutboxConfig<TSchema>>\n private readonly poller: PollingService\n\n constructor(config: PostgresDrizzleOutboxConfig<TSchema>) {\n this.config = {\n batchSize: config.batchSize ?? 50,\n pollIntervalMs: config.pollIntervalMs ?? 1000,\n maxRetries: config.maxRetries ?? 5,\n baseBackoffMs: config.baseBackoffMs ?? 1000,\n processingTimeoutMs: config.processingTimeoutMs ?? 30000,\n maxErrorBackoffMs: config.maxErrorBackoffMs ?? 30000,\n db: config.db,\n getTransaction: config.getTransaction,\n tables: config.tables ?? {\n outboxEvents,\n outboxEventsArchive,\n },\n }\n\n this.poller = new PollingService({\n pollIntervalMs: this.config.pollIntervalMs,\n baseBackoffMs: this.config.baseBackoffMs,\n maxErrorBackoffMs: this.config.maxErrorBackoffMs,\n processBatch: (handler) => this.processBatch(handler),\n })\n }\n\n async publish(\n events: BusEvent[],\n transaction?: PostgresJsDatabase<TSchema>\n ): Promise<void> {\n const executor = transaction ?? this.config.getTransaction?.() ?? this.config.db\n\n await executor.insert(this.config.tables.outboxEvents).values(\n events.map((event) => ({\n id: event.id,\n type: event.type,\n payload: event.payload,\n occurredAt: event.occurredAt,\n status: EventStatus.CREATED,\n }))\n )\n }\n\n async getFailedEvents(): Promise<FailedBusEvent[]> {\n const events = await this.config.db\n .select()\n .from(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.status, EventStatus.FAILED))\n .orderBy(sql`${this.config.tables.outboxEvents.occurredAt} DESC`)\n .limit(100)\n\n return events.map((event) => {\n const failedEvent: FailedBusEvent = {\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n retryCount: event.retryCount,\n }\n if (event.lastError) failedEvent.error = event.lastError\n if (event.startedOn) failedEvent.lastAttemptAt = event.startedOn\n return failedEvent\n })\n }\n\n async retryEvents(eventIds: string[]): Promise<void> {\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.CREATED,\n retryCount: 0,\n nextRetryAt: null,\n lastError: null,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n }\n\n start(handler: (event: BusEvent) => Promise<void>, onError: ErrorHandler): void {\n this.poller.start(handler, onError)\n }\n\n async stop(): Promise<void> {\n await this.poller.stop()\n }\n\n private async processBatch(handler: (event: BusEvent) => Promise<void>) {\n const now = new Date()\n\n const lockedEvents = await this.config.db.transaction(async (transaction) => {\n const events = await transaction\n .select()\n .from(this.config.tables.outboxEvents)\n .where(\n or(\n eq(this.config.tables.outboxEvents.status, EventStatus.CREATED),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.FAILED),\n lt(this.config.tables.outboxEvents.retryCount, this.config.maxRetries),\n lt(this.config.tables.outboxEvents.nextRetryAt, now)\n ),\n and(\n eq(this.config.tables.outboxEvents.status, EventStatus.ACTIVE),\n lt(\n this.config.tables.outboxEvents.keepAlive,\n sql`${now.toISOString()}::timestamp - make_interval(secs => ${this.config.tables.outboxEvents.expireInSeconds})`\n )\n )\n )\n )\n .limit(this.config.batchSize)\n .for(\"update\", { skipLocked: true })\n\n if (events.length === 0) return []\n\n const eventIds = events.map((event) => event.id)\n\n await transaction\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.ACTIVE,\n startedOn: now,\n keepAlive: now,\n })\n .where(inArray(this.config.tables.outboxEvents.id, eventIds))\n\n return events\n })\n\n if (lockedEvents.length === 0) return\n\n // 2. Process events outside of the transaction\n for (const event of lockedEvents) {\n try {\n await handler(event)\n\n // use the main db connection for individual updates to avoid long transactions\n await this.config.db.transaction(async (transaction) => {\n await transaction.insert(this.config.tables.outboxEventsArchive).values({\n id: event.id,\n type: event.type,\n payload: event.payload as any,\n occurredAt: event.occurredAt,\n status: EventStatus.COMPLETED,\n retryCount: event.retryCount,\n createdOn: event.createdOn,\n startedOn: now,\n completedOn: new Date(),\n })\n await transaction\n .delete(this.config.tables.outboxEvents)\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n })\n } catch (error: unknown) {\n const retryCount = event.retryCount + 1\n reportEventError(this.poller.onError, error, event, retryCount, this.config.maxRetries)\n\n const delay = this.poller.calculateBackoff(retryCount)\n await this.config.db\n .update(this.config.tables.outboxEvents)\n .set({\n status: EventStatus.FAILED,\n retryCount,\n lastError: formatErrorMessage(error),\n nextRetryAt: new Date(Date.now() + delay),\n })\n .where(eq(this.config.tables.outboxEvents.id, event.id))\n }\n }\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\"\n\nexport function createDrizzleTransactionStorage<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n>() {\n const storage = new AsyncLocalStorage<PostgresJsDatabase<TSchema>>()\n\n async function withTransaction<T>(\n db: PostgresJsDatabase<TSchema>,\n fn: (tx: PostgresJsDatabase<TSchema>) => Promise<T>\n ): Promise<T> {\n return db.transaction(async (tx) => {\n return storage.run(tx, () => fn(tx))\n })\n }\n\n function getTransaction(): PostgresJsDatabase<TSchema> | undefined {\n return storage.getStore()\n }\n\n return { storage, withTransaction, getTransaction }\n}\n\n/**\n * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.\n */\nexport const drizzleTransactionStorage = new AsyncLocalStorage<\n PostgresJsDatabase<Record<string, unknown>>\n>()\n\n/**\n * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.\n */\nexport async function withDrizzleTransaction<T>(\n db: PostgresJsDatabase<Record<string, unknown>>,\n fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>\n): Promise<T> {\n return db.transaction(async (tx) => {\n return drizzleTransactionStorage.run(tx, () => fn(tx))\n })\n}\n\n/**\n * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.\n */\nexport function getDrizzleTransaction(): () =>\n | PostgresJsDatabase<Record<string, unknown>>\n | undefined {\n return () => drizzleTransactionStorage.getStore()\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outbox-event-bus/postgres-drizzle-outbox",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -13,20 +13,20 @@ import {
13
13
  } from "outbox-event-bus"
14
14
  import { outboxEvents, outboxEventsArchive } from "./schema"
15
15
 
16
- export interface PostgresDrizzleOutboxConfig extends OutboxConfig {
17
- db: PostgresJsDatabase<Record<string, unknown>>
18
- getTransaction?: (() => PostgresJsDatabase<Record<string, unknown>> | undefined) | undefined
16
+ export interface PostgresDrizzleOutboxConfig<TSchema extends Record<string, unknown> = Record<string, unknown>> extends OutboxConfig {
17
+ db: PostgresJsDatabase<TSchema>
18
+ getTransaction?: (() => PostgresJsDatabase<TSchema> | undefined) | undefined
19
19
  tables?: {
20
20
  outboxEvents: typeof outboxEvents
21
21
  outboxEventsArchive: typeof outboxEventsArchive
22
22
  }
23
23
  }
24
24
 
25
- export class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record<string, unknown>>> {
26
- private readonly config: Required<PostgresDrizzleOutboxConfig>
25
+ export class PostgresDrizzleOutbox<TSchema extends Record<string, unknown> = Record<string, unknown>> implements IOutbox<PostgresJsDatabase<TSchema>> {
26
+ private readonly config: Required<PostgresDrizzleOutboxConfig<TSchema>>
27
27
  private readonly poller: PollingService
28
28
 
29
- constructor(config: PostgresDrizzleOutboxConfig) {
29
+ constructor(config: PostgresDrizzleOutboxConfig<TSchema>) {
30
30
  this.config = {
31
31
  batchSize: config.batchSize ?? 50,
32
32
  pollIntervalMs: config.pollIntervalMs ?? 1000,
@@ -52,7 +52,7 @@ export class PostgresDrizzleOutbox implements IOutbox<PostgresJsDatabase<Record<
52
52
 
53
53
  async publish(
54
54
  events: BusEvent[],
55
- transaction?: PostgresJsDatabase<Record<string, unknown>>
55
+ transaction?: PostgresJsDatabase<TSchema>
56
56
  ): Promise<void> {
57
57
  const executor = transaction ?? this.config.getTransaction?.() ?? this.config.db
58
58
 
@@ -1,10 +1,37 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks"
2
2
  import type { PostgresJsDatabase } from "drizzle-orm/postgres-js"
3
3
 
4
+ export function createDrizzleTransactionStorage<
5
+ TSchema extends Record<string, unknown> = Record<string, unknown>,
6
+ >() {
7
+ const storage = new AsyncLocalStorage<PostgresJsDatabase<TSchema>>()
8
+
9
+ async function withTransaction<T>(
10
+ db: PostgresJsDatabase<TSchema>,
11
+ fn: (tx: PostgresJsDatabase<TSchema>) => Promise<T>
12
+ ): Promise<T> {
13
+ return db.transaction(async (tx) => {
14
+ return storage.run(tx, () => fn(tx))
15
+ })
16
+ }
17
+
18
+ function getTransaction(): PostgresJsDatabase<TSchema> | undefined {
19
+ return storage.getStore()
20
+ }
21
+
22
+ return { storage, withTransaction, getTransaction }
23
+ }
24
+
25
+ /**
26
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
27
+ */
4
28
  export const drizzleTransactionStorage = new AsyncLocalStorage<
5
29
  PostgresJsDatabase<Record<string, unknown>>
6
30
  >()
7
31
 
32
+ /**
33
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
34
+ */
8
35
  export async function withDrizzleTransaction<T>(
9
36
  db: PostgresJsDatabase<Record<string, unknown>>,
10
37
  fn: (tx: PostgresJsDatabase<Record<string, unknown>>) => Promise<T>
@@ -14,6 +41,9 @@ export async function withDrizzleTransaction<T>(
14
41
  })
15
42
  }
16
43
 
44
+ /**
45
+ * @deprecated Use `createDrizzleTransactionStorage()` for type-safe schema support.
46
+ */
17
47
  export function getDrizzleTransaction(): () =>
18
48
  | PostgresJsDatabase<Record<string, unknown>>
19
49
  | undefined {