@relaybus/postgres 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +10 -0
  2. package/dist/chunk-5WWPAN5Q.js +26 -0
  3. package/dist/chunk-5WWPAN5Q.js.map +1 -0
  4. package/dist/chunk-FY65AUUF.js +40 -0
  5. package/dist/chunk-FY65AUUF.js.map +1 -0
  6. package/dist/chunk-UDBN4RRV.js +35 -0
  7. package/dist/chunk-UDBN4RRV.js.map +1 -0
  8. package/dist/drizzle.cjs +24 -0
  9. package/dist/drizzle.cjs.map +1 -1
  10. package/dist/drizzle.d.cts +1 -0
  11. package/dist/drizzle.d.ts +1 -0
  12. package/dist/drizzle.js +2 -1
  13. package/dist/drizzle.js.map +1 -1
  14. package/dist/{executor-CfJgktC6.d.cts → executor-Bt90w33Q.d.cts} +24 -1
  15. package/dist/{executor-CfJgktC6.d.ts → executor-Bt90w33Q.d.ts} +24 -1
  16. package/dist/index.cjs +103 -5
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +19 -3
  19. package/dist/index.d.ts +19 -3
  20. package/dist/index.js +71 -41
  21. package/dist/index.js.map +1 -1
  22. package/dist/knex.cjs +24 -0
  23. package/dist/knex.cjs.map +1 -1
  24. package/dist/knex.d.cts +1 -0
  25. package/dist/knex.d.ts +1 -0
  26. package/dist/knex.js +2 -1
  27. package/dist/knex.js.map +1 -1
  28. package/dist/kysely.cjs +24 -0
  29. package/dist/kysely.cjs.map +1 -1
  30. package/dist/kysely.d.cts +1 -0
  31. package/dist/kysely.d.ts +1 -0
  32. package/dist/kysely.js +2 -1
  33. package/dist/kysely.js.map +1 -1
  34. package/dist/prisma.cjs +24 -0
  35. package/dist/prisma.cjs.map +1 -1
  36. package/dist/prisma.d.cts +1 -0
  37. package/dist/prisma.d.ts +1 -0
  38. package/dist/prisma.js +2 -1
  39. package/dist/prisma.js.map +1 -1
  40. package/dist/typeorm.cjs +46 -0
  41. package/dist/typeorm.cjs.map +1 -1
  42. package/dist/typeorm.d.cts +1 -0
  43. package/dist/typeorm.d.ts +1 -0
  44. package/dist/typeorm.js +11 -1
  45. package/dist/typeorm.js.map +1 -1
  46. package/package.json +4 -4
  47. package/dist/chunk-NNZJR5AB.js +0 -12
  48. package/dist/chunk-NNZJR5AB.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transaction-timeouts.ts","../src/pg-executor.ts","../src/identifiers.ts","../src/names.ts","../src/sql-fragments.ts","../src/schema.ts","../src/notification-listener.ts","../src/root-pool-executor.ts","../src/row-mapping.ts","../src/postgres-append.ts","../src/errors.ts","../src/claim-rows.ts","../src/postgres-claim.ts","../src/postgres-completion.ts","../src/owned-connections.ts","../src/postgres-maintenance.ts","../src/postgres-setup.ts","../src/postgres-store-options.ts","../src/statements-append.ts","../src/statement-fragments.ts","../src/statements-claim.ts","../src/statements-completion.ts","../src/statements-candidates.ts","../src/statements-lanes.ts","../src/statements-purge.ts","../src/statements-queries.ts","../src/statements-setup.ts","../src/statements.ts","../src/postgres-event-store.ts"],"names":["createHash","ConfigurationError","connect","schedule","systemClock","LaneLeaseTokenFormat","inserted","CompositeKey","RelayBusError","OwnerSerializedClaims","LeaseSettlement","DeliveryLeaseIdentity","Client","PositiveInteger","HandedOutLedger","executor","pool","Pool"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { PostgresStoreState } from './postgres-store-state.js';\n\n/** What {@link budgetSettingsSql} sets and how long the settings last. */\nexport type BudgetSettings = {\n /** The value as SQL: a parameter (`$1`) or a quoted literal (`'5000ms'`). */\n readonly value: string;\n /**\n * Also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+, `transaction_timeout`: the\n * server then ends the session of an overrun, so only executors that survive that get them\n * ({@link PostgresExecutor.sessionTimeouts}).\n */\n readonly sessionTimeouts: boolean;\n /** `transaction`: `SET LOCAL` semantics, gone with the transaction. `session`: kept by the connection. */\n readonly scope: 'transaction' | 'session';\n};\n\n/** The statement that holds a transaction to a time budget: `statement_timeout` and, see {@link BudgetSettings}, more. */\nexport function budgetSettingsSql({ value, sessionTimeouts, scope }: BudgetSettings): string {\n const local = scope === 'transaction';\n const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;\n if (!sessionTimeouts) {\n return statementTimeout;\n }\n return (\n `${statementTimeout}, set_config('idle_in_transaction_session_timeout', ${value}, ${local}), ` +\n \"CASE WHEN current_setting('server_version_num')::int >= 170000 \" +\n `THEN set_config('transaction_timeout', ${value}, ${local}) END`\n );\n}\n\n/** Puts the settings {@link budgetSettingsSql} keeps at session level back to the defaults of the session. */\nexport const SESSION_DEFAULTS_SQL =\n 'SELECT set_config(name, reset_val, false) FROM pg_settings ' +\n \"WHERE name IN ('statement_timeout', 'idle_in_transaction_session_timeout', 'transaction_timeout')\";\n\n/** The budget as a setting value: whole milliseconds, so nothing but digits reaches SQL text. */\nexport function budgetValue(timeoutMs: number): string {\n return `${Math.ceil(timeoutMs)}ms`;\n}\n\n/**\n * Runs `work` in a transaction of `state`'s executor that the server holds to `timeoutMs`. An executor\n * with `transactionWithBudget` (`PgExecutor`) sets the budget in the round trip of its `BEGIN`; any\n * other executor runs it with `SET LOCAL` semantics as the first statement of the transaction.\n */\nexport function inBudgetedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithBudget !== undefined) {\n return executor.transactionWithBudget(work, timeoutMs);\n }\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await state.query({ sql, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import { createHash } from 'node:crypto';\nimport type { RelayBusLogger } from '@relaybus/core';\nimport type { Pool, PoolClient } from 'pg';\nimport type {\n PostgresExecutor,\n PostgresParameter,\n PostgresQueryOptions,\n PostgresRow,\n} from './executor.js';\nimport { SESSION_DEFAULTS_SQL, budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/**\n * SQLSTATEs of a named statement the server does not know (26000) or already has under that name\n * (42P05). Both mean the connection the statement ran on is not the session that prepared it, which is\n * what a pooler in transaction mode without prepared statement support (PgBouncer before 1.21) does.\n */\nconst FOREIGN_SESSION_ERRORS = new Set(['26000', '42P05']);\n\nexport interface PgExecutorOptions {\n /** Receives the warning sent when prepared statements are switched off. Default `console`. */\n readonly logger?: RelayBusLogger;\n /**\n * The pool is this executor's alone (the store sets it for the pool it creates from\n * `connectionString`). A transaction budget then becomes a session setting of the connection, sent\n * with `BEGIN` only when the connection does not have it yet, and a transaction without a budget on\n * such a connection puts the session defaults back in its `BEGIN`. Statements outside a\n * transaction run under the budget the connection last got. Never set it for a pool other code\n * uses, or behind a pooler in transaction mode (session settings would reach other clients); the\n * executor stops it by itself when it notices a pooler (see prepared statements). Default `false`.\n */\n readonly sessionBudget?: boolean;\n}\n\n/** How a transaction starts on one connection, and what its commit tells about the session. */\ntype TransactionStart = {\n readonly begin: string;\n /** The budget the session keeps once the transaction committed; `null` for the defaults. */\n readonly sessionValue?: string | null;\n};\n\n/** Hex digits of the statement hash in a prepared statement name. */\nconst STATEMENT_NAME_DIGITS = 24;\n\n/**\n * Executor for a `pg` {@link Pool}. A transaction is a dedicated pool client\n * between `BEGIN` and `COMMIT`; it is handed to callers as the transaction\n * handle, so they can run their own queries on it.\n *\n * A statement sent with `prepare: true` is a named prepared statement: each\n * connection parses and plans its text once and from then on only binds the\n * parameters. Its name is derived from the text, so stores with different\n * tables never share one. When the server reports that a prepared statement\n * does not exist on the connection, or already does (a pooler such as\n * PgBouncer before 1.21 in transaction mode hands every transaction another\n * server session), the executor stops preparing for good, logs a warning, and\n * runs the statement again unprepared unless it belonged to a transaction,\n * which has failed by then and is the caller's to retry.\n */\nexport class PgExecutor implements PostgresExecutor<PoolClient> {\n readonly #pool: Pool;\n readonly #logger: RelayBusLogger;\n readonly #names = new Map<string, string>();\n #preparing = true;\n readonly #sessionBudget: boolean;\n /** The budget each connection keeps at session level (`sessionBudget`); absent for the defaults. */\n readonly #sessionValues = new WeakMap<PoolClient, string>();\n\n constructor(pool: Pool, options: PgExecutorOptions = {}) {\n this.#pool = pool;\n this.#logger = options.logger ?? console;\n this.#sessionBudget = options.sessionBudget === true;\n }\n\n /** The connection listens for `error` during the transaction, so a server-ended session fails the transaction instead of the process. */\n readonly sessionTimeouts = true;\n\n transaction<T>(work: (transaction: PoolClient) => Promise<T>): Promise<T> {\n // Once a pooler was noticed, which session a connection reaches is unknown: every transaction resets.\n return this.#transaction(work, (client) =>\n this.#sessionBudget && (!this.#preparing || this.#sessionValues.has(client))\n ? { begin: `BEGIN; ${SESSION_DEFAULTS_SQL}`, sessionValue: null }\n : { begin: 'BEGIN' },\n );\n }\n\n /**\n * Sends `BEGIN` and the budget settings as one simple query (the value as a literal: the simple\n * query protocol has no parameters), so the budget costs no round trip. With `sessionBudget` a\n * connection that already keeps this budget only gets `BEGIN`.\n */\n transactionWithBudget<T>(\n work: (transaction: PoolClient) => Promise<T>,\n timeoutMs: number,\n ): Promise<T> {\n const value = budgetValue(timeoutMs);\n const settings = (scope: 'transaction' | 'session'): string =>\n budgetSettingsSql({ value: `'${value}'`, sessionTimeouts: true, scope });\n return this.#transaction(work, (client) => {\n if (!this.#keepsSessionBudget()) {\n return { begin: `BEGIN; ${settings('transaction')}` };\n }\n return this.#sessionValues.get(client) === value\n ? { begin: 'BEGIN' }\n : { begin: `BEGIN; ${settings('session')}`, sessionValue: value };\n });\n }\n\n #recordSession(client: PoolClient, sessionValue: string | null | undefined): void {\n if (sessionValue === null) {\n this.#sessionValues.delete(client);\n } else if (sessionValue !== undefined) {\n this.#sessionValues.set(client, sessionValue);\n }\n }\n\n /** A pooler that hands out other server sessions (noticed by prepared statements) shares session settings. */\n #keepsSessionBudget(): boolean {\n return this.#sessionBudget && this.#preparing;\n }\n\n async #transaction<T>(\n work: (transaction: PoolClient) => Promise<T>,\n start: (client: PoolClient) => TransactionStart,\n ): Promise<T> {\n const client = await this.#pool.connect();\n let released = false;\n const release = (destroy: boolean): void => {\n if (released) {\n return;\n }\n released = true;\n client.removeListener('error', onSessionEnded);\n if (destroy) {\n client.release(true);\n } else {\n client.release();\n }\n };\n // The pool only listens while a client is idle: an error event of a checked-out client (the\n // server ending the session, for example at idle_in_transaction_session_timeout) would be\n // unhandled. The connection is dead, so it goes back to the pool at once, destroyed; the\n // transaction fails at its next statement or its commit.\n const onSessionEnded = (error: Error): void => {\n this.#logger.warn(\n `[PgExecutor](transaction) The server ended the session of an open transaction, the transaction fails | error=${error.message}`,\n );\n release(true);\n };\n client.on('error', onSessionEnded);\n const { begin, sessionValue } = start(client);\n try {\n await client.query(begin);\n const result = await work(client);\n const { command } = await client.query('COMMIT');\n // Settings changed in a transaction that rolls back (a failed one answers COMMIT with ROLLBACK)\n // return to what the session had before.\n if (command === 'COMMIT') {\n this.#recordSession(client, sessionValue);\n }\n release(false);\n return result;\n } catch (error) {\n await this.#rollbackAndRelease(client, release);\n throw error;\n }\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n async query(\n sql: string,\n parameters: readonly PostgresParameter[],\n transaction?: PoolClient,\n options?: PostgresQueryOptions,\n ): Promise<readonly PostgresRow[]> {\n const queryable = transaction ?? this.#pool;\n const values = [...parameters];\n if (options?.prepare !== true || !this.#preparing) {\n return (await queryable.query<PostgresRow>(sql, values)).rows;\n }\n try {\n return (await queryable.query<PostgresRow>({ name: this.#nameOf(sql), text: sql, values }))\n .rows;\n } catch (error) {\n if (!FOREIGN_SESSION_ERRORS.has((error as { code?: unknown }).code as string)) {\n throw error;\n }\n if (this.#preparing) {\n this.#preparing = false;\n this.#logger.warn(\n `[PgExecutor](query) The server does not keep prepared statements per connection, statements are sent unprepared from now on; set preparedStatements: false to skip this check | code=${String((error as { code?: unknown }).code)}`,\n );\n }\n if (transaction !== undefined) {\n throw error;\n }\n return (await queryable.query<PostgresRow>(sql, values)).rows;\n }\n }\n\n /** `relaybus_` and 24 hex digits of the SHA-256 of the text: well under the 63 bytes of an identifier. */\n #nameOf(sql: string): string {\n let name = this.#names.get(sql);\n if (name === undefined) {\n name = `relaybus_${createHash('sha256').update(sql).digest('hex').slice(0, STATEMENT_NAME_DIGITS)}`;\n this.#names.set(sql, name);\n }\n return name;\n }\n\n /** A client whose rollback fails is in an unknown state, so it is destroyed instead of reused. */\n async #rollbackAndRelease(\n client: PoolClient,\n release: (destroy: boolean) => void,\n ): Promise<void> {\n try {\n await client.query('ROLLBACK');\n release(false);\n } catch {\n release(true);\n }\n }\n}\n","import { ConfigurationError } from '@relaybus/core';\n\nconst IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_]*$/;\nconst MAXIMUM_IDENTIFIER_LENGTH = 63;\n\n/**\n * Throws {@link ConfigurationError} unless `value` is a plain lower-case\n * PostgreSQL identifier. Identifiers are interpolated into SQL text (they\n * cannot be bound as parameters), so this is the injection boundary: only\n * letters, digits and underscores survive, and nothing needs escaping.\n */\nexport function assertIdentifier(label: string, value: string): void {\n if (!IDENTIFIER_PATTERN.test(value) || value.length > MAXIMUM_IDENTIFIER_LENGTH) {\n throw new ConfigurationError(\n `${label} '${value}' must match ${String(IDENTIFIER_PATTERN)} and be at most ${MAXIMUM_IDENTIFIER_LENGTH} characters`,\n );\n }\n}\n\n/** Double-quotes an identifier that already passed {@link assertIdentifier}. */\nexport function quoteIdentifier(value: string): string {\n return `\"${value}\"`;\n}\n","import { ConfigurationError } from '@relaybus/core';\nimport { createHash } from 'node:crypto';\nimport { assertIdentifier, quoteIdentifier } from './identifiers.js';\n\n/** Where relaybus keeps its tables. */\nexport interface PostgresSchemaOptions {\n /** Schema that holds the tables. Created by `setup()` when it is not `public`. Default `'public'`. */\n readonly schema?: string;\n /**\n * Prepended to every table and index name, which makes the names\n * `<prefix>events`, `<prefix>deliveries` and `<prefix>key_sequences`.\n * Lower-case letters, digits and underscores. Default `'relaybus_'`.\n */\n readonly tablePrefix?: string;\n /**\n * Keep an append-only record of completed deliveries in\n * `<prefix>completed_deliveries`, so `listDeliveries({ status: 'completed' })`,\n * `statistics().completed` and `retention.completed` keep working. Default\n * `false`: a completed delivery is deleted, which avoids the dead tuples and\n * index churn of updating it. Use the same value in every process.\n */\n readonly completionHistory?: boolean;\n}\n\n/** Validated, quoted names used to build SQL. */\nexport interface PostgresNames {\n readonly schema: string;\n readonly quotedSchema: string;\n readonly events: string;\n /** Unquoted, unqualified name of {@link events}, for catalog lookups. */\n readonly eventsTableName: string;\n readonly deliveries: string;\n readonly keySequences: string;\n /** Lane lease rows: one per lane, see {@link LANE_COUNT}. */\n readonly lanes: string;\n /** Unquoted, unqualified name of {@link lanes}, for catalog lookups. */\n readonly lanesTableName: string;\n /** One row per event that had a delivery complete: when the last one did. Retention of completed work is measured from it. */\n readonly eventCompletions: string;\n /** Completion history, present only with `completionHistory`. */\n readonly completions: string;\n readonly completionHistory: boolean;\n /**\n * Channel of the notifications that wake dispatchers when deliveries were published:\n * `<schema>.<prefix>deliveries`, or a hash of it when that is longer than a channel name may be.\n */\n readonly notificationChannel: string;\n /** Index names, quoted but not schema-qualified (an index lives in its table's schema). */\n readonly indexes: {\n readonly deliveryEventHandler: string;\n readonly deliveryLaneDue: string;\n readonly deliveryKeyPending: string;\n readonly eventCreated: string;\n readonly deliveryCompleted: string;\n readonly deliveryDead: string;\n readonly completionCompleted: string;\n readonly eventCompletionsCompleted: string;\n /** Indexes of the 0.1.0 schema that the current schema drops. */\n readonly obsolete: readonly string[];\n };\n}\n\n/**\n * Number of lanes. Every delivery belongs to the lane of its ordering key (or of\n * its event id when the event has no key); workers lease whole lanes. The count\n * is fixed because the lane of a delivery is stored, and all processes must\n * agree on it.\n */\nexport const LANE_COUNT = 256;\n\nconst DEFAULT_SCHEMA = 'public';\nconst MAXIMUM_CHANNEL_LENGTH = 63;\nconst DEFAULT_TABLE_PREFIX = 'relaybus_';\nconst TABLE_PREFIX_PATTERN = /^[a-z0-9_]*$/;\n\n/** Derives the names of every index, current and obsolete, from the index-name builder. */\nfunction indexNames(index: (suffix: string) => string): PostgresNames['indexes'] {\n return {\n deliveryEventHandler: index('deliveries_event_handler_unique'),\n deliveryLaneDue: index('deliveries_lane_due_idx'),\n deliveryKeyPending: index('deliveries_key_pending_idx'),\n eventCreated: index('events_created_idx'),\n deliveryCompleted: index('deliveries_completed_idx'),\n deliveryDead: index('deliveries_dead_idx'),\n completionCompleted: index('completed_deliveries_completed_idx'),\n eventCompletionsCompleted: index('event_completions_completed_idx'),\n obsolete: [\n index('deliveries_due_idx'),\n index('deliveries_due_unkeyed_idx'),\n index('deliveries_handler_created_idx'),\n index('deliveries_key_unfinished_idx'),\n index('deliveries_key_processing_idx'),\n index('deliveries_status_created_idx'),\n ],\n };\n}\n\n/**\n * Validates the options and derives every name the store uses. Every name,\n * including the longest index name, is checked against the PostgreSQL 63\n * character limit so that a too-long prefix fails here and not as a\n * silently truncated, colliding name in the database.\n */\nexport function resolvePostgresNames(options: PostgresSchemaOptions = {}): PostgresNames {\n const schema = options.schema ?? DEFAULT_SCHEMA;\n const tablePrefix = options.tablePrefix ?? DEFAULT_TABLE_PREFIX;\n assertIdentifier('schema', schema);\n if (!TABLE_PREFIX_PATTERN.test(tablePrefix)) {\n throw new ConfigurationError(\n `tablePrefix '${tablePrefix}' must match ${String(TABLE_PREFIX_PATTERN)}`,\n );\n }\n const name = (suffix: string): string => {\n const identifier = `${tablePrefix}${suffix}`;\n assertIdentifier(`tablePrefix '${tablePrefix}' produces the name`, identifier);\n return identifier;\n };\n const quotedSchema = quoteIdentifier(schema);\n const table = (suffix: string): string => `${quotedSchema}.${quoteIdentifier(name(suffix))}`;\n const index = (suffix: string): string => quoteIdentifier(name(suffix));\n return {\n schema,\n quotedSchema,\n events: table('events'),\n eventsTableName: name('events'),\n deliveries: table('deliveries'),\n keySequences: table('key_sequences'),\n lanes: table('lanes'),\n lanesTableName: name('lanes'),\n eventCompletions: table('event_completions'),\n completions: table('completed_deliveries'),\n completionHistory: options.completionHistory ?? false,\n notificationChannel: channelName(`${schema}.${tablePrefix}deliveries`),\n indexes: indexNames(index),\n };\n}\n\n/** Hex digits of the hash that names a channel whose readable name is too long. */\nconst CHANNEL_HASH_DIGITS = 32;\n\n/** PostgreSQL truncates names longer than 63 bytes, which could merge channels: those are hashed instead. */\nfunction channelName(readable: string): string {\n return readable.length <= MAXIMUM_CHANNEL_LENGTH\n ? readable\n : `relaybus_${createHash('sha256').update(readable).digest('hex').slice(0, CHANNEL_HASH_DIGITS)}`;\n}\n","import { LANE_COUNT } from './names.js';\n\n/**\n * Renders a timestamptz as ISO-8601 text in UTC. Reading timestamps as text\n * makes results independent of the driver's type parsers (Drizzle, for\n * instance, replaces them) and of the session time zone.\n */\nexport function isoText(expression: string): string {\n return `to_char(${expression} AT TIME ZONE 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`;\n}\n\n/**\n * The lane of a delivery: a hash of the ordering key, or of the event id when\n * the event has no key. All deliveries of one key therefore share a lane and\n * are owned by one worker at a time, which is what keeps their order.\n * `hashtextextended` is stable across PostgreSQL versions and platforms.\n */\nexport function laneExpression(keyExpression: string, eventIdExpression: string): string {\n return `(hashtextextended(COALESCE(${keyExpression}, ${eventIdExpression}), 0) & ${LANE_COUNT - 1})::smallint`;\n}\n","import { createHash } from 'node:crypto';\nimport {\n LANE_COUNT,\n resolvePostgresNames,\n type PostgresNames,\n type PostgresSchemaOptions,\n} from './names.js';\nimport { laneExpression } from './sql-fragments.js';\n\n/** Hex digits of the statement hash in the schema marker. */\nconst SCHEMA_MARKER_DIGITS = 32;\n\n/** The payload and headers columns of the event table, and as 0.4.0 and earlier created them. */\nconst PAYLOAD_COLUMNS = ` payload json NOT NULL,\n headers json NOT NULL DEFAULT '{}'::json,`;\nconst JSONB_PAYLOAD_COLUMNS = ` payload jsonb NOT NULL,\n headers jsonb NOT NULL DEFAULT '{}'::jsonb,`;\n\n/**\n * Statements that create the schema, tables and indexes, in dependency order,\n * and upgrade a 0.1.0 schema and the `jsonb` payload columns of schemas before 0.4.1 in place.\n * Every statement is idempotent (`IF NOT EXISTS`, or guarded by a check for the old columns). Run them in\n * one transaction and serialize concurrent runs (see\n * {@link PostgresEventStore.setup}), or paste {@link createPostgresSchemaSql}\n * into your own migration tool.\n *\n * `events.id` and `deliveries.id` are `text` so that any caller-supplied id\n * (UUID, ULID, deterministic business id) is accepted. `deliveries.id` uses the\n * `C` collation so that ordering by id matches a byte-wise comparison on every\n * database, whatever its locale.\n *\n * A delivery row is written once (insert) and removed once (delete) on the\n * normal path. The lease lives in the lane row a delivery belongs to, so\n * claiming, renewing and completing never update an indexed column of the\n * delivery. The lane table is tiny, has no index besides its primary key and\n * leaves free space in its pages, so its updates are heap-only (HOT).\n */\nexport function createPostgresSchemaStatements(options: PostgresSchemaOptions = {}): string[] {\n const names = resolvePostgresNames(options);\n const statements = schemaBodyStatements(names);\n statements.push(`COMMENT ON TABLE ${names.lanes} IS '${version040Marker(names, statements)}'`);\n return statements;\n}\n\n/** The schema statements without the marker comment. */\nfunction schemaBodyStatements(names: PostgresNames): string[] {\n const statements = [...eventAndDeliveryStatements(names), ...laneAndCompletionStatements(names)];\n if (names.completionHistory) {\n statements.push(...completionHistoryStatements(names));\n }\n if (names.schema !== 'public') {\n statements.unshift(`CREATE SCHEMA IF NOT EXISTS ${names.quotedSchema}`);\n }\n return statements;\n}\n\n/** The event, key sequence and delivery tables, their upgrades and indexes. */\nfunction eventAndDeliveryStatements(names: PostgresNames): string[] {\n return [...eventAndKeySequenceStatements(names), ...deliveryStatements(names)];\n}\n\n/** The event table with its index, and the key sequence table. */\nfunction eventAndKeySequenceStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.events} (\n id text PRIMARY KEY,\n type text NOT NULL,\n source text NOT NULL,\n key text,\n sequence bigint,\n${PAYLOAD_COLUMNS}\n correlation_id text,\n causation_id text,\n occurred_at timestamptz NOT NULL,\n created_at timestamptz NOT NULL,\n handlers text[] NOT NULL DEFAULT '{}'\n)`,\n upgradePayloadToJson(names),\n `CREATE INDEX IF NOT EXISTS ${names.indexes.eventCreated} ON ${names.events} (created_at, id)`,\n `CREATE TABLE IF NOT EXISTS ${names.keySequences} (\n key text PRIMARY KEY,\n sequence bigint NOT NULL\n)`,\n ];\n}\n\n/** The delivery table, the 0.1.0 upgrade, the obsolete index drops and the current indexes. */\nfunction deliveryStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.deliveries} (\n id text COLLATE \"C\" PRIMARY KEY,\n event_id text NOT NULL REFERENCES ${names.events} (id) ON DELETE CASCADE,\n handler text NOT NULL,\n lane smallint NOT NULL,\n claims integer NOT NULL DEFAULT 0,\n status text NOT NULL CHECK (status IN ('pending', 'processing', 'completed', 'dead')),\n attempts integer NOT NULL DEFAULT 0,\n available_at timestamptz NOT NULL,\n last_error jsonb,\n key text,\n sequence bigint,\n created_at timestamptz NOT NULL,\n updated_at timestamptz NOT NULL,\n completed_at timestamptz,\n CONSTRAINT ${names.indexes.deliveryEventHandler} UNIQUE (event_id, handler)\n) WITH (autovacuum_vacuum_scale_factor = 0.02, autovacuum_analyze_scale_factor = 0.05)`,\n upgradeFromVersion010(names),\n `ALTER TABLE ${names.deliveries} ADD COLUMN IF NOT EXISTS claims integer NOT NULL DEFAULT 0`,\n `ALTER TABLE ${names.deliveries} SET (autovacuum_vacuum_scale_factor = 0.02, autovacuum_analyze_scale_factor = 0.05)`,\n ...names.indexes.obsolete.map((index) => `DROP INDEX IF EXISTS ${names.quotedSchema}.${index}`),\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryLaneDue} ON ${names.deliveries} (lane, available_at, id) WHERE status = 'pending'`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryKeyPending} ON ${names.deliveries} (lane, handler, key, sequence) WHERE key IS NOT NULL AND status = 'pending'`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryCompleted} ON ${names.deliveries} (completed_at, id) WHERE status = 'completed'`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryDead} ON ${names.deliveries} (updated_at, id) WHERE status = 'dead'`,\n ];\n}\n\n/** The lane and event completion tables, and the lane rows. */\nfunction laneAndCompletionStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.lanes} (\n lane smallint PRIMARY KEY CHECK (lane >= 0 AND lane < ${LANE_COUNT}),\n epoch bigint NOT NULL DEFAULT 0,\n lease_owner text,\n lease_expires_at timestamptz,\n in_flight text[] NOT NULL DEFAULT '{}',\n claim_floor bigint NOT NULL DEFAULT 0\n) WITH (fillfactor = 50)`,\n `ALTER TABLE ${names.lanes} ADD COLUMN IF NOT EXISTS claim_floor bigint NOT NULL DEFAULT 0`,\n `CREATE TABLE IF NOT EXISTS ${names.eventCompletions} (\n event_id text PRIMARY KEY REFERENCES ${names.events} (id) ON DELETE CASCADE,\n completed_at timestamptz NOT NULL\n)`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.eventCompletionsCompleted} ON ${names.eventCompletions} (completed_at, event_id)`,\n `INSERT INTO ${names.lanes} (lane) SELECT generate_series(0, ${LANE_COUNT - 1})::smallint ON CONFLICT (lane) DO NOTHING`,\n ];\n}\n\n/** The completion history table, kept with `completionHistory: true`. */\nfunction completionHistoryStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.completions} (\n id text COLLATE \"C\" PRIMARY KEY,\n event_id text NOT NULL REFERENCES ${names.events} (id) ON DELETE CASCADE,\n handler text NOT NULL,\n attempts integer NOT NULL,\n available_at timestamptz NOT NULL,\n created_at timestamptz NOT NULL,\n completed_at timestamptz NOT NULL\n)`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.completionCompleted} ON ${names.completions} (completed_at, id)`,\n ];\n}\n\n/**\n * A schema marker: the hash of `statements`. The last schema statement leaves one on the lane table\n * ({@link version040SchemaMarker}), and {@link PostgresEventStore.setup} reads it to skip the\n * statements when the schema is already current, because their table locks queue behind running\n * claims and completions and deadlock with them.\n */\nfunction postgresSchemaMarker(statements: readonly string[]): string {\n return `relaybus schema ${createHash('sha256').update(statements.join(';')).digest('hex').slice(0, SCHEMA_MARKER_DIGITS)}`;\n}\n\n/**\n * Upgrades a 0.1.0 deliveries table, recognized by its `lease_token` column.\n * Rows keep their ids, attempts and payload references. Deliveries that were\n * `processing` become `pending` (their attempt stays counted, as a lost lease\n * would count it), every row gets its lane, every event learns which handlers\n * it already has deliveries for, and the per-delivery lease columns go. Deliveries completed under 0.1.0 stay as `completed` rows until\n * `retention.completed` purges them. Stop all 0.1.0 workers before the first\n * run: they cannot use the upgraded tables.\n */\nfunction upgradeFromVersion010(names: ReturnType<typeof resolvePostgresNames>): string {\n return `DO $relaybus_upgrade$\nBEGIN\n IF EXISTS (\n SELECT 1 FROM pg_attribute\n WHERE attrelid = '${names.deliveries}'::regclass AND attname = 'lease_token' AND NOT attisdropped\n ) THEN\n ALTER TABLE ${names.events} ADD COLUMN IF NOT EXISTS handlers text[] NOT NULL DEFAULT '{}';\n UPDATE ${names.events} AS event SET handlers = known.handlers\n FROM (\n SELECT event_id, array_agg(handler) AS handlers FROM ${names.deliveries} GROUP BY event_id\n ) AS known\n WHERE event.id = known.event_id;\n ALTER TABLE ${names.deliveries} ADD COLUMN IF NOT EXISTS lane smallint;\n UPDATE ${names.deliveries} SET lane = ${laneExpression('key', 'event_id')} WHERE lane IS NULL;\n ALTER TABLE ${names.deliveries} ALTER COLUMN lane SET NOT NULL;\n UPDATE ${names.deliveries} SET status = 'pending' WHERE status = 'processing';\n ALTER TABLE ${names.deliveries}\n DROP COLUMN lease_owner, DROP COLUMN lease_token, DROP COLUMN lease_expires_at;\n END IF;\nEND\n$relaybus_upgrade$`;\n}\n\n/**\n * Turns the `jsonb` payload and headers columns of a schema created before 0.4.1 into `json`, which\n * keeps the text the producer serialized: `jsonb` re-orders object keys, so an event read back\n * serialized differently from what was published. One table rewrite under an exclusive lock; rows\n * stored before the upgrade keep the key order `jsonb` gave them. A no-op once both columns are\n * `json`, and when the table does not exist yet. {@link PostgresEventStore.setup} runs it in a\n * transaction of its own before the other statements, so it holds no other table lock while it\n * waits for the event table (a completion locks deliveries before the event rows it references).\n */\nexport function upgradePayloadToJson(names: PostgresNames): string {\n return `DO $relaybus_payload_json$\nBEGIN\n IF EXISTS (\n SELECT 1 FROM pg_attribute\n WHERE attrelid = to_regclass('${names.events}') AND attname IN ('payload', 'headers')\n AND atttypid = 'jsonb'::regtype AND NOT attisdropped\n ) THEN\n ALTER TABLE ${names.events}\n ALTER COLUMN headers DROP DEFAULT,\n ALTER COLUMN payload TYPE json USING payload::json,\n ALTER COLUMN headers TYPE json USING headers::json,\n ALTER COLUMN headers SET DEFAULT '{}'::json;\n END IF;\nEND\n$relaybus_payload_json$`;\n}\n\n/**\n * The schema marker 0.4.0 writes, which 0.4.1 keeps writing: the hash of the schema statements without\n * the payload conversion and with the `jsonb` columns of 0.4.0. A 0.4.0 instance started next to 0.4.1,\n * or after a rollback, then still finds its marker and runs no schema statement, whose table locks could\n * deadlock with running claims. Whether the payload columns are converted is read from the column types\n * instead (see {@link SetupStatements.schemaCurrent}).\n */\nexport function version040SchemaMarker(options: PostgresSchemaOptions = {}): string {\n const names = resolvePostgresNames(options);\n return version040Marker(names, schemaBodyStatements(names));\n}\n\n/** {@link version040SchemaMarker} of the body statements of {@link schemaBodyStatements}. */\nfunction version040Marker(names: PostgresNames, statements: readonly string[]): string {\n const conversion = upgradePayloadToJson(names);\n return postgresSchemaMarker(\n statements\n .filter((statement) => statement !== conversion)\n .map((statement) => statement.replace(PAYLOAD_COLUMNS, JSONB_PAYLOAD_COLUMNS)),\n );\n}\n\n/**\n * The statements of {@link createPostgresSchemaStatements} as one SQL script,\n * for migration tools. Pair it with `new RelayBus({ setupStore: false })`.\n */\nexport function createPostgresSchemaSql(options: PostgresSchemaOptions = {}): string {\n return `${createPostgresSchemaStatements(options).join(';\\n\\n')};\\n`;\n}\n","import type { RelayBusLogger } from '@relaybus/core';\nimport { systemClock } from '@relaybus/core';\nimport { schedule, type CancelTimer } from '@relaybus/core/internal';\n\n/** Wait before a lost listening connection is opened again. */\nconst RECONNECT_DELAY_MS = 1_000;\n\n/** What the listener needs of a connection: a `pg` `Client` has it. */\nexport interface ListeningConnection {\n on(event: 'notification', listener: () => void): unknown;\n on(event: 'error', listener: (error: Error) => void): unknown;\n on(event: 'end', listener: () => void): unknown;\n query(sql: string): Promise<unknown>;\n end(): Promise<void>;\n}\n\n/**\n * Returns a function that ends the connection once, however often it is called. `ended` is set\n * first because ending can report the end synchronously, which calls back into the loss handler.\n */\nfunction endOnce(connection: ListeningConnection, ended: { value: boolean }): () => Promise<void> {\n let ending: Promise<void> = Promise.resolve();\n return () => {\n if (!ended.value) {\n ended.value = true;\n ending = connection.end().catch(() => undefined);\n }\n return ending;\n };\n}\n\n/**\n * Holds one connection of its own (outside any pool, so it never takes a connection the store needs)\n * that `LISTEN`s on a channel, and calls a listener for every notification. The notifications are hints\n * for the dispatcher, never needed for correctness: when the connection is lost it is replaced after a\n * pause, and the listener is called once for whatever was sent meanwhile.\n */\nexport class NotificationListener {\n readonly #connect: () => Promise<ListeningConnection>;\n readonly #channel: string;\n readonly #listener: () => void;\n readonly #logger: RelayBusLogger;\n /** Ends the current connection, listening or still starting; undefined while there is none. */\n #drop: (() => Promise<void>) | undefined;\n #reconnectTimer: CancelTimer | undefined;\n #closed = false;\n\n constructor(\n connect: () => Promise<ListeningConnection>,\n channel: string,\n listener: () => void,\n logger: RelayBusLogger,\n ) {\n this.#connect = connect;\n this.#channel = channel;\n this.#listener = listener;\n this.#logger = logger;\n }\n\n /** Connects and listens. Rejects when that fails; a connection lost later is replaced. */\n async start(): Promise<void> {\n const connection = await this.#connect();\n const ended = { value: false };\n const end = endOnce(connection, ended);\n if (this.#closed) {\n await end();\n return;\n }\n // Registered before LISTEN, so closing ends a connection whose LISTEN has not answered yet.\n this.#drop = end;\n let listening = false;\n const onLost = (error?: Error): void => {\n if (!listening || ended.value) {\n // While starting, a failure surfaces as the rejection of LISTEN, which ends the connection.\n return;\n }\n void end();\n // Only a listening connection gets here, and it is always the current one.\n this.#drop = undefined;\n this.#logger.warn(\n `[NotificationListener](start) Listening connection lost, opening another | channel=${this.#channel} | error=${error?.message ?? 'connection ended'}`,\n );\n this.#scheduleReconnect();\n };\n connection.on('error', onLost);\n connection.on('end', () => onLost());\n connection.on('notification', () => this.#listener());\n try {\n await connection.query(`LISTEN \"${this.#channel}\"`);\n } catch (error) {\n await this.#abandonFailedListen(end, error);\n return;\n }\n if (this.#closed) {\n await end();\n return;\n }\n listening = true;\n }\n\n /** Forgets and ends a connection whose LISTEN failed; rethrows the failure unless closing caused it. */\n async #abandonFailedListen(end: () => Promise<void>, error: unknown): Promise<void> {\n if (this.#drop === end) {\n this.#drop = undefined;\n }\n await end();\n if (this.#closed) {\n // Closing ended the connection while LISTEN was pending: not a failure to report.\n return;\n }\n throw error;\n }\n\n #scheduleReconnect(): void {\n this.#reconnectTimer = schedule(systemClock, {\n run: () => {\n this.#reconnectTimer = undefined;\n this.start().then(\n () => {\n if (!this.#closed) {\n this.#listener();\n }\n },\n (error: unknown) => {\n this.#logger.warn(\n `[NotificationListener](scheduleReconnect) Listening again failed, retrying | channel=${this.#channel} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n if (!this.#closed) {\n this.#scheduleReconnect();\n }\n },\n );\n },\n delayMs: RECONNECT_DELAY_MS,\n unref: true,\n });\n }\n\n /** Stops listening for good and ends the connection. */\n async close(): Promise<void> {\n this.#closed = true;\n this.#reconnectTimer?.();\n const drop = this.#drop;\n this.#drop = undefined;\n await drop?.();\n }\n}\n","import type { PoolClient } from 'pg';\nimport type { PostgresExecutor } from './executor.js';\n\n/**\n * An executor whose transactions (and the statements in them) belong to `executor`, the application's\n * library, while statements outside a transaction run on `root`, a `PgExecutor` on a `pg` pool of the\n * same database that keeps them as prepared statements.\n */\nexport function withRootPool<TTransaction>(\n executor: PostgresExecutor<TTransaction>,\n root: PostgresExecutor<PoolClient>,\n): PostgresExecutor<TTransaction> {\n return {\n ...(executor.sessionTimeouts === undefined\n ? {}\n : { sessionTimeouts: executor.sessionTimeouts }),\n transaction: (work) => executor.transaction(work),\n ...(executor.transactionWithBudget === undefined\n ? {}\n : {\n transactionWithBudget: (work, timeoutMs) =>\n executor.transactionWithBudget!(work, timeoutMs),\n }),\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction, options) =>\n transaction === undefined\n ? root.query(sql, parameters, undefined, options)\n : executor.query(sql, parameters, transaction, options),\n };\n}\n","import type {\n ClaimedDelivery,\n DeliveryRecord,\n DeliveryStatus,\n ErrorInfo,\n EventEnvelope,\n EventHeaders,\n} from '@relaybus/core';\nimport { LaneLeaseTokenFormat, type LaneLeaseTokenParts } from '@relaybus/core/internal';\nimport type { PostgresRow } from './executor.js';\nimport { LANE_COUNT } from './names.js';\n\n// Rows come from statements written in this package, so their shape is known.\n// Casting here is the single place where driver output is trusted.\n\nfunction text(row: PostgresRow, column: string): string {\n return row[column] as string;\n}\n\nfunction nullableText(row: PostgresRow, column: string): string | null {\n return row[column] as string | null;\n}\n\nfunction nullableDate(row: PostgresRow, column: string): Date | null {\n const value = nullableText(row, column);\n return value === null ? null : new Date(value);\n}\n\n/** Count columns arrive as number, string or bigint depending on the driver. */\nexport function readCount(row: PostgresRow, column: string): number {\n return Number(row[column]);\n}\n\nexport function mapEventEnvelope(row: PostgresRow): EventEnvelope {\n return {\n id: text(row, 'event_id'),\n type: text(row, 'event_type'),\n source: text(row, 'event_source'),\n key: nullableText(row, 'event_key'),\n payload: JSON.parse(text(row, 'event_payload')) as unknown,\n headers: JSON.parse(text(row, 'event_headers')) as EventHeaders,\n correlationId: nullableText(row, 'event_correlation_id'),\n causationId: nullableText(row, 'event_causation_id'),\n occurredAt: new Date(text(row, 'event_occurred_at')),\n };\n}\n\n/** Lease tokens of this store: epochs are bigint text of up to 18 digits. */\nconst LEASE_TOKENS = new LaneLeaseTokenFormat({\n laneCount: LANE_COUNT,\n epochDigits: 18,\n claimsDigits: 9,\n});\n\n/**\n * The fencing token of a claimed delivery names its lane and the lane's epoch,\n * so every state change can check the lane without reading the delivery first.\n */\nexport function formatLeaseToken(\n lane: number,\n { epoch, claims }: { readonly epoch: string; readonly claims: number },\n): string {\n return LEASE_TOKENS.format(lane, { epoch, claims });\n}\n\n/**\n * A lane lease: lane, epoch and claim generation. `claims` counts the claims of this delivery\n * that ended before this one; every end of a claim bumps it, so an old lease can never match a\n * newer claim.\n */\nexport type LaneLease = LaneLeaseTokenParts;\n\n/** Splits a lease token; undefined when it was not issued by this store. */\nexport function parseLeaseToken(token: string): LaneLease | undefined {\n return LEASE_TOKENS.parse(token);\n}\n\nexport function mapClaimedDelivery(row: PostgresRow, leaseExpiresAt: Date): ClaimedDelivery {\n return {\n deliveryId: text(row, 'delivery_id'),\n leaseToken: formatLeaseToken(readCount(row, 'lane'), {\n epoch: text(row, 'epoch'),\n claims: readCount(row, 'claims'),\n }),\n handler: text(row, 'handler'),\n attempt: readCount(row, 'attempt'),\n leaseExpiresAt,\n event: mapEventEnvelope(row),\n };\n}\n\nexport function mapDeliveryRecord(row: PostgresRow): DeliveryRecord {\n const lastError = nullableText(row, 'last_error');\n return {\n id: text(row, 'delivery_id'),\n handler: text(row, 'handler'),\n status: text(row, 'status') as DeliveryStatus,\n attempts: readCount(row, 'attempts'),\n availableAt: new Date(text(row, 'available_at')),\n leaseOwner: nullableText(row, 'lease_owner'),\n leaseExpiresAt: nullableDate(row, 'lease_expires_at'),\n lastError: lastError === null ? null : (JSON.parse(lastError) as ErrorInfo),\n createdAt: new Date(text(row, 'created_at')),\n updatedAt: new Date(text(row, 'updated_at')),\n completedAt: nullableDate(row, 'completed_at'),\n event: mapEventEnvelope(row),\n };\n}\n\nexport function mapOldestDueAt(rows: readonly PostgresRow[]): Date | null {\n return nullableDate(rows[0]!, 'oldest_due_at');\n}\n","import {\n systemClock,\n type AppendEntry,\n type AppendResult,\n type EventEnvelope,\n} from '@relaybus/core';\nimport { CompositeKey, schedule } from '@relaybus/core/internal';\nimport type { PostgresRow } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { readCount } from './row-mapping.js';\n\n/**\n * Least time between two wake-up notifications of one store. A transaction that sends `NOTIFY` holds a\n * database-wide lock from its commit until the commit is flushed, so a notification per publishing\n * transaction made concurrent publishers commit one at a time.\n */\nconst NOTIFICATION_INTERVAL_MS = 10;\n\ninterface EventRow {\n readonly id: string;\n readonly type: string;\n readonly source: string;\n readonly key: string | null;\n readonly sequence: string | null;\n readonly payload: unknown;\n readonly headers: EventEnvelope['headers'];\n readonly correlation_id: string | null;\n readonly causation_id: string | null;\n readonly occurred_at: string;\n readonly handlers: readonly string[];\n}\n\ninterface DeliveryRow {\n readonly id: string;\n readonly event_id: string;\n readonly handler: string;\n readonly available_at: string;\n}\n\n/** What `#appendToExistingEvents` needs from the append that found existing events. */\ntype AppendToExistingEventsInput = {\n readonly plan: AppendPlan;\n readonly fresh: readonly PostgresRow[];\n readonly deliveries: readonly DeliveryRow[];\n readonly handlersByEvent: ReadonlyMap<string, string[]>;\n /** Grows by every event that turns out to be gone and is inserted again. */\n readonly insertedEventIds: Set<string>;\n readonly createdAt: string;\n readonly wakeAt: string | null;\n};\n\n/** appender */\nexport class PostgresAppend<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n this.#state = state;\n }\n\n /** Implements {@link PostgresEventStore.append}. */\n async append(\n transaction: TTransaction,\n { entries, now }: { readonly entries: readonly AppendEntry[]; readonly now: Date },\n ): Promise<AppendResult> {\n const plan = planAppend(entries);\n if (plan.events.length === 0) {\n return { appendedEventIds: [], duplicateEventIds: [], appendedDeliveryCount: 0 };\n }\n const createdAt = now.toISOString();\n const wakeAt = this.#wakeAt(plan.deliveries, { now, transaction });\n const handlersByEvent = handlersByEventOf(plan.deliveries);\n const fresh = await this.#insertFreshEvents(transaction, {\n plan,\n handlersByEvent,\n createdAt,\n wakeAt,\n });\n const insertedEventIds = new Set(\n fresh.filter((row) => row['inserted'] === true).map((row) => row['id'] as string),\n );\n let appendedDeliveryCount = readCount(fresh[0]!, 'deliveries');\n const remaining = plan.deliveries.filter(\n (delivery) => !insertedEventIds.has(delivery.event_id),\n );\n if (remaining.length > 0) {\n appendedDeliveryCount += await this.#appendToExistingEvents(transaction, {\n plan,\n fresh,\n deliveries: remaining,\n handlersByEvent,\n insertedEventIds,\n createdAt,\n wakeAt,\n });\n }\n return { ...splitOutcomes(plan, insertedEventIds), appendedDeliveryCount };\n }\n\n /** Runs the publishing statement that inserts the events not stored yet, with their deliveries. */\n async #insertFreshEvents(\n transaction: TTransaction,\n {\n plan,\n handlersByEvent,\n createdAt,\n wakeAt,\n }: {\n readonly plan: AppendPlan;\n readonly handlersByEvent: ReadonlyMap<string, string[]>;\n readonly createdAt: string;\n readonly wakeAt: string | null;\n },\n ): Promise<readonly PostgresRow[]> {\n const keyCounts = keyCountsOf(plan.events);\n return this.#state.query({\n sql: this.#state.statements.append.insertFreshEvents,\n parameters: [\n JSON.stringify(\n plan.events.map((event, ordinal) => ({\n ordinal,\n ...toEventRow(event, { sequence: null, handlers: handlersByEvent.get(event.id) ?? [] }),\n })),\n ),\n createdAt,\n JSON.stringify(plan.deliveries),\n JSON.stringify([...keyCounts].map(([key, count]) => ({ key, count }))),\n wakeAt,\n ],\n transaction,\n });\n }\n\n /** Locks the given events and returns the ids of those that still exist. */\n async #lockExistingEvents(\n transaction: TTransaction,\n existing: readonly EventRow[],\n ): Promise<Set<string>> {\n const locked = await this.#state.query({\n sql: this.#state.statements.append.lockExistingEvents,\n parameters: [JSON.stringify(existing.map((row) => row.id).sort())],\n transaction,\n });\n return new Set(locked.map((row) => row['id'] as string));\n }\n\n /**\n * The time the publishing statements notify the dispatchers for (deliveries due by then wake them),\n * or `null` for no notification. An append in a transaction of the caller's always notifies, at its\n * commit. In a transaction of this store, only the first append within {@link NOTIFICATION_INTERVAL_MS}\n * does; the others leave the wake-up to {@link #wakeAfterCommit}, which runs once their transaction\n * committed, so no committed delivery waits for the poll.\n */\n #wakeAt(\n deliveries: readonly DeliveryRow[],\n { now, transaction }: { readonly now: Date; readonly transaction: TTransaction },\n ): string | null {\n if (\n !this.#state.notifies ||\n !deliveries.some((delivery) => Date.parse(delivery.available_at) <= now.getTime())\n ) {\n return null;\n }\n const own = this.#state.ownTransactions.get(transaction);\n if (\n own !== undefined &&\n Date.now() - this.#state.lastNotificationAt < NOTIFICATION_INTERVAL_MS\n ) {\n own.wake = true;\n return null;\n }\n this.#state.lastNotificationAt = Date.now();\n return now.toISOString();\n }\n\n /**\n * Wakes the dispatchers for a committed transaction whose appends sent no notification: at once when\n * none was sent within {@link NOTIFICATION_INTERVAL_MS}, otherwise once when the interval ends. A\n * wake-up already scheduled covers this transaction too, since it is sent after this commit. Nothing is\n * sent once the store is closed or the `pg` pool behind it is ending: no dispatcher can be woken through\n * it then, and the deliveries are found by polling.\n */\n wakeAfterCommit(): void {\n if (this.#state.trailingNotification !== undefined || this.#state.closed) {\n return;\n }\n this.#state.trailingNotification = schedule(systemClock, {\n run: () => {\n this.#state.trailingNotification = undefined;\n if (this.#state.pool?.ending === true) {\n return;\n }\n this.#state.lastNotificationAt = Date.now();\n this.#state\n .query({ sql: this.#state.statements.append.notify, parameters: [] })\n .catch((error: unknown) => {\n this.#state.logger.error(\n `[PostgresAppend](wakeAfterCommit) Waking the dispatchers failed, they find the deliveries when they poll | error=${error instanceof Error ? error.message : String(error)}`,\n );\n });\n },\n delayMs: Math.max(0, this.#state.lastNotificationAt + NOTIFICATION_INTERVAL_MS - Date.now()),\n });\n }\n\n /**\n * Adds the deliveries of events the publishing statement found already stored. An event that already\n * exists may be getting the same new handler from another transaction at this very moment. Whoever\n * holds the event decides, so the freshness check of the insert sees what the other transaction\n * committed, even if its delivery has completed since. An existing event that a purge removed\n * meanwhile is inserted again (with the sequence reserved for it) instead of being skipped; its id is\n * added to `insertedEventIds`. Returns how many deliveries were inserted.\n */\n async #appendToExistingEvents(\n transaction: TTransaction,\n input: AppendToExistingEventsInput,\n ): Promise<number> {\n const { plan, fresh, deliveries, handlersByEvent, insertedEventIds, createdAt, wakeAt } = input;\n const sequences = new Map(\n fresh.map((row) => [row['id'] as string, row['sequence'] as string | null]),\n );\n const reinserted: string[] = [];\n let existing = plan.events\n .filter((event) => !insertedEventIds.has(event.id))\n .map((event) =>\n toEventRow(event, {\n sequence: sequences.get(event.id)!,\n handlers: handlersByEvent.get(event.id) ?? [],\n }),\n );\n while (existing.length > 0) {\n const locked = await this.#lockExistingEvents(transaction, existing);\n const gone = existing.filter((row) => !locked.has(row.id));\n if (gone.length > 0) {\n const inserted = await this.#state.query({\n sql: this.#state.statements.append.insertEvents,\n parameters: [JSON.stringify(gone), createdAt],\n transaction,\n });\n for (const row of inserted) {\n insertedEventIds.add(row['id'] as string);\n reinserted.push(row['id'] as string);\n }\n }\n existing = gone.filter((row) => !insertedEventIds.has(row.id));\n }\n const inserted = await this.#state.query({\n sql: this.#state.statements.append.insertDeliveries,\n parameters: [JSON.stringify(deliveries), createdAt, JSON.stringify(reinserted), wakeAt],\n transaction,\n });\n return inserted.length;\n }\n}\n\ninterface AppendPlan {\n /** First occurrence of every event id in the call, in entry order. */\n readonly events: readonly EventEnvelope[];\n readonly deliveries: readonly DeliveryRow[];\n /** One per entry: its event id, and whether an earlier entry of the call carried the same id. */\n readonly outcomes: ReadonlyArray<{ readonly eventId: string; readonly repeated: boolean }>;\n}\n\nfunction planAppend(entries: readonly AppendEntry[]): AppendPlan {\n const events: EventEnvelope[] = [];\n const deliveries: DeliveryRow[] = [];\n const outcomes: Array<{ eventId: string; repeated: boolean }> = [];\n const seenEventIds = new Set<string>();\n const seenDeliveries = new Set<string>();\n for (const { event, deliveries: newDeliveries } of entries) {\n const repeated = seenEventIds.has(event.id);\n seenEventIds.add(event.id);\n outcomes.push({ eventId: event.id, repeated });\n if (!repeated) {\n events.push(event);\n }\n for (const delivery of newDeliveries) {\n const identity = CompositeKey.of(event.id, delivery.handler);\n if (!seenDeliveries.has(identity)) {\n seenDeliveries.add(identity);\n deliveries.push({\n id: delivery.id,\n event_id: event.id,\n handler: delivery.handler,\n available_at: delivery.availableAt.toISOString(),\n });\n }\n }\n }\n return { events, deliveries, outcomes };\n}\n\nfunction toEventRow(\n event: EventEnvelope,\n {\n sequence,\n handlers,\n }: { readonly sequence: string | null; readonly handlers: readonly string[] },\n): EventRow {\n return {\n id: event.id,\n type: event.type,\n source: event.source,\n key: event.key,\n sequence,\n payload: event.payload,\n headers: event.headers,\n correlation_id: event.correlationId,\n causation_id: event.causationId,\n occurred_at: event.occurredAt.toISOString(),\n handlers,\n };\n}\n\n/** The handlers each event gets a delivery for, in delivery order. */\nfunction handlersByEventOf(deliveries: readonly DeliveryRow[]): Map<string, string[]> {\n const handlersByEvent = new Map<string, string[]>();\n for (const delivery of deliveries) {\n handlersByEvent.set(delivery.event_id, [\n ...(handlersByEvent.get(delivery.event_id) ?? []),\n delivery.handler,\n ]);\n }\n return handlersByEvent;\n}\n\n/** How many of the events carry each key: the sequences each key reserves. */\nfunction keyCountsOf(events: AppendPlan['events']): Map<string, number> {\n const keyCounts = new Map<string, number>();\n for (const event of events) {\n if (event.key !== null) {\n keyCounts.set(event.key, (keyCounts.get(event.key) ?? 0) + 1);\n }\n }\n return keyCounts;\n}\n\n/** Each entry's event id as appended (new and inserted by this call) or duplicate, in entry order. */\nfunction splitOutcomes(\n plan: AppendPlan,\n insertedEventIds: ReadonlySet<string>,\n): { appendedEventIds: string[]; duplicateEventIds: string[] } {\n const appendedEventIds: string[] = [];\n const duplicateEventIds: string[] = [];\n for (const { eventId, repeated } of plan.outcomes) {\n (!repeated && insertedEventIds.has(eventId) ? appendedEventIds : duplicateEventIds).push(\n eventId,\n );\n }\n return { appendedEventIds, duplicateEventIds };\n}\n","import { RelayBusError } from '@relaybus/core';\n\n/**\n * A claim was refused because giving back the deliveries of an earlier, failed\n * claim still fails. Claiming before that would take the owner's live lanes for\n * foreign ones; the next claim tries the reconciliation again.\n */\nexport class ReconcileFailedError extends RelayBusError {\n override name = 'ReconcileFailedError';\n override readonly code: string = 'RELAYBUS_POSTGRES_RECONCILE_FAILED';\n}\n","import { CompositeKey } from '@relaybus/core/internal';\nimport type { PostgresRow } from './executor.js';\n\n// Reading the rows of the claim statements: what they left behind, and their order.\n\n/** Whether the claim statement saw work it could not take: a takeover in progress, unexamined free lanes, or a stale snapshot. */\nexport function leftWorkBehind(row: PostgresRow): boolean {\n return (\n row['takeover_waiting'] === true ||\n row['unexamined_free_lanes'] === true ||\n row['stale'] === true\n );\n}\n\n/**\n * The first `limit` picks in due order, keeping only the lowest sequence of each (handler, key):\n * two statements that read at different moments may each have picked a head of the same key.\n */\nexport function keepKeyHeads(picked: readonly PostgresRow[], limit: number): PostgresRow[] {\n const seenKeys = new Set<string>();\n const kept = [...picked]\n .sort((left, right) => compareSequence(left, right))\n .filter((row) => {\n if (row['delivery_key'] === null) {\n return true;\n }\n const group = CompositeKey.of(row['handler'] as string, row['delivery_key'] as string);\n return !seenKeys.has(group) && Boolean(seenKeys.add(group));\n });\n kept.sort(compareDue);\n return kept.slice(0, limit);\n}\n\nfunction compareSequence(left: PostgresRow, right: PostgresRow): number {\n const first = sequenceOf(left);\n const second = sequenceOf(right);\n return Number(first > second) - Number(first < second);\n}\n\n/** The key sequence of a picked row; 0 for an unkeyed delivery, which has none. */\nfunction sequenceOf(row: PostgresRow): bigint {\n return BigInt((row['sequence'] as string | null) ?? 0);\n}\n\nexport function compareDue(left: PostgresRow, right: PostgresRow): number {\n return (\n compareText(left['due_at'] as string, right['due_at'] as string) ||\n compareText(left['delivery_id'] as string, right['delivery_id'] as string)\n );\n}\n\nfunction compareText(left: string, right: string): number {\n return Number(left > right) - Number(left < right);\n}\n","import { type ClaimRequest, type ClaimedDelivery } from '@relaybus/core';\nimport { OwnerSerializedClaims } from '@relaybus/core/internal';\nimport { ReconcileFailedError } from './errors.js';\nimport type { PostgresParameter, PostgresRow } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { compareDue, keepKeyHeads, leftWorkBehind } from './claim-rows.js';\nimport { mapClaimedDelivery, parseLeaseToken, readCount } from './row-mapping.js';\n\n/** Lanes a claim takes in its first round; every further round takes twice as many. */\nconst INITIAL_LANES_PER_ROUND = 4;\n\n/** Attempts of the held-lane claim before a stale statement is given up for this call (a later claim finds the work). */\nconst MAXIMUM_STALE_CLAIM_ATTEMPTS = 3;\n\n/**\n * Claims for {@link PostgresEventStore.claim}, one claim per owner at a time: held lanes first\n * when the owner is draining a backlog there, then free lanes round by round. A claim that fails\n * after the database may have recorded it reconciles the owner's lanes.\n */\nexport class PostgresClaims<TTransaction> extends OwnerSerializedClaims {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n super();\n this.#state = state;\n }\n\n protected async claimInTurn(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n await this.#assertReconciled(request.leaseOwner);\n // An owner whose last claim was filled from the lanes it held is draining a backlog there: those\n // lanes are asked first.\n const heldFirst = this.#state.drainingOwners.has(request.leaseOwner);\n let rows = await this.#claimFirst(request, heldFirst);\n const heldLanes = new Set(JSON.parse(rows[0]!['examined_lanes'] as string) as number[]);\n const claimed = this.#takeClaimed(rows, request.leaseOwner);\n if (heldFirst && claimed.length < request.limit && rows[0]!['stale'] !== true) {\n const freeRows = await this.#claimFreeLanesAfterHeld(request, claimed);\n if (freeRows === undefined) {\n return this.#handOutInDueOrder(claimed, { request, heldLanes });\n }\n rows = freeRows;\n }\n if (claimed.length < request.limit && leftWorkBehind(rows[0]!)) {\n await this.#claimMoreLanes(request, claimed);\n }\n return this.#handOutInDueOrder(claimed, { request, heldLanes });\n }\n\n /** Reconciles first when an earlier reconciliation of `owner` failed; refuses to claim while it still fails. */\n async #assertReconciled(owner: string): Promise<void> {\n if (this.#state.unreconciled.has(owner) && !(await this.#reconcile(owner))) {\n // The generation moved on and the lanes were not told: claiming now would take the owner's live lanes for foreign ones.\n throw new ReconcileFailedError(\n `[PostgresEventStore](claim) Giving back unreturned deliveries still fails, so no claim is made | owner=${owner}`,\n );\n }\n }\n\n /** The first claim statement: from the held lanes only when `heldFirst`, else from held and free lanes. */\n async #claimFirst(request: ClaimRequest, heldFirst: boolean): Promise<readonly PostgresRow[]> {\n try {\n return await this.#claimInOneStatement(\n request,\n heldFirst\n ? this.#state.statements.lanes.claimHeldLanes\n : this.#state.statements.lanes.claimLanes,\n );\n } catch (error) {\n await this.#reconcile(request.leaseOwner);\n throw error;\n }\n }\n\n /**\n * After a held-lanes claim came up short: claims the rest from held and free lanes and adds it to\n * `claimed`. Returns the statement's rows, or undefined when it failed after something was claimed\n * already, which is then handed out as it is.\n */\n async #claimFreeLanesAfterHeld(\n request: ClaimRequest,\n claimed: PostgresRow[],\n ): Promise<readonly PostgresRow[] | undefined> {\n let rows: readonly PostgresRow[];\n try {\n rows = await this.#claimInOneStatement(\n { ...request, limit: request.limit - claimed.length },\n this.#state.statements.lanes.claimLanes,\n );\n } catch (error) {\n await this.#reconcile(request.leaseOwner);\n if (claimed.length === 0) {\n this.#state.drainingOwners.delete(request.leaseOwner);\n throw error;\n }\n this.#state.logger.error(\n `[PostgresClaims](claimFreeLanesAfterHeld) Claiming from free lanes failed, returning the deliveries already claimed | claimed=${claimed.length} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n return undefined;\n }\n claimed.push(...this.#takeClaimed(rows, request.leaseOwner));\n return rows;\n }\n\n /** Takes more lanes round by round and adds what they give to `claimed`; keeps what was claimed when that fails. */\n async #claimMoreLanes(request: ClaimRequest, claimed: PostgresRow[]): Promise<void> {\n try {\n const more = await this.#claimMore(request, claimed.length);\n this.#handOut(more, request.leaseOwner);\n claimed.push(...more);\n } catch (error) {\n await this.#reconcile(request.leaseOwner);\n if (claimed.length === 0) {\n throw error;\n }\n this.#state.logger.error(\n `[PostgresClaims](claimMoreLanes) Taking more lanes failed, returning the deliveries already claimed | claimed=${claimed.length} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /** The deliveries a claim statement picked, registered as handed out to `leaseOwner`. */\n #takeClaimed(rows: readonly PostgresRow[], leaseOwner: string): PostgresRow[] {\n const claimed = rows.filter((row) => row['delivery_id'] !== null);\n this.#forgetFinished(rows[0]!, { leaseOwner, claimed });\n this.#handOut(claimed, leaseOwner);\n return claimed;\n }\n\n #handOutInDueOrder(\n claimed: PostgresRow[],\n {\n request,\n heldLanes,\n }: { readonly request: ClaimRequest; readonly heldLanes: ReadonlySet<number> },\n ): ClaimedDelivery[] {\n if (\n claimed.length >= request.limit &&\n claimed.every((row) => heldLanes.has(readCount(row, 'lane')))\n ) {\n this.#state.drainingOwners.add(request.leaseOwner);\n } else {\n this.#state.drainingOwners.delete(request.leaseOwner);\n }\n // The steps pick from different lanes; hand the batch out in due order, like a single query would.\n claimed.sort(compareDue);\n return claimed.map((row) => mapClaimedDelivery(row, request.leaseExpiresAt));\n }\n\n /**\n * Runs `statement` (`LaneStatements.claimLanes` or its held-lane form), again when it reports that it waited for a lane lock and\n * read deliveries with an older snapshot than the lane it got. A held lane is only locked by an\n * operation of its own owner (another claim, a reschedule), so a few attempts are enough.\n */\n async #claimInOneStatement(\n request: ClaimRequest,\n statement: string,\n ): Promise<readonly PostgresRow[]> {\n const parameters = [\n request.now.toISOString(),\n JSON.stringify(request.handlers),\n request.limit,\n request.leaseOwner,\n request.leaseExpiresAt.toISOString(),\n this.#generation(request.leaseOwner).toString(),\n ];\n let rows = await this.#state.query({ sql: statement, parameters });\n for (\n let attempt = 1;\n attempt < MAXIMUM_STALE_CLAIM_ATTEMPTS && rows[0]!['stale'] === true;\n attempt += 1\n ) {\n rows = await this.#state.query({ sql: statement, parameters });\n }\n return rows;\n }\n\n /**\n * Second step of {@link PostgresEventStore.claim}, in one transaction: takes free lanes a few at a\n * time, lanes to take over included (their lost attempts are charged first), and records the batch.\n * `alreadyClaimed` deliveries of the first step are in flight, so they are not picked again.\n */\n async #claimMore(request: ClaimRequest, alreadyClaimed: number): Promise<PostgresRow[]> {\n const now = request.now.toISOString();\n const leaseExpiresAt = request.leaseExpiresAt.toISOString();\n const handlers = JSON.stringify(request.handlers);\n // Taken before the transaction starts: a transaction that reaches the server late keeps its generation.\n const generation = this.#generation(request.leaseOwner).toString();\n return this.#state.executor.transaction(async (transaction) => {\n const claimed: PostgresRow[] = [];\n const remaining = (): number => request.limit - alreadyClaimed - claimed.length;\n const takenLanes = new Set<number>();\n for (let laneCount = INITIAL_LANES_PER_ROUND; remaining() > 0;) {\n const taken = await this.#state.query({\n sql: this.#state.statements.lanes.takeFreeLanes,\n parameters: [now, handlers, laneCount, request.leaseOwner, leaseExpiresAt, generation],\n transaction,\n });\n if (taken.length === 0) {\n break;\n }\n const lanes = taken.map((row) => readCount(row, 'lane'));\n for (const lane of lanes) {\n takenLanes.add(lane);\n }\n claimed.push(\n ...(await this.#pickDeliveries(\n [now, handlers, remaining(), JSON.stringify(lanes)],\n transaction,\n )),\n );\n laneCount *= 2;\n }\n await this.#recordClaim(claimed, { lanes: takenLanes, request, transaction });\n return claimed;\n });\n }\n\n /**\n * The generation of the owner's claim statements. It only grows, also across restarts (it starts at the\n * clock), and a reconciliation moves it up, which fences off every earlier statement still in flight.\n */\n #generation(owner: string, advance = false): bigint {\n const current = this.#state.generations.get(owner) ?? BigInt(Date.now());\n const next = advance\n ? current + GENERATION_STEP > BigInt(Date.now())\n ? current + GENERATION_STEP\n : BigInt(Date.now())\n : current;\n this.#state.generations.set(owner, next);\n return next;\n }\n\n /** Remembers the claims handed to the caller of `claim` until they are settled. */\n #handOut(rows: readonly PostgresRow[], leaseOwner: string): void {\n for (const row of rows) {\n const claim = mapClaimedDelivery(row, new Date(0));\n this.#state.handedOut.register(claim, {\n owner: leaseOwner,\n deliveryId: claim.deliveryId,\n ...parseLeaseToken(claim.leaseToken)!,\n });\n }\n }\n\n /**\n * Drops the registrations of the owner's held lanes whose delivery no longer runs there\n * (completed inside the caller's transaction, deleted, or listed no more). Registrations of\n * lanes this claim did not see stay: their tokens may still be valid.\n */\n #forgetFinished(\n row: PostgresRow,\n {\n leaseOwner,\n claimed,\n }: { readonly leaseOwner: string; readonly claimed: readonly PostgresRow[] },\n ): void {\n // Lanes the statement freed are examined too: nothing runs there any more.\n const heldLanes = new Set(JSON.parse(row['examined_lanes'] as string) as number[]);\n const running = new Set([\n ...(JSON.parse(row['running_ids'] as string) as string[]),\n ...claimed.map((picked) => picked['delivery_id'] as string),\n ]);\n this.#state.handedOut.forgetWhere(\n (entry) =>\n entry.owner === leaseOwner && heldLanes.has(entry.lane) && !running.has(entry.deliveryId),\n );\n }\n\n /**\n * After a claim failed, possibly after the database recorded its batch: gives back the recorded\n * deliveries that were never handed out, keeping exactly the claims handed out and not settled.\n * A failure is remembered and retried before the owner's next claim: other deliveries keep\n * renewing the lane, so an unreturned one would otherwise never be recovered.\n */\n async #reconcile(leaseOwner: string): Promise<boolean> {\n // Claim statements of the generation before are fenced off by the new one.\n const generation = this.#generation(leaseOwner, true);\n const handedOut = this.#state.handedOut\n .entriesOf(leaseOwner)\n .map(({ deliveryId, lane, epoch, claims }) => ({ id: deliveryId, lane, epoch, claims }));\n try {\n await this.#state.query({\n sql: this.#state.statements.claim.reconcileClaims,\n parameters: [leaseOwner, JSON.stringify(handedOut), generation.toString()],\n });\n this.#state.unreconciled.delete(leaseOwner);\n return true;\n } catch (error) {\n this.#state.unreconciled.add(leaseOwner);\n this.#state.logger.error(\n `[PostgresClaims](reconcile) Giving back unreturned deliveries failed, it is retried before the next claim | owner=${leaseOwner} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n return false;\n }\n }\n\n /** Fast claim, then the slow one when the fast window was full of blocked followers. */\n async #pickDeliveries(\n parameters: readonly PostgresParameter[],\n transaction: TTransaction,\n ): Promise<PostgresRow[]> {\n const limit = parameters[2] as number;\n const fastRows = await this.#state.query({\n sql: this.#state.statements.claim.claim,\n parameters,\n transaction,\n });\n const picked = fastRows.filter((row) => row['delivery_id'] !== null);\n if (picked.length < limit && fastRows[0]!['window_saturated'] === true) {\n const slowRows = await this.#state.query({\n sql: this.#state.statements.claim.claimBehindBlockedKeys,\n parameters,\n transaction,\n });\n // Nothing was written, so the slow statement sees the fast statement's picks again.\n // Both pick at most the head of a key, so the union is still one delivery per key.\n const pickedIds = new Set(picked.map((row) => row['delivery_id']));\n picked.push(\n ...slowRows.filter(\n (row) => row['delivery_id'] !== null && !pickedIds.has(row['delivery_id']),\n ),\n );\n // The two statements read at different moments: a dead letter requeued in between can put a key's\n // predecessor in one result and its successor in the other. Only the lowest of a key may run.\n return keepKeyHeads(picked, limit);\n }\n return picked;\n }\n\n /** Writes the picked ids into their lane rows and frees the lanes that picked nothing. */\n async #recordClaim(\n claimed: readonly PostgresRow[],\n {\n lanes,\n request,\n transaction,\n }: {\n readonly lanes: ReadonlySet<number>;\n readonly request: ClaimRequest;\n readonly transaction: TTransaction;\n },\n ): Promise<void> {\n const idsByLane = new Map<number, string[]>();\n for (const row of claimed) {\n const lane = readCount(row, 'lane');\n idsByLane.set(lane, [...(idsByLane.get(lane) ?? []), row['delivery_id'] as string]);\n }\n const idleLanes = [...lanes].filter((lane) => !idsByLane.has(lane));\n if (idsByLane.size === 0 && idleLanes.length === 0) {\n return;\n }\n await this.#state.query({\n sql: this.#state.statements.claim.recordClaim,\n parameters: [\n JSON.stringify([...idsByLane].map(([lane, ids]) => ({ lane, ids }))),\n JSON.stringify(idleLanes),\n request.leaseOwner,\n request.leaseExpiresAt.toISOString(),\n ],\n transaction,\n });\n }\n}\n\n/** How far a reconciliation moves the generation at least. */\nconst GENERATION_STEP = 1n;\n","import { type LeaseReference } from '@relaybus/core';\nimport {\n DeliveryLeaseIdentity,\n LeaseSettlement,\n type LeaseChange,\n type LeaseExtension,\n} from '@relaybus/core/internal';\nimport type { PostgresParameter } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { parseLeaseToken, readCount, type LaneLease } from './row-mapping.js';\n\n/**\n * Ends and renews claims for {@link PostgresEventStore}: every statement is fenced by the lane\n * lease the token names (lane, epoch and claim generation).\n */\nexport class PostgresCompletion<TTransaction> extends LeaseSettlement<LaneLease> {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n super();\n this.#state = state;\n }\n\n /** Implements {@link PostgresEventStore.complete}. */\n async complete(\n lease: LeaseReference,\n { now, transaction }: { readonly now: Date; readonly transaction?: TTransaction | undefined },\n ): Promise<boolean> {\n return (await this.#completeLeases([lease], { now, transaction }))[0]!;\n }\n\n /** Implements {@link PostgresEventStore.completeMany}. */\n completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]> {\n return this.#completeLeases(leases, { now, transaction: undefined });\n }\n\n /** A lease this store issued; any other token cannot be held. */\n protected findHeld(lease: LeaseReference): LaneLease | undefined {\n return parseLeaseToken(lease.leaseToken);\n }\n\n protected writeExtension(\n held: LaneLease,\n { lease, leaseExpiresAt }: LeaseExtension,\n ): Promise<boolean> {\n return this.#changed(this.#state.statements.completion.extendLease, [\n ...fenceOf(lease, held),\n leaseExpiresAt.toISOString(),\n ]);\n }\n\n protected writeChange(held: LaneLease, { lease, change }: LeaseChange): Promise<boolean> {\n const { completion } = this.#state.statements;\n const fence = fenceOf(lease, held);\n if (change.kind === 'reschedule') {\n return this.#changed(completion.reschedule, [\n ...fence,\n change.availableAt.toISOString(),\n JSON.stringify(change.error),\n change.now.toISOString(),\n ]);\n }\n if (change.kind === 'bury') {\n return this.#changed(completion.bury, [\n ...fence,\n JSON.stringify(change.error),\n change.now.toISOString(),\n ]);\n }\n return this.#changed(completion.release, [...fence, change.now.toISOString()]);\n }\n\n /** Forgets a handed-out lease once the store answered about it (any answer: the claim is over or fenced out). */\n protected forgetHandedOut(lease: LeaseReference): void {\n this.#state.handedOut.forget(lease);\n }\n\n async #changed(sql: string, parameters: readonly PostgresParameter[]): Promise<boolean> {\n const rows = await this.#state.query({ sql, parameters });\n return readCount(rows[0]!, 'count') > 0;\n }\n\n /**\n * Deletes the delivery of every lease that is still the current claim of its\n * delivery. Returns one flag per lease, in order. Results are matched to leases\n * by position, so two leases of one delivery (a stale and a current one) get\n * their own answers; a lease listed twice completes once, at its first position.\n */\n async #completeLeases(\n leases: readonly LeaseReference[],\n { now, transaction }: { readonly now: Date; readonly transaction: TTransaction | undefined },\n ): Promise<boolean[]> {\n const issued = issuedLeases(leases);\n const completed = new Set<number>();\n if (issued.length > 0) {\n const rows = await this.#state.query({\n sql: this.#state.statements.completion.complete,\n parameters: [JSON.stringify(issued), now.toISOString()],\n transaction,\n });\n for (const row of rows) {\n completed.add(readCount(row, 'ord'));\n }\n }\n if (transaction === undefined) {\n // Inside the caller's transaction the completion is only provisional: it may roll back and retry.\n for (const lease of leases) {\n this.#state.handedOut.forget(lease);\n }\n }\n return leases.map((_, ord) => completed.has(ord));\n }\n}\n\n/** The first parameters of every fenced statement: the delivery and the lane lease of its claim. */\nfunction fenceOf(lease: LeaseReference, held: LaneLease): PostgresParameter[] {\n return [lease.deliveryId, held.lane, held.epoch, held.claims];\n}\n\n/** The leases this store can have issued, each once, with their position in `leases`. */\nfunction issuedLeases(\n leases: readonly LeaseReference[],\n): Array<{ ord: number; id: string } & LaneLease> {\n const issued: Array<{ ord: number; id: string } & LaneLease> = [];\n const seen = new Set<string>();\n leases.forEach((lease, ord) => {\n const held = parseLeaseToken(lease.leaseToken);\n const identity = DeliveryLeaseIdentity.of(lease.deliveryId, lease.leaseToken);\n if (held !== undefined && !seen.has(identity)) {\n seen.add(identity);\n issued.push({ ord, id: lease.deliveryId, ...held });\n }\n });\n return issued;\n}\n","import { Client, type ClientConfig } from 'pg';\n\n/**\n * The connections the store opened itself: every connection of the pool it created from\n * `connectionString`, and the connections it listens for notifications on. A shutdown that runs past\n * its deadline destroys them, so a query that hangs (a lock wait, an unreachable server) fails at\n * once instead of holding `stop` and the process. Pools the application passed in are never tracked.\n */\nexport class OwnedConnections {\n readonly #clients = new Set<Client>();\n\n /**\n * The `Client` class for a pool the store creates: every connection is tracked from the moment it\n * is created, so one still connecting or authenticating is destroyed too.\n */\n clientClass(): typeof Client {\n // eslint-disable-next-line @typescript-eslint/no-this-alias -- the class below needs the tracker\n const owned = this;\n return class OwnedClient extends Client {\n constructor(config?: string | ClientConfig) {\n super(config);\n owned.track(this);\n }\n };\n }\n\n /** Tracks one connection until it ends. */\n track(client: Client): void {\n this.#clients.add(client);\n client.once('end', () => this.#clients.delete(client));\n }\n\n /**\n * Destroys the socket of every tracked connection. Its queries fail with \"Connection terminated\"\n * and the pool drops it. The server ends the session when it next talks to the client.\n */\n destroyAll(): void {\n for (const client of this.#clients) {\n // A destroyed connection reports an error; nobody may be listening on a checked-out one.\n client.on('error', () => undefined);\n client.connection.stream.destroy();\n }\n this.#clients.clear();\n }\n}\n","import {\n type DeliveryQuery,\n type DeliveryRecord,\n type EventStoreStatistics,\n type PurgeRequest,\n type PurgeResult,\n} from '@relaybus/core';\nimport type { PostgresRow } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { mapDeliveryRecord, mapOldestDueAt, readCount } from './row-mapping.js';\n\n/** maintenance */\nexport class PostgresMaintenance<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n this.#state = state;\n }\n\n /** Implements {@link PostgresEventStore.relinquish}. */\n async relinquish(leaseOwner: string): Promise<void> {\n await this.#state.query({\n sql: this.#state.statements.claim.relinquish,\n parameters: [leaseOwner],\n });\n }\n\n /** Implements {@link PostgresEventStore.listDeliveries}. */\n async listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n const statement = this.#state.statements.queries.listDeliveries(query);\n const rows = await this.#state.executor.query(statement.sql, statement.parameters);\n return rows.map(mapDeliveryRecord);\n }\n\n /** Implements {@link PostgresEventStore.requeue}. */\n async requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n const rows = await this.#state.query({\n sql: this.#state.statements.queries.requeue,\n parameters: [JSON.stringify(deliveryIds), now.toISOString()],\n });\n return readCount(rows[0]!, 'count');\n }\n\n /** Implements {@link PostgresEventStore.statistics}. */\n async statistics(now: Date): Promise<EventStoreStatistics> {\n const stored: Record<string, number> = { pending: 0, dead: 0, completed: 0 };\n for (const row of await this.#state.query({\n sql: this.#state.statements.queries.countByStatus,\n parameters: [],\n })) {\n stored[row['status'] as string] = readCount(row, 'count');\n }\n const [running] = await this.#state.query({\n sql: this.#state.statements.queries.countRunning,\n parameters: [],\n });\n const processing = readCount(running!, 'count');\n let completed = stored['completed']!;\n if (this.#state.completionHistory) {\n const [history] = await this.#state.query({\n sql: this.#state.statements.queries.countCompletionHistory,\n parameters: [],\n });\n completed += readCount(history!, 'count');\n }\n const oldestDue = await this.#state.query({\n sql: this.#state.statements.queries.oldestDue,\n parameters: [now.toISOString()],\n });\n return {\n // The counts come from separate statements; a delivery that finishes in between must not make this negative.\n pending: Math.max(0, stored['pending']! - processing),\n processing,\n completed,\n dead: stored['dead']!,\n oldestDueAt: mapOldestDueAt(oldestDue),\n };\n }\n\n /** Implements {@link PostgresEventStore.purge}. */\n async purge(request: PurgeRequest): Promise<PurgeResult> {\n const total = { deletedDeliveries: 0, deletedEvents: 0 };\n const batches = this.#purgeBatchPlan(request);\n for (const [sql, cutoff, deleteOrphans] of batches) {\n if (cutoff === undefined) {\n continue;\n }\n let deletedInBatch = this.#state.purgeBatchSize;\n while (deletedInBatch === this.#state.purgeBatchSize) {\n const batch = await this.#purgeBatch(sql, { cutoff, deleteOrphans });\n deletedInBatch = batch.deletedDeliveries;\n total.deletedDeliveries += batch.deletedDeliveries;\n total.deletedEvents += batch.deletedEvents;\n }\n }\n total.deletedEvents += await this.#purgeAllOrphanEvents(request);\n return total;\n }\n\n /** The purge statements to run in order: SQL, cutoff (undefined skips it) and the orphan-event delete. */\n #purgeBatchPlan(request: PurgeRequest): Array<[string, Date | undefined, string]> {\n const batches: Array<[string, Date | undefined, string]> = [\n [\n this.#state.statements.purge.purgeCompletedBatch(),\n request.completedBefore,\n this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n ],\n [\n this.#state.statements.purge.purgeDeadBatch(),\n request.deadBefore,\n this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n ],\n ];\n if (this.#state.completionHistory) {\n batches.push([\n this.#state.statements.purge.purgeCompletionHistoryBatch(),\n request.completedBefore,\n this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n ]);\n }\n return batches;\n }\n\n /** Removes the events left without deliveries, in two passes; returns how many events were deleted. */\n async #purgeAllOrphanEvents(request: PurgeRequest): Promise<number> {\n let deletedEvents = 0;\n const orphanCutoff = [request.completedBefore, request.deadBefore]\n .filter((cutoff) => cutoff !== undefined)\n .sort((first, second) => first.getTime() - second.getTime())[0];\n if (orphanCutoff !== undefined) {\n deletedEvents += await this.#purgeOrphanEvents(\n this.#state.statements.purge.lockOrphanEventsBatch,\n {\n deleteStatement: this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n cutoff: orphanCutoff,\n recheckCutoff: false,\n },\n );\n }\n if (request.completedBefore !== undefined) {\n deletedEvents += await this.#purgeOrphanEvents(\n this.#state.statements.purge.lockCompletedOrphanEventsBatch,\n {\n deleteStatement: this.#state.statements.purge.deleteExpiredCompletedOrphanEvents,\n cutoff: request.completedBefore,\n recheckCutoff: true,\n },\n );\n }\n return deletedEvents;\n }\n\n async #purgeOrphanEvents(\n lockStatement: string,\n {\n deleteStatement,\n cutoff,\n recheckCutoff,\n }: { readonly deleteStatement: string; readonly cutoff: Date; readonly recheckCutoff: boolean },\n ): Promise<number> {\n let deletedEvents = 0;\n let removedInBatch = this.#state.purgeBatchSize;\n while (removedInBatch === this.#state.purgeBatchSize) {\n removedInBatch = await this.#state.executor.transaction(async (transaction) => {\n const locked = await this.#state.query({\n sql: lockStatement,\n parameters: [cutoff.toISOString(), this.#state.purgeBatchSize],\n transaction,\n });\n const ids = JSON.stringify(locked.map((row: PostgresRow) => row['id'] as string));\n const removed = await this.#state.query({\n sql: deleteStatement,\n parameters: recheckCutoff ? [ids, cutoff.toISOString()] : [ids],\n transaction,\n });\n return readCount(removed[0]!, 'count');\n });\n deletedEvents += removedInBatch;\n }\n return deletedEvents;\n }\n\n async #purgeBatch(\n sql: string,\n { cutoff, deleteOrphans }: { readonly cutoff: Date; readonly deleteOrphans: string },\n ): Promise<{ deletedDeliveries: number; deletedEvents: number }> {\n return this.#state.executor.transaction(async (transaction) => {\n const deleted = await this.#state.query({\n sql,\n parameters: [cutoff.toISOString(), this.#state.purgeBatchSize],\n transaction,\n });\n if (deleted.length === 0) {\n return { deletedDeliveries: 0, deletedEvents: 0 };\n }\n const eventIds = JSON.stringify([\n ...new Set(deleted.map((row) => row['event_id'] as string)),\n ]);\n const locked = await this.#state.query({\n sql: this.#state.statements.purge.lockEvents,\n parameters: [eventIds],\n transaction,\n });\n const removed = await this.#state.query({\n sql: deleteOrphans,\n parameters: [JSON.stringify(locked.map((row: PostgresRow) => row['id'] as string))],\n transaction,\n });\n return { deletedDeliveries: deleted.length, deletedEvents: readCount(removed[0]!, 'count') };\n });\n }\n}\n","import { resolvePostgresNames, type PostgresSchemaOptions } from './names.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { upgradePayloadToJson } from './schema.js';\n\n/** What the catalog says about the schema (see {@link SetupStatements.schemaCurrent}). */\ntype SchemaState = {\n /** The lane table carries the schema marker, which 0.4.0 writes too. */\n readonly marked: boolean;\n /** The payload and headers columns are `json`. */\n readonly payloadJson: boolean;\n};\n\n/**\n * Brings the schema to the current statements under the setup lock (see\n * {@link PostgresEventStore.setup}): first the payload conversion in a transaction of its own, then\n * the other statements, unless the schema carries the marker, which 0.4.0 writes too and which then\n * needs only the conversion.\n */\nexport class PostgresSetup<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n /** The conversion of `jsonb` payload columns. */\n readonly #payloadUpgrade: string;\n\n constructor(state: PostgresStoreState<TTransaction>, options: PostgresSchemaOptions) {\n this.#state = state;\n this.#payloadUpgrade = upgradePayloadToJson(resolvePostgresNames(options));\n }\n\n /** Implements {@link PostgresEventStore.setup}. */\n async run(): Promise<void> {\n // DDL on a current schema would still lock the tables, and those locks deadlock with running claims.\n if (isCurrent(await this.#schemaState())) {\n return;\n }\n await this.#underSetupLock(async (transaction) => {\n await this.#run(this.#payloadUpgrade, transaction);\n });\n await this.#underSetupLock(async (transaction, schema) => {\n // A 0.4.0 setup may have created the schema since the first step released the lock.\n if (schema.marked) {\n await this.#run(this.#payloadUpgrade, transaction);\n return;\n }\n for (const statement of this.#state.schemaStatements) {\n await this.#run(statement, transaction);\n }\n });\n }\n\n /**\n * Runs `work` in a transaction under the setup lock, unless the schema became current. The\n * payload conversion goes first in a transaction of its own, so it holds no other table lock\n * while it waits for the event table (a completion locks deliveries before the event rows).\n */\n async #underSetupLock(\n work: (transaction: TTransaction, schema: SchemaState) => Promise<void>,\n ): Promise<void> {\n await this.#state.executor.transaction(async (transaction) => {\n await this.#state.executor.query(\n this.#state.statements.setup.setupLock,\n [this.#state.setupLockKey],\n transaction,\n );\n const schema = await this.#schemaState(transaction);\n if (!isCurrent(schema)) {\n await work(transaction, schema);\n }\n });\n }\n\n async #run(statement: string, transaction: TTransaction): Promise<void> {\n await this.#state.executor.query(statement, [], transaction);\n }\n\n async #schemaState(transaction?: TTransaction): Promise<SchemaState> {\n const rows = await this.#state.executor.query(\n this.#state.statements.setup.schemaCurrent,\n [this.#state.schemaMarker],\n transaction,\n );\n return { marked: rows[0]!['marked'] === true, payloadJson: rows[0]!['payload_json'] === true };\n }\n}\n\n/** Current: the marker is there and the payload columns are converted. */\nfunction isCurrent(schema: SchemaState): boolean {\n return schema.marked && schema.payloadJson;\n}\n","import { ConfigurationError, type RelayBusLogger } from '@relaybus/core';\nimport { PositiveInteger } from '@relaybus/core/internal';\nimport type { Pool, PoolClient, PoolConfig } from 'pg';\nimport type { PostgresExecutor, PostgresQueryOptions } from './executor.js';\nimport type { PostgresSchemaOptions } from './names.js';\n\n/** Options shared by every way of connecting. */\nexport interface PostgresEventStoreSettings extends PostgresSchemaOptions {\n /**\n * Maximum deliveries deleted per transaction by `purge`. Smaller batches\n * hold row locks for less time; `purge` keeps going until nothing is left.\n * Default 1000.\n */\n readonly purgeBatchSize?: number;\n /**\n * Receives errors of idle connections in a pool the store creates itself\n * (database failover, `pg_terminate_backend`, network resets). Default\n * `console`. A pool you pass in is yours: attach `pool.on('error', ...)` to\n * it, otherwise `pg` raises an unhandled `error` event and the process exits.\n */\n readonly logger?: RelayBusLogger;\n /**\n * Send the statements the store repeats (publish, claim, complete, renew) as named prepared\n * statements, so each connection parses and plans their text once instead of on every call. Default\n * `true`. Set `false` behind a pooler in transaction mode that does not keep prepared statements per\n * client (PgBouncer before 1.21, or 1.21+ with `max_prepared_statements = 0`). Left on there, the\n * first statement that lands on another server session fails once, then the store stops preparing\n * and logs a warning. Only executors that support it prepare (`PgExecutor`, the default); the\n * other adapters send every statement unprepared.\n */\n readonly preparedStatements?: boolean;\n /**\n * How dispatchers in other processes learn about new deliveries.\n * - `'notify'` (default): a publishing transaction sends `NOTIFY` (at most one per 10 ms per store,\n * the rest merged into one trailing notification after the commit) and each dispatcher listens\n * with `LISTEN` on a connection of its own, so a delivery is picked up within milliseconds.\n * - `'poll'`: no `NOTIFY`, no listening connection. Other processes find new deliveries when they\n * poll (`dispatcher.pollInterval`, default 1 s); a dispatcher in the publishing process is still\n * woken at once. Use it behind a pooler in transaction mode, where `LISTEN` does not work.\n */\n readonly wakeUp?: PostgresWakeUp;\n}\n\n/** See {@link PostgresEventStoreSettings.wakeUp}. */\nexport type PostgresWakeUp = 'notify' | 'poll';\n\nconst WAKE_UPS: readonly PostgresWakeUp[] = ['notify', 'poll'];\n\n/** Use an existing `pg` pool. The store never closes it. */\nexport interface PostgresPoolOptions extends PostgresEventStoreSettings {\n readonly pool: Pool;\n readonly connectionString?: never;\n readonly poolConfig?: never;\n readonly executor?: never;\n}\n\n/** Let the store create (and on `close()` end) its own `pg` pool. */\nexport interface PostgresConnectionOptions extends PostgresEventStoreSettings {\n readonly connectionString: string;\n /** Extra `pg` pool settings, for example `max`. */\n readonly poolConfig?: Omit<PoolConfig, 'connectionString'>;\n readonly pool?: never;\n readonly executor?: never;\n}\n\n/** Use another database library through an adapter. The store never closes it. */\nexport interface PostgresExecutorOptions<TTransaction> extends PostgresEventStoreSettings {\n readonly executor: PostgresExecutor<TTransaction>;\n /**\n * Optional `pg` pool on the same database, for example the one an ORM's `pg` driver adapter uses\n * (`new PrismaPg(pool)`, Kysely's `PostgresDialect`, Drizzle's `node-postgres`). The store never\n * closes it. With it:\n * - the statements the store sends outside a transaction (the dispatcher's claims, completions and\n * lease renewals, maintenance) run on it as prepared statements (`preparedStatements`), which ORM\n * raw queries cannot do; statements in a transaction still go through `executor`;\n * - with `wakeUp: 'notify'` the store listens for wake-ups with its connection settings, so a\n * delivery published in an ORM transaction is dispatched right after that transaction commits,\n * instead of after a fixed delay or the next poll.\n */\n readonly pool?: Pool;\n readonly connectionString?: never;\n readonly poolConfig?: never;\n}\n\nexport type PostgresEventStoreOptions<TTransaction = PoolClient> =\n PostgresPoolOptions | PostgresConnectionOptions | PostgresExecutorOptions<TTransaction>;\n\nconst DEFAULT_PURGE_BATCH_SIZE = 1_000;\n\n/** Validates the options that are not names, in declaration order. */\nexport function resolveStoreSettings<TTransaction>(\n options: PostgresEventStoreOptions<TTransaction>,\n): {\n purgeBatchSize: number;\n wakeUp: PostgresWakeUp;\n queryOptions: PostgresQueryOptions | undefined;\n} {\n // A pool next to an executor only serves the store's own statements (PostgresExecutorOptions.pool).\n const sources = [options.executor ?? options.pool, options.connectionString].filter(\n (source) => source !== undefined,\n );\n if (sources.length !== 1) {\n throw new ConfigurationError(\n 'PostgresEventStore needs exactly one of pool, connectionString or executor',\n );\n }\n const purgeBatchSize = PositiveInteger.of(\n options.purgeBatchSize ?? DEFAULT_PURGE_BATCH_SIZE,\n 'purgeBatchSize',\n );\n const wakeUp = options.wakeUp ?? 'notify';\n if (!WAKE_UPS.includes(wakeUp)) {\n throw new ConfigurationError(`wakeUp must be 'notify' or 'poll', received ${String(wakeUp)}`);\n }\n const preparedStatements = options.preparedStatements ?? true;\n if (typeof preparedStatements !== 'boolean') {\n throw new ConfigurationError(\n `preparedStatements must be a boolean, received ${String(preparedStatements)}`,\n );\n }\n return {\n purgeBatchSize,\n wakeUp,\n queryOptions: preparedStatements ? { prepare: true } : undefined,\n };\n}\n","import type { PostgresNames } from './names.js';\nimport { laneExpression } from './sql-fragments.js';\n\n/** Statements that publish: events, deliveries and the wake-up notification. */\nexport class AppendStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Publishes in one statement: reserves the sequences of the keys (`[{ key, count }]` in `$4`, locked in\n * key order: each row lock is held until the publishing transaction ends, which makes sequence order equal commit order for a key), numbers the keyed events in entry order (`ordinal`), inserts\n * the events of `$1` that do not exist yet and the deliveries of `$3` that belong to them, and sends one\n * wake-up notification when a delivery it inserted is due at `$5`. Parameters:\n * `[eventsJson, createdAt, deliveriesJson, keyCountsJson, now]`. Returns one row per event of `$1`: its\n * id, its sequence, whether this statement inserted it, and (on every row) how many deliveries it\n * inserted. Deliveries of events that already existed are left to {@link insertDeliveries}.\n */\n get insertFreshEvents(): string {\n return `WITH ${this.#reservedSequences()}, ${this.#incomingEvents()}, ${this.#insertedEvents()}, ${this.#insertedDeliveries()}, ${this.#wakeUp('inserted_deliveries', '$5')}\nSELECT incoming.id, incoming.sequence::text AS sequence,\n incoming.id IN (SELECT inserted_events.id FROM inserted_events) AS inserted,\n (SELECT count(*) FROM inserted_deliveries)::int AS deliveries\nFROM incoming\nWHERE (SELECT count(*) FROM woken) >= 0`;\n }\n\n /** The CTE `reserved` of {@link insertFreshEvents}: the sequences the keys of `$4` reserve. */\n #reservedSequences(): string {\n return `reserved AS (\n INSERT INTO ${this.#names.keySequences} AS reserved (key, sequence)\n SELECT requested.key, requested.count\n FROM jsonb_to_recordset($4::jsonb) AS requested (key text, count bigint)\n ORDER BY requested.key\n ON CONFLICT (key) DO UPDATE SET sequence = reserved.sequence + EXCLUDED.sequence\n RETURNING reserved.key AS key, reserved.sequence AS sequence\n)`;\n }\n\n /** The CTE `incoming` of {@link insertFreshEvents}: the events of `$1` with their key sequences. */\n #incomingEvents(): string {\n return `incoming AS (\n SELECT incoming.*,\n CASE WHEN incoming.key IS NULL THEN NULL ELSE\n reserved.sequence - count(*) OVER (PARTITION BY incoming.key)\n + row_number() OVER (PARTITION BY incoming.key ORDER BY incoming.ordinal)\n END AS sequence\n FROM json_to_recordset($1::json) AS incoming (\n ordinal int, id text, type text, source text, key text, payload json, headers json,\n correlation_id text, causation_id text, occurred_at timestamptz, handlers text[])\n LEFT JOIN reserved ON reserved.key = incoming.key\n)`;\n }\n\n /** The CTE `inserted_events` of {@link insertFreshEvents}: the events of `$1` that do not exist yet. */\n #insertedEvents(): string {\n return `inserted_events AS (\n INSERT INTO ${this.#names.events}\n (id, type, source, key, sequence, payload, headers, correlation_id, causation_id, occurred_at, created_at, handlers)\n SELECT incoming.id, incoming.type, incoming.source, incoming.key, incoming.sequence,\n COALESCE(incoming.payload, 'null'::json), COALESCE(incoming.headers, '{}'::json),\n incoming.correlation_id, incoming.causation_id, incoming.occurred_at, $2::timestamptz,\n COALESCE(incoming.handlers, '{}')\n FROM incoming\n ORDER BY incoming.id\n ON CONFLICT (id) DO NOTHING\n RETURNING id, key, sequence\n)`;\n }\n\n /** The CTE `inserted_deliveries` of {@link insertFreshEvents}: the deliveries of `$3` of the inserted events. */\n #insertedDeliveries(): string {\n return `inserted_deliveries AS (\n INSERT INTO ${this.#names.deliveries}\n (id, event_id, handler, lane, status, attempts, available_at, key, sequence, created_at, updated_at)\n SELECT delivery.id, delivery.event_id, delivery.handler, ${laneExpression('event.key', 'event.id')}, 'pending', 0,\n delivery.available_at, event.key, event.sequence, $2::timestamptz, $2::timestamptz\n FROM jsonb_to_recordset($3::jsonb) AS delivery (id text, event_id text, handler text, available_at timestamptz)\n JOIN inserted_events AS event ON event.id = delivery.event_id\n ORDER BY delivery.event_id, delivery.handler\n ON CONFLICT (event_id, handler) DO NOTHING\n RETURNING available_at\n)`;\n }\n\n /**\n * One wake-up notification on {@link PostgresNames.notificationChannel}, outside any publishing\n * transaction. Returns a boolean column rather than the `void` of `pg_notify`, which some libraries\n * cannot read (Prisma's raw queries reject a `void` column).\n */\n get notify(): string {\n return `SELECT true AS notified FROM pg_notify('${this.#names.notificationChannel}', '')`;\n }\n\n /**\n * A CTE `woken` that sends one notification on {@link PostgresNames.notificationChannel} when a row of\n * `inserted` is due at `now`. PostgreSQL delivers it when the transaction commits, merges the same\n * notification sent twice in one transaction, and drops it on rollback. The statement must reference\n * `woken` for it to run.\n */\n #wakeUp(inserted: string, now: string): string {\n return `woken AS (\n SELECT pg_notify('${this.#names.notificationChannel}', '') FROM (\n SELECT 1 FROM ${inserted} WHERE ${inserted}.available_at <= ${now}::timestamptz LIMIT 1\n ) AS due\n)`;\n }\n\n /**\n * Parameters: `[eventsJson, createdAt]`. Returns the ids that were inserted.\n * `handlers` is the list of handlers the event gets deliveries for: it\n * outlives the deliveries, which are deleted when they complete.\n */\n get insertEvents(): string {\n return `INSERT INTO ${this.#names.events}\n (id, type, source, key, sequence, payload, headers, correlation_id, causation_id, occurred_at, created_at, handlers)\nSELECT incoming.id, incoming.type, incoming.source, incoming.key, incoming.sequence,\n COALESCE(incoming.payload, 'null'::json), COALESCE(incoming.headers, '{}'::json),\n incoming.correlation_id, incoming.causation_id, incoming.occurred_at, $2::timestamptz,\n COALESCE(incoming.handlers, '{}')\nFROM json_to_recordset($1::json) AS incoming (\n id text, type text, source text, key text, sequence bigint, payload json, headers json,\n correlation_id text, causation_id text, occurred_at timestamptz, handlers text[])\nORDER BY incoming.id\nON CONFLICT (id) DO NOTHING\nRETURNING id`;\n }\n\n /**\n * Locks events that were not inserted by the current append, in id order, so\n * that appends adding handlers to the same event run one after the other.\n * Parameters: `[eventIdsJson]`. `FOR NO KEY UPDATE` conflicts with itself and\n * not with the foreign key checks of other inserts.\n */\n get lockExistingEvents(): string {\n return `SELECT id FROM ${this.#names.events}\nWHERE id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\nORDER BY id\nFOR NO KEY UPDATE`;\n }\n\n /**\n * Parameters: `[deliveriesJson, createdAt, insertedEventIdsJson, now]`. Key and\n * sequence are copied from the stored event, so a delivery added later to an\n * existing event keeps the event's position in its key and lands in the same\n * lane. Returns the ids that were inserted.\n *\n * The deliveries of events this call just inserted are all new. For an event\n * that already existed, a handler gets a delivery only if the event does not\n * list it yet: a completed delivery is deleted, but its handler stays listed,\n * so a redelivered or republished event never runs a handler twice. The\n * handlers added to an existing event are appended to its list.\n */\n get insertDeliveries(): string {\n const events = this.#names.events;\n const insertedEvents = `ARRAY(SELECT jsonb_array_elements_text($3::jsonb))`;\n return `WITH incoming AS (\n SELECT incoming.id, incoming.event_id, incoming.handler, incoming.available_at\n FROM jsonb_to_recordset($1::jsonb) AS incoming (id text, event_id text, handler text, available_at timestamptz)\n), fresh AS (\n SELECT incoming.*, event.key, event.sequence, ${laneExpression('event.key', 'event.id')} AS lane\n FROM incoming\n JOIN ${events} AS event ON event.id = incoming.event_id\n WHERE event.id = ANY (${insertedEvents}) OR NOT incoming.handler = ANY (event.handlers)\n), inserted AS (\n INSERT INTO ${this.#names.deliveries}\n (id, event_id, handler, lane, status, attempts, available_at, key, sequence, created_at, updated_at)\n SELECT fresh.id, fresh.event_id, fresh.handler, fresh.lane, 'pending', 0, fresh.available_at,\n fresh.key, fresh.sequence, $2::timestamptz, $2::timestamptz\n FROM fresh\n ORDER BY fresh.event_id, fresh.handler\n ON CONFLICT (event_id, handler) DO NOTHING\n RETURNING id, event_id, handler, available_at\n), extended AS (\n UPDATE ${events} AS event SET handlers = event.handlers || added.handlers\n FROM (\n SELECT inserted.event_id, array_agg(inserted.handler) AS handlers FROM inserted\n WHERE inserted.event_id <> ALL (${insertedEvents}) GROUP BY inserted.event_id\n ) AS added\n WHERE event.id = added.event_id\n RETURNING event.id\n), ${this.#wakeUp('inserted', '$4')}\nSELECT id FROM inserted WHERE (SELECT count(*) FROM woken) >= 0`;\n }\n}\n","import type { PostgresParameter } from './executor.js';\nimport type { PostgresNames } from './names.js';\nimport { isoText } from './sql-fragments.js';\n\nexport interface PostgresStatement {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n}\n\n/**\n * Due deliveries the fast claim examines before it gives up and lets the slow\n * claim look at the heads of all keys.\n */\nexport const CLAIM_SCAN_WINDOW = 256;\n\n/** Due deliveries the fast claim reads from one lane. A lane that fills it may hide claimable deliveries behind blocked followers. */\nexport const LANE_SCAN_WINDOW = 64;\n\n/**\n * Due deliveries of a free lane a claim looks at when it decides how many lanes to take: their unkeyed\n * deliveries and distinct keys estimate what the lane can give, so a deep backlog is taken a few lanes\n * at a time and a lane of few hot keys counts for no more than its keys.\n */\nexport const LANE_DEPTH_CAP = 16;\n\n/** Free lanes a claim that needs more takes at least (those with the oldest due deliveries), as in its first round. */\nexport const INITIAL_FREE_LANES = 4;\n\nexport const HANDLER_PREDICATE = `delivery.handler = ANY (ARRAY(SELECT jsonb_array_elements_text($2::jsonb)))`;\n\nexport function eventColumns(alias: string): string {\n return `${alias}.id AS event_id,\n ${alias}.type AS event_type,\n ${alias}.source AS event_source,\n ${alias}.key AS event_key,\n ${alias}.payload::text AS event_payload,\n ${alias}.headers::text AS event_headers,\n ${alias}.correlation_id AS event_correlation_id,\n ${alias}.causation_id AS event_causation_id,\n ${isoText(`${alias}.occurred_at`)} AS event_occurred_at`;\n}\n\n/** `WITH changed AS (<dml> RETURNING 1) SELECT count(*)`: a top-level SELECT works the same on every driver. */\nexport function countChanged(dml: string): string {\n return `WITH changed AS (${dml} RETURNING 1) SELECT count(*)::int AS count FROM changed`;\n}\n\n/**\n * The head (lowest pending sequence) of every key of every wanted handler in the lane `scope.lane`,\n * as a subquery returning `(id, lane, available_at, handler, key)`. A loose index scan on the\n * pending-key index hops from key to key of a handler, and after its last key on to the first key of\n * the next wanted handler, so the cost follows the number of keys, not the number of followers. The\n * handlers are walked inside the recursion instead of joined to it: a join multiplied the planner's\n * cost estimate by the handler count, which pushed the claim statements over `jit_above_cost`, and\n * compiling them took longer than running them.\n */\nexport function keyHeads(names: PostgresNames, scope: string): string {\n const deliveries = names.deliveries;\n // `key IS NOT NULL` is spelled out only where nothing else implies it: next to `key > ...` or\n // `key = ...` the planner proves the partial index from those, and with the column all null in the\n // statistics the extra clause made it expect one row behind many index entries and cost every hop as a\n // full range scan.\n const pending = `candidate.lane = ${scope}.lane AND candidate.status = 'pending'`;\n const nextHandler = (after: string): string =>\n `(SELECT min(wanted.handler) FROM jsonb_array_elements_text($2::jsonb) AS wanted (handler)${after === '' ? '' : ` WHERE wanted.handler > ${after}`})`;\n return `\n WITH RECURSIVE hops (handler, key) AS (\n SELECT ${nextHandler('')}, NULL::text\n UNION ALL\n SELECT CASE WHEN next.key IS NULL THEN ${nextHandler('hops.handler')} ELSE hops.handler END, next.key\n FROM hops\n CROSS JOIN LATERAL (\n SELECT CASE WHEN hops.key IS NULL\n THEN (SELECT candidate.key FROM ${deliveries} AS candidate\n WHERE ${pending} AND candidate.handler = hops.handler AND candidate.key IS NOT NULL\n ORDER BY candidate.key LIMIT 1)\n ELSE (SELECT candidate.key FROM ${deliveries} AS candidate\n WHERE ${pending} AND candidate.handler = hops.handler AND candidate.key > hops.key\n ORDER BY candidate.key LIMIT 1)\n END AS key\n OFFSET 0\n ) AS next\n WHERE hops.handler IS NOT NULL\n )\n SELECT lowest.id, lowest.lane, lowest.available_at, lowest.handler, lowest.key\n FROM hops\n CROSS JOIN LATERAL (\n SELECT candidate.id, candidate.lane, candidate.available_at, candidate.handler, candidate.key\n FROM ${deliveries} AS candidate\n WHERE ${pending} AND candidate.handler = hops.handler AND candidate.key = hops.key\n ORDER BY candidate.sequence LIMIT 1\n ) AS lowest\n WHERE hops.key IS NOT NULL\n `;\n}\n\n/** True when none of the lane's listed deliveries exists as a pending row. */\nexport function noRunningDelivery(names: PostgresNames, laneAlias: string): string {\n return `NOT EXISTS (\n SELECT 1 FROM unnest(${laneAlias}.in_flight) AS flying (id)\n JOIN ${names.deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n )`;\n}\n","import type { PostgresNames } from './names.js';\nimport {\n CLAIM_SCAN_WINDOW,\n HANDLER_PREDICATE,\n LANE_SCAN_WINDOW,\n eventColumns,\n keyHeads,\n noRunningDelivery,\n} from './statement-fragments.js';\n\nconst LANE_LIST = `ARRAY(SELECT jsonb_array_elements_text($4::jsonb)::smallint)`;\n\n/** Statements of the claim continued round by round, its record, reconciliation and lane handback. */\nexport class ClaimStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Fast claim: picks from the first {@link CLAIM_SCAN_WINDOW} due deliveries of\n * the given lanes in due order, which is everything the claim needs while the\n * front of the queue is not clogged with blocked followers of busy keys.\n * Parameters: `[now, handlersJson, limit, lanesJson]`. The lanes must be held\n * and locked by the caller.\n *\n * Always returns one row per picked delivery, or a single row whose\n * `delivery_id` is null when nothing was picked. `window_saturated` says\n * whether the window was full: when it is and fewer than `limit` deliveries\n * were picked, deliveries beyond the window may still be claimable and the\n * caller runs {@link claimBehindBlockedKeys}. When the window is not\n * saturated every due delivery was examined, so the result is complete.\n *\n * A delivery is a candidate when it is pending, due, and not in flight. A\n * keyed delivery is a candidate only when it is the head of its (handler,\n * key), that is (a) no earlier delivery of that handler and key is pending\n * (an earlier one in flight is still a pending row, which is the ordering\n * guarantee), and (b) no other delivery of that handler and key is in\n * flight, which covers a delivery that re-enters the key behind a running one\n * (requeue, or a handler added to an old event).\n *\n * No row is locked or written here: the lanes' exclusive leases are the\n * mutual exclusion, so two claimers never see the same lane.\n */\n get claim(): string {\n return `WITH ${this.#scopeAndRunning(`SELECT lane.lane, lane.epoch, lane.in_flight FROM ${this.#names.lanes} AS lane WHERE lane.lane = ANY (${LANE_LIST})`)},\n${this.#fastWindow()}\n)\n${this.#pickedRows(`((SELECT count(*) FROM due_window) >= ${CLAIM_SCAN_WINDOW} OR EXISTS (SELECT 1 FROM due_window GROUP BY lane HAVING count(*) >= ${LANE_SCAN_WINDOW}))`)}`;\n }\n\n /** The `due_window` and `candidates` CTEs of the fast claim, up to (not including) the closing parenthesis of `candidates`. */\n #fastWindow(): string {\n const deliveries = this.#names.deliveries;\n return `due_window AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at\n FROM scope\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = scope.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (scope.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${LANE_SCAN_WINDOW}\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT ${CLAIM_SCAN_WINDOW}\n), candidates AS MATERIALIZED (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM due_window\n JOIN ${deliveries} AS delivery ON delivery.id = due_window.id\n WHERE delivery.key IS NULL OR NOT (${this.#blockedKey('delivery')})\n ORDER BY delivery.available_at, delivery.id\n LIMIT $3::int`;\n }\n\n /**\n * Slow claim, run when {@link claim} picked too few deliveries from a full\n * window: the front of the due queue is mostly followers of blocked keys.\n * Same parameters and rules as {@link claim}, but heads are found with\n * a loose index scan over the pending-key index of each lane (it hops from key\n * to key), so the cost follows the number of pending keys in the lanes\n * instead of one probe per due follower.\n */\n get claimBehindBlockedKeys(): string {\n const deliveries = this.#names.deliveries;\n return `WITH ${this.#scopeAndRunning(`SELECT lane.lane, lane.epoch, lane.in_flight FROM ${this.#names.lanes} AS lane WHERE lane.lane = ANY (${LANE_LIST})`)},\nheads AS MATERIALIZED (\n SELECT head.id, head.lane, head.available_at, head.handler, head.key\n FROM scope\n CROSS JOIN LATERAL (${keyHeads(this.#names, 'scope')}) AS head\n), keyed AS MATERIALIZED (\n SELECT heads.id, heads.lane, heads.available_at\n FROM heads\n JOIN scope ON scope.lane = heads.lane\n WHERE heads.available_at <= $1::timestamptz AND heads.id <> ALL (scope.in_flight)\n AND NOT EXISTS (SELECT 1 FROM running WHERE running.handler = heads.handler AND running.key = heads.key)\n ORDER BY heads.available_at, heads.id\n LIMIT $3::int\n), unkeyed AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at\n FROM scope\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = scope.lane AND delivery.key IS NULL AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (scope.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT $3::int\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT $3::int\n), candidates AS MATERIALIZED (\n SELECT id, lane, available_at FROM (\n SELECT id, lane, available_at FROM keyed\n UNION ALL\n SELECT id, lane, available_at FROM unkeyed\n ) AS both_sets\n ORDER BY available_at, id\n LIMIT $3::int\n)\n${this.#pickedRows('false')}`;\n }\n\n /** The held lanes with their epochs and in-flight ids, and the keyed deliveries running in them. */\n #scopeAndRunning(scopeQuery: string): string {\n const deliveries = this.#names.deliveries;\n return `scope AS MATERIALIZED (\n ${scopeQuery}\n), running AS MATERIALIZED (\n SELECT delivery.handler, delivery.key\n FROM scope\n CROSS JOIN LATERAL unnest(scope.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id\n WHERE delivery.status = 'pending' AND delivery.key IS NOT NULL\n)`;\n }\n\n /** True when an earlier delivery of the candidate's handler and key is pending, or another one is running. */\n #blockedKey(alias: string): string {\n return `EXISTS (\n SELECT 1 FROM ${this.#names.deliveries} AS earlier\n WHERE earlier.lane = ${alias}.lane AND earlier.handler = ${alias}.handler AND earlier.key = ${alias}.key\n AND earlier.status = 'pending' AND earlier.key IS NOT NULL\n AND earlier.sequence < ${alias}.sequence\n ) OR ${this.#runningElsewhere(alias)}`;\n }\n\n /** True when a delivery of the candidate's handler and key is in flight. The candidate itself never is. */\n #runningElsewhere(alias: string): string {\n return `EXISTS (\n SELECT 1 FROM running\n WHERE running.handler = ${alias}.handler AND running.key = ${alias}.key\n )`;\n }\n\n /** Final SELECT shared by both claims: the picked deliveries with their lane epoch and event. */\n #pickedRows(saturated: string): string {\n return `SELECT ${saturated} AS window_saturated, picked.*\nFROM (SELECT 1) AS anchor\nLEFT JOIN (\n ${this.#pickedRowsSelect()}\n) AS picked ON true\nORDER BY picked.due_at, picked.delivery_id`;\n }\n\n /** The picked deliveries joined with the lane epoch and their event, as the claim result columns. */\n #pickedRowsSelect(): string {\n return `SELECT candidates.available_at AS due_at, delivery.id AS delivery_id, delivery.lane::int AS lane,\n scope.epoch::text AS epoch, delivery.claims AS claims, delivery.handler, delivery.key AS delivery_key, delivery.sequence::text AS sequence, (delivery.attempts + 1)::int AS attempt,\n ${eventColumns('event')}\n FROM candidates\n JOIN scope ON scope.lane = candidates.lane\n JOIN ${this.#names.deliveries} AS delivery ON delivery.id = candidates.id\n JOIN ${this.#names.events} AS event ON event.id = delivery.event_id`;\n }\n\n /**\n * Records the deliveries a claim picked in their lanes and frees the lanes it\n * took or held for nothing. Parameters:\n * `[pickedJson, idleLanesJson, leaseOwner, leaseExpiresAt]` with\n * `pickedJson = [{ lane, ids }]`.\n *\n * A picked lane lists the ids that are still in flight (listed ids whose row\n * still exists) plus the new ones, and its lease reaches `leaseExpiresAt`.\n * An idle lane is freed when no delivery of it is in flight, so other workers\n * need not wait for the lease to expire.\n */\n get recordClaim(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `WITH picked AS (\n SELECT recorded.lane, recorded.ids\n FROM jsonb_to_recordset($1::jsonb) AS recorded (lane smallint, ids text[])\n), still_running AS (\n SELECT lane.lane, array_agg(delivery.id) AS ids\n FROM picked\n JOIN ${lanes} AS lane ON lane.lane = picked.lane\n CROSS JOIN LATERAL unnest(lane.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n GROUP BY lane.lane\n), extended AS (\n UPDATE ${lanes} AS lane\n SET in_flight = COALESCE(still_running.ids, '{}') || picked.ids,\n lease_expires_at = GREATEST(lane.lease_expires_at, $4::timestamptz)\n FROM picked\n LEFT JOIN still_running ON still_running.lane = picked.lane\n WHERE lane.lane = picked.lane\n RETURNING lane.lane\n), freed AS (\n UPDATE ${lanes} AS lane\n SET lease_owner = NULL, lease_expires_at = NULL, in_flight = '{}'\n WHERE lane.lane = ANY (ARRAY(SELECT jsonb_array_elements_text($2::jsonb)::smallint))\n AND lane.lease_owner = $3::text\n AND ${noRunningDelivery(this.#names, 'lane')}\n RETURNING lane.lane\n)\nSELECT (SELECT count(*) FROM extended)::int AS extended, (SELECT count(*) FROM freed)::int AS freed`;\n }\n\n /**\n * Keeps in the in-flight lists of the lanes `$1` holds only the claims in `$2`\n * (`[{ id, lane, epoch, claims }]`, the ones this store handed out and nobody\n * settled yet) and takes every other delivery out. That is a batch a claim\n * recorded but whose answer never arrived: nothing runs it and the lane lease,\n * renewed by the owner's other deliveries, would keep it away from everybody for\n * ever. A claim matches only with the lane epoch and the delivery generation it was\n * handed out with. Parameters: `[leaseOwner, handedOutJson, generation]`; a lane whose `claim_floor` is above\n * the generation was reconciled by a newer call, so an older (late) reconciliation leaves it alone.\n * The lanes are locked in lane order first (see the lock order on {@link PostgresStatements}).\n */\n get reconcileClaims(): string {\n const deliveries = this.#names.deliveries;\n const handedOut = `jsonb_to_recordset($2::jsonb) AS handed (id text, lane smallint, epoch bigint, claims int)`;\n const kept = `SELECT 1 FROM ${handedOut} JOIN ${deliveries} AS delivery ON delivery.id = handed.id\n WHERE handed.id = flying.id AND handed.lane = lane.lane AND handed.epoch = lane.epoch AND delivery.claims = handed.claims`;\n return `WITH owned AS MATERIALIZED (\n SELECT lane.lane FROM ${this.#names.lanes} AS lane\n WHERE lane.lease_owner = $1::text AND lane.claim_floor <= $3::bigint\n ORDER BY lane.lane\n FOR NO KEY UPDATE\n)\nUPDATE ${this.#names.lanes} AS lane\nSET in_flight = ARRAY(SELECT flying.id FROM unnest(lane.in_flight) AS flying (id) WHERE EXISTS (${kept})),\n claim_floor = $3::bigint\nFROM owned\nWHERE lane.lane = owned.lane AND lane.lease_owner = $1::text AND lane.claim_floor <= $3::bigint`;\n }\n\n /**\n * Frees every lane `$1` holds that has no running delivery, locking them in lane order first.\n * Parameters: `[leaseOwner]`.\n */\n get relinquish(): string {\n return `WITH owned AS MATERIALIZED (\n SELECT lane.lane FROM ${this.#names.lanes} AS lane\n WHERE lane.lease_owner = $1::text\n ORDER BY lane.lane\n FOR NO KEY UPDATE\n)\nUPDATE ${this.#names.lanes} AS lane\nSET lease_owner = NULL, lease_expires_at = NULL, in_flight = '{}'\nFROM owned\nWHERE lane.lane = owned.lane AND lane.lease_owner = $1::text AND ${noRunningDelivery(this.#names, 'lane')}`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { countChanged } from './statement-fragments.js';\n\n/** Fenced statements that end or extend a claim. */\nexport class CompletionStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Extends the lease of the lane a running delivery belongs to; the lane lease\n * never shrinks. Parameters: `[deliveryId, lane, epoch, claims, leaseExpiresAt]`.\n */\n get extendLease(): string {\n return countChanged(`UPDATE ${this.#names.lanes} AS lane\nSET lease_expires_at = GREATEST(lane.lease_expires_at, $5::timestamptz)\nWHERE lane.lane = $2::smallint AND lane.epoch = $3::bigint AND $1::text = ANY (lane.in_flight)\n AND EXISTS (\n SELECT 1 FROM ${this.#names.deliveries} AS delivery\n WHERE delivery.id = $1::text AND delivery.status = 'pending' AND delivery.claims = $4::int\n )`);\n }\n\n /**\n * Deletes the running deliveries whose lane lease is still the one they were\n * claimed under. Parameters: `[leasesJson, now]` with\n * `leasesJson = [{ ord, id, lane, epoch, claims }]`. Returns the `ord` of every lease that was completed, so\n * results are matched to leases and not to delivery ids. A delivery is only deleted by the claim that\n * is still its current one (`claims`), which makes a stale lease harmless even when the same owner re-claimed\n * the delivery in the same lane epoch. The event gets a completion time for retention.\n *\n * The lane rows are locked `FOR KEY SHARE` first, in lane order, and the lock\n * is held until the surrounding transaction ends. A claimer that takes the\n * lane over locks it `FOR UPDATE`, which conflicts with that lock, so it\n * skips the lane until this completion commits or rolls back: a completion\n * and a takeover cannot both succeed for one delivery, which is what makes a\n * transactional handler's writes effectively-once. The weakest lock that\n * conflicts with a takeover is used on purpose: it does not conflict with the\n * owner's own claim and heartbeats (plain updates of the lane row), which\n * would otherwise wait for every completion in progress. With a completion history the deleted rows are copied to\n * it in the same statement.\n */\n get complete(): string {\n const deliveries = this.#names.deliveries;\n const history = this.#names.completionHistory;\n return `WITH leases AS (\n SELECT lease.ord, lease.id, lease.lane, lease.epoch, lease.claims\n FROM jsonb_to_recordset($1::jsonb) AS lease (ord int, id text, lane smallint, epoch bigint, claims int)\n), fence AS MATERIALIZED (\n SELECT lane.lane, lane.epoch, lane.in_flight\n FROM ${this.#names.lanes} AS lane\n WHERE lane.lane IN (SELECT lane FROM leases)\n ORDER BY lane.lane\n FOR KEY SHARE\n), completed AS (\n DELETE FROM ${deliveries} AS delivery\n USING leases JOIN fence ON fence.lane = leases.lane AND fence.epoch = leases.epoch\n WHERE delivery.id = leases.id AND delivery.lane = leases.lane AND delivery.status = 'pending'\n AND delivery.claims = leases.claims AND leases.id = ANY (fence.in_flight)\n RETURNING leases.ord, delivery.id, delivery.event_id, delivery.handler, delivery.attempts, delivery.available_at, delivery.created_at\n), stamped AS (\n INSERT INTO ${this.#names.eventCompletions} (event_id, completed_at)\n SELECT DISTINCT completed.event_id, $2::timestamptz FROM completed\n -- Event id order: completions of other handlers of the same events lock these rows too.\n ORDER BY completed.event_id\n ON CONFLICT (event_id) DO UPDATE SET completed_at = GREATEST(${this.#names.eventCompletions}.completed_at, EXCLUDED.completed_at)\n RETURNING event_id\n)${\n history\n ? `, archived AS (\n INSERT INTO ${this.#names.completions} (id, event_id, handler, attempts, available_at, created_at, completed_at)\n SELECT id, event_id, handler, attempts + 1, available_at, created_at, $2::timestamptz FROM completed\n RETURNING id\n)`\n : ''\n }\nSELECT ord FROM completed`;\n }\n\n /**\n * Returns a running delivery to pending, due at `availableAt`, and takes it\n * out of the lane's in-flight list. Parameters:\n * `[deliveryId, lane, epoch, claims, availableAt, errorJson, now]`. The attempt that\n * just ended is counted.\n */\n get reschedule(): string {\n return this.#leaveFlight(\n `SET available_at = $5::timestamptz, last_error = $6::jsonb, attempts = delivery.attempts + 1, claims = delivery.claims + 1, updated_at = $7::timestamptz`,\n );\n }\n\n /** Parameters: `[deliveryId, lane, epoch, claims, errorJson, now]`. The attempt that just ended is counted. */\n get bury(): string {\n return this.#leaveFlight(\n `SET status = 'dead', last_error = $5::jsonb, attempts = delivery.attempts + 1, claims = delivery.claims + 1, updated_at = $6::timestamptz`,\n );\n }\n\n /**\n * Gives a running delivery back without spending its attempt (an attempt is\n * only recorded when it ends in failure or a lost lease): pending, due `now`.\n * Parameters: `[deliveryId, lane, epoch, claims, now]`.\n */\n get release(): string {\n return this.#leaveFlight(\n `SET available_at = $5::timestamptz, claims = delivery.claims + 1, updated_at = $5::timestamptz`,\n );\n }\n\n /**\n * Applies `assignments` to a running delivery and removes it from its lane's\n * in-flight list, if the lane still has the caller's epoch. The lane row is\n * locked first (`FOR NO KEY UPDATE`, which conflicts with a takeover's `FOR UPDATE`), so a takeover cannot interleave. Parameters\n * `$1`..`$4` are always `[deliveryId, lane, epoch, claims]`; ending a claim bumps `claims`.\n */\n #leaveFlight(assignments: string): string {\n const lanes = this.#names.lanes;\n return `WITH fence AS MATERIALIZED (\n SELECT lane.lane FROM ${lanes} AS lane\n WHERE lane.lane = $2::smallint AND lane.epoch = $3::bigint AND $1::text = ANY (lane.in_flight)\n FOR NO KEY UPDATE\n), changed AS (\n UPDATE ${this.#names.deliveries} AS delivery ${assignments}\n FROM fence\n WHERE delivery.id = $1::text AND delivery.lane = fence.lane AND delivery.status = 'pending'\n AND delivery.claims = $4::int\n RETURNING delivery.id\n), trimmed AS (\n UPDATE ${lanes} AS lane SET in_flight = array_remove(lane.in_flight, $1::text)\n FROM changed WHERE lane.lane = $2::smallint\n RETURNING lane.lane\n)\nSELECT count(*)::int AS count FROM changed`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport {\n CLAIM_SCAN_WINDOW,\n HANDLER_PREDICATE,\n LANE_SCAN_WINDOW,\n keyHeads,\n} from './statement-fragments.js';\n\n/** Which lanes `#candidates` picks from, under which CTE names, and how many. */\ntype CandidateSpec = {\n readonly prefix: string;\n readonly scope: string;\n readonly running: string | null;\n readonly limit: string;\n};\n\n/** True for a delivery whose (handler, key) runs nowhere in the CTE `running`; always true without one. */\nfunction notRunning(running: string | null, alias: string): string {\n return running === null\n ? 'true'\n : `NOT EXISTS (SELECT 1 FROM ${running} AS running WHERE running.handler = ${alias}.handler AND running.key = ${alias}.key)`;\n}\n\n/** Statements that pick the claimable deliveries of a set of lanes, as CTEs a claim embeds. */\nexport class CandidateStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * CTEs that pick up to `limit` claimable deliveries from the lanes of the CTE `scope` (columns `lane`,\n * `epoch`, `in_flight`), named after `prefix`; the result is `<prefix>_candidates (id, lane, available_at)`.\n * The rules are those of `ClaimStatements.claim`. The fast window reads the first {@link LANE_SCAN_WINDOW} due\n * deliveries of each lane (at most {@link CLAIM_SCAN_WINDOW} together); of a key, only the lowest sequence\n * in the window can be its head, so only that one is checked for an earlier pending delivery. Only when\n * that yields fewer than `limit` are the lanes whose window filled up looked at again with a loose index\n * scan over the heads of all their keys. `running` names the CTE of the keyed deliveries running in the\n * lanes, or is null when nothing runs there.\n */\n candidates(\n prefix: string,\n {\n scope,\n running,\n limit,\n }: { readonly scope: string; readonly running: string | null; readonly limit: string },\n ): string {\n const spec: CandidateSpec = { prefix, scope, running, limit };\n return this.#fastCandidates(spec) + this.#slowCandidates(spec);\n }\n\n /** The fast window of each lane and the claimable deliveries in it (`<prefix>_window`, `<prefix>_fast`). */\n #fastCandidates({ prefix, scope, running, limit }: CandidateSpec): string {\n const deliveries = this.#names.deliveries;\n return `${prefix}_window AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at, recent.handler, recent.key, recent.sequence\n FROM ${scope}\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at, delivery.handler, delivery.key, delivery.sequence\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = ${scope}.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (${scope}.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${LANE_SCAN_WINDOW}\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT ${CLAIM_SCAN_WINDOW}\n), ${prefix}_fast AS MATERIALIZED (\n SELECT picked.id, picked.lane, picked.available_at FROM (\n SELECT unkeyed.id, unkeyed.lane, unkeyed.available_at FROM ${prefix}_window AS unkeyed WHERE unkeyed.key IS NULL\n UNION ALL\n SELECT head.id, head.lane, head.available_at\n FROM (\n SELECT DISTINCT ON (keyed.handler, keyed.key) keyed.id, keyed.lane, keyed.available_at, keyed.handler, keyed.key, keyed.sequence\n FROM ${prefix}_window AS keyed\n WHERE keyed.key IS NOT NULL\n ORDER BY keyed.handler, keyed.key, keyed.sequence\n ) AS head\n WHERE NOT EXISTS (\n SELECT 1 FROM ${deliveries} AS earlier\n WHERE earlier.lane = head.lane AND earlier.handler = head.handler AND earlier.key = head.key\n AND earlier.status = 'pending' AND earlier.key IS NOT NULL AND earlier.sequence < head.sequence\n ) AND ${notRunning(running, 'head')}\n ) AS picked\n ORDER BY picked.available_at, picked.id\n LIMIT ${limit}\n`;\n }\n\n /**\n * For lanes whose window filled up while the fast pick came up short: the heads of all their keys and\n * their unkeyed deliveries, then the union with the fast pick (`<prefix>_candidates`).\n */\n #slowCandidates(spec: CandidateSpec): string {\n return (\n this.#saturatedLanes(spec) +\n this.#keyHeads(spec) +\n this.#keyedHeads(spec) +\n this.#unkeyedRecent(spec) +\n this.#unionCandidates(spec)\n );\n }\n\n /** `<prefix>_saturated`: the lanes whose window filled up while the fast pick came up short. */\n #saturatedLanes({ prefix, scope, limit }: CandidateSpec): string {\n return `), ${prefix}_saturated AS MATERIALIZED (\n SELECT ${scope}.lane, ${scope}.in_flight FROM ${scope}\n WHERE (SELECT count(*) FROM ${prefix}_fast) < ${limit}\n AND ((SELECT count(*) FROM ${prefix}_window) >= ${CLAIM_SCAN_WINDOW}\n OR ${scope}.lane IN (\n SELECT full_lane.lane FROM ${prefix}_window AS full_lane\n GROUP BY full_lane.lane HAVING count(*) >= ${LANE_SCAN_WINDOW}\n ))\n`;\n }\n\n /** `<prefix>_heads`: the head of every key of the saturated lanes. */\n #keyHeads({ prefix }: CandidateSpec): string {\n return `), ${prefix}_heads AS MATERIALIZED (\n SELECT head.id, head.lane, head.available_at, head.handler, head.key\n FROM ${prefix}_saturated AS scope\n CROSS JOIN LATERAL (${keyHeads(this.#names, 'scope')}) AS head\n`;\n }\n\n /** `<prefix>_keyed`: the due heads that are not in flight and whose key runs nowhere. */\n #keyedHeads({ prefix, running, limit }: CandidateSpec): string {\n return `), ${prefix}_keyed AS MATERIALIZED (\n SELECT heads.id, heads.lane, heads.available_at\n FROM ${prefix}_heads AS heads\n JOIN ${prefix}_saturated AS scope ON scope.lane = heads.lane\n WHERE heads.available_at <= $1::timestamptz AND heads.id <> ALL (scope.in_flight) AND ${notRunning(running, 'heads')}\n ORDER BY heads.available_at, heads.id\n LIMIT ${limit}\n`;\n }\n\n /** `<prefix>_unkeyed`: the due unkeyed deliveries of the saturated lanes that are not in flight. */\n #unkeyedRecent({ prefix, limit }: CandidateSpec): string {\n const deliveries = this.#names.deliveries;\n return `), ${prefix}_unkeyed AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at\n FROM ${prefix}_saturated AS scope\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = scope.lane AND delivery.key IS NULL AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (scope.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${limit}\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT ${limit}\n`;\n }\n\n /** `<prefix>_candidates`: the union of the fast pick and the slow picks, oldest first, at most `limit`. */\n #unionCandidates({ prefix, limit }: CandidateSpec): string {\n return `), ${prefix}_candidates AS MATERIALIZED (\n SELECT chosen.id, chosen.lane, chosen.available_at FROM (\n SELECT fast.id, fast.lane, fast.available_at FROM ${prefix}_fast AS fast\n UNION\n SELECT keyed.id, keyed.lane, keyed.available_at FROM ${prefix}_keyed AS keyed\n UNION\n SELECT unkeyed.id, unkeyed.lane, unkeyed.available_at FROM ${prefix}_unkeyed AS unkeyed\n ) AS chosen\n ORDER BY chosen.available_at, chosen.id\n LIMIT ${limit}\n)`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { CandidateStatements } from './statements-candidates.js';\nimport {\n CLAIM_SCAN_WINDOW,\n HANDLER_PREDICATE,\n INITIAL_FREE_LANES,\n LANE_DEPTH_CAP,\n LANE_SCAN_WINDOW,\n eventColumns,\n noRunningDelivery,\n} from './statement-fragments.js';\n\n/**\n * Free lanes a claim looks at beyond the number of deliveries it still wants, so lanes whose due\n * deliveries all wait behind a key's later head do not hide the others. When even these are not enough\n * the claim continues in the transaction that takes lanes round by round.\n */\nconst FREE_LANE_SURPLUS = 16;\n\n/** A free lane: its lease expired, or this owner left it behind under an older claim floor. */\nconst freeLane = (alias: string): string =>\n `(${alias}.lease_expires_at IS NULL OR ${alias}.lease_expires_at <= $1::timestamptz\n OR (${alias}.lease_owner = $4::text AND ${alias}.claim_floor < $6::bigint))`;\n\n/** The free-lane CTEs of a claim that only looks at the lanes it holds: all empty. */\nconst NO_FREE_LANES = `), free_lanes AS (\n SELECT NULL::smallint AS lane, NULL::bigint AS epoch, NULL::text[] AS in_flight, false AS running WHERE false\n), free_scope AS (\n SELECT NULL::smallint AS lane, NULL::bigint AS epoch WHERE false\n), free_candidates AS (\n SELECT NULL::text AS id, NULL::smallint AS lane, NULL::timestamptz AS available_at WHERE false\n)`;\n\n/** Statements that claim with the lanes they hold or take: the one-statement claim and the lane takeover. */\nexport class LaneStatements {\n readonly #names: PostgresNames;\n readonly #candidateStatements: CandidateStatements;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n this.#candidateStatements = new CandidateStatements(names);\n }\n\n /**\n * A claim in one statement, the only one in the common case. Parameters:\n * `[now, handlersJson, limit, leaseOwner, leaseExpiresAt, generation]`.\n *\n * 1. **Held lanes.** The lanes this owner holds under a live lease whose `claim_floor` is exactly the\n * generation are locked `FOR NO KEY UPDATE` in lane order. A lane above it was raised by a\n * reconciliation, so a statement of a claim whose caller gave up (a client timeout does not cancel\n * the statement on the server) and that reaches the server late records nothing; a lane below it was\n * taken by such a late statement after the reconciliation, and its listed deliveries were never\n * handed out. A lane that another transaction of this owner is changing makes the statement wait;\n * the statement then reports `stale` and does nothing (see the `stale` CTE).\n * 2. **Free lanes**, only when the held lanes yield fewer than `limit`: the free lanes with a due\n * delivery (one index probe per free lane) are ranked by their oldest due delivery; the first\n * {@link INITIAL_FREE_LANES} that can give something now, and further ones until what they can give\n * (estimated from their first {@link LANE_DEPTH_CAP} due deliveries) covers what is still wanted, are locked\n * `FOR UPDATE SKIP LOCKED`, so a lane another claimer has is skipped, never waited\n * for. A lane that still runs deliveries of an expired lease is left to the transaction of\n * {@link takeFreeLanes}, which charges their lost attempts (`takeover_waiting`); so is any lane whose\n * locked row differs from what the statement's snapshot saw. A lane that runs nothing and did not\n * change cannot have had a delivery written since the snapshot, so its deliveries can be read here.\n * 3. **Picks** follow the rules of `ClaimStatements.claim`: the fast window of each lane, and for lanes whose\n * window filled up while the batch is not full, the heads of all keys (a loose index scan per lane).\n * 4. **Writes**: one update per lane. A held lane records its picks; a taken lane gets a new epoch, the\n * owner, the lease and its picks; a taken lane that yielded nothing is not written. Held lanes that\n * picked nothing, run nothing and have no full scan window are freed.\n *\n * Always returns one row per picked delivery, or one row whose `delivery_id` is null. `running_ids`\n * (JSON text) lists the deliveries the held lanes still run, `examined_lanes` the held lanes.\n */\n get claimLanes(): string {\n return this.#claimLanes(true);\n }\n\n /**\n * {@link claimLanes} limited to the lanes the owner holds: the same parameters, rows and writes, without\n * looking at free lanes (`takeover_waiting` and `unexamined_free_lanes` are false). A worker draining a\n * backlog finds its batch in the lanes it holds; this statement is about half as costly to plan, and\n * the caller runs {@link claimLanes} after it only when it came up short.\n */\n get claimHeldLanes(): string {\n return this.#claimLanes(false);\n }\n\n #claimLanes(includeFreeLanes: boolean): string {\n const free = includeFreeLanes\n ? this.#freeLaneChoice() + this.#freeLaneDepth() + this.#freeLaneTake()\n : NO_FREE_LANES;\n return (\n this.#heldLanes() + free + this.#claimPicks() + this.#claimRecord() + this.#claimRelease()\n );\n }\n\n /** Locks the held lanes, detects a stale snapshot and picks from the held lanes; ends with `wanted`. */\n #heldLanes(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `WITH held AS MATERIALIZED (\n SELECT lane.lane, lane.epoch, lane.in_flight\n FROM ${lanes} AS lane\n WHERE lane.lease_owner = $4::text AND lane.lease_expires_at > $1::timestamptz\n AND lane.claim_floor = $6::bigint\n ORDER BY lane.lane\n FOR NO KEY UPDATE\n), stale AS (\n -- A claim that waited for a lane lock sees the new lane row but reads deliveries with the snapshot it took\n -- before the wait: whatever changed the lane meanwhile (a reschedule, a release) may also have changed\n -- deliveries it cannot see. The statement then does nothing and reports it, and the caller runs it again.\n SELECT EXISTS (\n SELECT 1 FROM held\n JOIN ${lanes} AS before ON before.lane = held.lane\n WHERE before.epoch <> held.epoch OR before.in_flight IS DISTINCT FROM held.in_flight\n ) AS value\n), held_scope AS MATERIALIZED (\n SELECT held.lane, held.epoch, held.in_flight FROM held WHERE NOT (SELECT value FROM stale)\n), held_running AS MATERIALIZED (\n SELECT delivery.handler, delivery.key\n FROM held_scope\n CROSS JOIN LATERAL unnest(held_scope.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id\n WHERE delivery.status = 'pending' AND delivery.key IS NOT NULL\n), ${this.#candidateStatements.candidates('held', { scope: 'held_scope', running: 'held_running', limit: '$3::int' })}, wanted AS MATERIALIZED (\n SELECT CASE WHEN (SELECT value FROM stale) THEN 0\n ELSE $3::int - (SELECT count(*) FROM held_candidates)::int END AS count\n`;\n }\n\n /** The oldest due delivery of each free lane, at most the number still wanted plus a surplus. */\n #freeLaneChoice(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `), free_lanes AS MATERIALIZED (\n -- The oldest due delivery of each free lane: one index probe per free lane, bounded by the due time,\n -- so deliveries scheduled for later are never read.\n SELECT lane.lane, lane.epoch, lane.in_flight, lane.lease_owner, lane.lease_expires_at,\n oldest.available_at, oldest.id, NOT ${noRunningDelivery(this.#names, 'lane')} AS running\n FROM ${lanes} AS lane\n CROSS JOIN LATERAL (\n SELECT delivery.available_at, delivery.id\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = lane.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n ORDER BY delivery.available_at, delivery.id\n LIMIT 1\n ) AS oldest\n WHERE (SELECT count FROM wanted) > 0 AND ${freeLane('lane')}\n ORDER BY oldest.available_at, oldest.id\n LIMIT (SELECT count FROM wanted) + ${FREE_LANE_SURPLUS}\n`;\n }\n\n /** What each free candidate lane can give now, and their order. */\n #freeLaneDepth(): string {\n const deliveries = this.#names.deliveries;\n return `), free_depth AS MATERIALIZED (\n -- What each candidate lane can give now, from its first due deliveries: unkeyed ones, and of a key its\n -- lowest one when nothing earlier of the key is pending. Lanes that can give nothing are passed over;\n -- of the others, the first ${INITIAL_FREE_LANES} are taken, and further ones until they cover what is\n -- still wanted, so the earliest due work of the free lanes comes first.\n SELECT runnable.lane,\n row_number() OVER (ORDER BY runnable.available_at, runnable.id) AS rank,\n sum(runnable.count) OVER (ORDER BY runnable.available_at, runnable.id ROWS UNBOUNDED PRECEDING) - runnable.count AS due_before\n FROM (\n SELECT lane_candidate.lane, lane_candidate.available_at, lane_candidate.id, depth.count\n FROM free_lanes AS lane_candidate\n CROSS JOIN LATERAL (\n -- A full window that shows nothing runnable may hide runnable work behind it: such a lane counts\n -- once, and the claim looks behind its blocked deliveries.\n SELECT GREATEST(count(*) FILTER (\n WHERE due.key IS NULL OR (due.position = 1 AND NOT EXISTS (\n SELECT 1 FROM ${deliveries} AS earlier\n WHERE earlier.lane = due.lane AND earlier.handler = due.handler AND earlier.key = due.key\n AND earlier.status = 'pending' AND earlier.key IS NOT NULL AND earlier.sequence < due.sequence\n ))\n ), CASE WHEN count(*) >= ${LANE_DEPTH_CAP} THEN 1 ELSE 0 END) AS count\n FROM (\n SELECT window_rows.*,\n row_number() OVER (PARTITION BY window_rows.handler, window_rows.key ORDER BY window_rows.sequence) AS position\n FROM (\n SELECT delivery.lane, delivery.handler, delivery.key, delivery.sequence FROM ${deliveries} AS delivery\n WHERE delivery.lane = lane_candidate.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${LANE_DEPTH_CAP}\n ) AS window_rows\n ) AS due\n ) AS depth\n WHERE NOT lane_candidate.running AND depth.count > 0\n ) AS runnable\n`;\n }\n\n /** Locks the chosen free lanes that did not change hands and picks from them. */\n #freeLaneTake(): string {\n const lanes = this.#names.lanes;\n return `), free_locked AS MATERIALIZED (\n SELECT lane.lane, lane.epoch, lane.in_flight, lane.lease_owner, lane.lease_expires_at\n FROM ${lanes} AS lane\n WHERE lane.lane IN (\n SELECT chosen.lane FROM free_depth AS chosen\n WHERE chosen.rank <= ${INITIAL_FREE_LANES} OR chosen.due_before < (SELECT count FROM wanted)\n )\n AND ${freeLane('lane')}\n ORDER BY lane.lane\n FOR UPDATE SKIP LOCKED\n), free_scope AS MATERIALIZED (\n -- A lane whose locked row is not the one the snapshot saw changed hands meanwhile: left for a later claim.\n SELECT locked.lane, locked.epoch + 1 AS epoch, '{}'::text[] AS in_flight\n FROM free_locked AS locked\n JOIN free_lanes AS seen ON seen.lane = locked.lane\n WHERE locked.epoch = seen.epoch AND locked.in_flight = seen.in_flight\n AND locked.lease_owner IS NOT DISTINCT FROM seen.lease_owner\n AND locked.lease_expires_at IS NOT DISTINCT FROM seen.lease_expires_at\n), ${this.#candidateStatements.candidates('free', { scope: 'free_scope', running: null, limit: '(SELECT count FROM wanted)' })}`;\n }\n\n /** The picked deliveries of held and taken lanes with their events, and the picks per lane. */\n #claimPicks(): string {\n const deliveries = this.#names.deliveries;\n return `, claim_scope AS MATERIALIZED (\n SELECT held_scope.lane, held_scope.epoch FROM held_scope\n UNION ALL\n SELECT free_scope.lane, free_scope.epoch FROM free_scope\n), picked_rows AS MATERIALIZED (\n SELECT candidates.available_at AS due_at, delivery.id AS delivery_id, delivery.lane::int AS lane,\n scope.epoch::text AS epoch, delivery.claims AS claims, delivery.handler, delivery.key AS delivery_key, delivery.sequence::text AS sequence, (delivery.attempts + 1)::int AS attempt,\n ${eventColumns('event')}\n FROM (\n SELECT held_candidates.id, held_candidates.lane, held_candidates.available_at FROM held_candidates\n UNION ALL\n SELECT free_candidates.id, free_candidates.lane, free_candidates.available_at FROM free_candidates\n ) AS candidates\n JOIN claim_scope AS scope ON scope.lane = candidates.lane\n JOIN ${deliveries} AS delivery ON delivery.id = candidates.id\n JOIN ${this.#names.events} AS event ON event.id = delivery.event_id\n), by_lane AS (\n SELECT picked_rows.lane, array_agg(picked_rows.delivery_id) AS ids FROM picked_rows GROUP BY picked_rows.lane\n`;\n }\n\n /** Records the picks in the held lanes and takes the free lanes that yielded picks. */\n #claimRecord(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `), still_running AS (\n -- The retained ids come from the locked \\`held\\` rows, not from the lane table: a claim that waited for the lock\n -- must see the in-flight list the claim before it recorded, which the statement snapshot may not.\n SELECT held.lane, array_agg(delivery.id) AS ids\n FROM by_lane\n JOIN held ON held.lane = by_lane.lane\n CROSS JOIN LATERAL unnest(held.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n GROUP BY held.lane\n), extended AS (\n UPDATE ${lanes} AS lane\n SET in_flight = COALESCE(still_running.ids, '{}') || by_lane.ids,\n lease_expires_at = GREATEST(lane.lease_expires_at, $5::timestamptz)\n FROM by_lane\n JOIN held_scope ON held_scope.lane = by_lane.lane\n LEFT JOIN still_running ON still_running.lane = by_lane.lane\n WHERE lane.lane = by_lane.lane\n RETURNING lane.lane\n), taken AS (\n UPDATE ${lanes} AS lane\n SET epoch = free_scope.epoch, lease_owner = $4::text, lease_expires_at = $5::timestamptz,\n in_flight = by_lane.ids, claim_floor = $6::bigint\n FROM free_scope\n JOIN by_lane ON by_lane.lane = free_scope.lane\n WHERE lane.lane = free_scope.lane\n RETURNING lane.lane\n`;\n }\n\n /** Frees the held lanes that yielded nothing and run nothing, and selects the result rows. */\n #claimRelease(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `), saturated_lanes AS (\n SELECT held_window.lane FROM held_window GROUP BY held_window.lane HAVING count(*) >= ${LANE_SCAN_WINDOW}\n), freed AS (\n UPDATE ${lanes} AS lane\n SET lease_owner = NULL, lease_expires_at = NULL, in_flight = '{}'\n FROM held\n WHERE lane.lane = held.lane\n AND lane.lane NOT IN (SELECT lane FROM by_lane)\n AND lane.lane NOT IN (SELECT lane FROM saturated_lanes)\n AND (SELECT count(*) FROM held_window) < ${CLAIM_SCAN_WINDOW}\n AND NOT (SELECT value FROM stale)\n AND ${noRunningDelivery(this.#names, 'lane')}\n RETURNING lane.lane\n)\nSELECT (SELECT value FROM stale) AS stale,\n EXISTS (SELECT 1 FROM free_lanes WHERE free_lanes.running) AS takeover_waiting,\n (SELECT count(*) FROM free_lanes) = (SELECT count FROM wanted) + ${FREE_LANE_SURPLUS} AS unexamined_free_lanes,\n (\n SELECT COALESCE(jsonb_agg(delivery.id), '[]'::jsonb)\n FROM held\n CROSS JOIN LATERAL unnest(held.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n )::text AS running_ids,\n (SELECT COALESCE(jsonb_agg(held.lane), '[]'::jsonb) FROM held)::text AS examined_lanes,\n picked.*\nFROM (SELECT 1) AS anchor\nLEFT JOIN picked_rows AS picked ON true\nORDER BY picked.due_at, picked.delivery_id`;\n }\n\n /**\n * Takes up to `$3` free lanes (no lease, or an expired one) that have a due\n * delivery of the requested handlers, the ones with the oldest due delivery\n * first. Parameters: `[now, handlersJson, laneCount, leaseOwner, leaseExpiresAt, generation]`.\n * The lane gets the owner's `generation` as its `claim_floor`. A lane the owner itself holds under a live\n * lease with a lower floor was taken by a claim statement that reached the server after its caller gave up\n * and the owner reconciled (or by an earlier incarnation of the same owner): it is taken over like the lane of a\n * crashed worker, so its listed deliveries are charged an attempt.\n *\n * A taken lane gets a new epoch, which fences everything the previous owner\n * still holds. Deliveries the previous owner had in flight are the ones whose\n * attempt was never recorded (a claim writes no delivery row), so each of\n * them is charged one attempt here: a worker that crashes with a poison\n * message still runs it into the retry limit. Lanes another claimer has locked\n * are skipped, never waited for.\n */\n get takeFreeLanes(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `WITH picked AS (\n -- in_flight is read here, from the locked version of the lane: a settlement that committed after the\n -- statement took its snapshot has taken its delivery out of the list already and must not be charged again.\n SELECT free.lane, free.in_flight\n FROM ${lanes} AS free\n CROSS JOIN LATERAL (\n SELECT delivery.available_at, delivery.id\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = free.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n ORDER BY delivery.available_at, delivery.id\n LIMIT 1\n ) AS oldest\n WHERE free.lease_expires_at IS NULL OR free.lease_expires_at <= $1::timestamptz\n OR (free.lease_owner = $4::text AND free.claim_floor < $6::bigint)\n ORDER BY oldest.available_at, oldest.id\n LIMIT $3::int\n FOR UPDATE OF free SKIP LOCKED\n), charged AS (\n UPDATE ${deliveries} AS delivery SET attempts = delivery.attempts + 1, claims = delivery.claims + 1\n FROM (\n SELECT unnest(picked.in_flight) AS id FROM picked\n ) AS lost\n WHERE delivery.id = lost.id AND delivery.status = 'pending'\n RETURNING delivery.id\n), taken AS (\n UPDATE ${lanes} AS lane\n SET epoch = lane.epoch + 1, lease_owner = $4::text, lease_expires_at = $5::timestamptz, in_flight = '{}',\n claim_floor = $6::bigint\n FROM picked WHERE lane.lane = picked.lane\n RETURNING lane.lane, lane.epoch\n)\nSELECT lane::int AS lane, epoch::text AS epoch FROM taken ORDER BY lane`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { countChanged } from './statement-fragments.js';\n\n/** Statements that purge old deliveries and the events nothing references. */\nexport class PurgeStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Deletes one bounded batch of purgeable deliveries (or of the completion\n * history) and returns the event id of each deleted row. Parameters:\n * `[cutoff, batchSize]`. `FOR UPDATE SKIP LOCKED` keeps purge from waiting\n * on, or being waited on by, anything.\n */\n purgeCompletedBatch(): string {\n return this.#purgeBatch(this.#names.deliveries, {\n condition: `status = 'completed' AND completed_at < $1::timestamptz`,\n orderColumn: 'completed_at',\n });\n }\n\n purgeCompletionHistoryBatch(): string {\n return this.#purgeBatch(this.#names.completions, {\n condition: `completed_at < $1::timestamptz`,\n orderColumn: 'completed_at',\n });\n }\n\n purgeDeadBatch(): string {\n return this.#purgeBatch(this.#names.deliveries, {\n condition: `status = 'dead' AND updated_at < $1::timestamptz`,\n orderColumn: 'updated_at',\n });\n }\n\n /**\n * Selects and locks one bounded batch of events created before the cutoff\n * that no delivery references and that never had a delivery complete (those\n * are measured from their completion, see {@link lockCompletedOrphanEventsBatch}).\n * Parameters: `[cutoff, batchSize]`. The ids go through\n * {@link deleteOrphanEventsWithoutCompletion} or {@link deleteExpiredCompletedOrphanEvents}, which re-check under a fresh snapshot.\n */\n get lockOrphanEventsBatch(): string {\n return `SELECT event.id FROM ${this.#names.events} AS event\nWHERE event.created_at < $1::timestamptz\n AND ${this.#unreferenced('event')}\n AND NOT EXISTS (SELECT 1 FROM ${this.#names.eventCompletions} AS completion WHERE completion.event_id = event.id)\nORDER BY event.created_at, event.id\nLIMIT $2::int\nFOR UPDATE OF event SKIP LOCKED`;\n }\n\n /**\n * Like {@link lockOrphanEventsBatch} for events that had a delivery complete:\n * they go once their last completion is older than the cutoff, however old the\n * event itself is. Parameters: `[cutoff, batchSize]`.\n */\n get lockCompletedOrphanEventsBatch(): string {\n return `SELECT event.id FROM ${this.#names.events} AS event\nJOIN ${this.#names.eventCompletions} AS completion ON completion.event_id = event.id\nWHERE completion.completed_at < $1::timestamptz\n AND ${this.#unreferenced('event')}\nORDER BY completion.completed_at, event.id\nLIMIT $2::int\nFOR UPDATE OF event SKIP LOCKED`;\n }\n\n /**\n * Locks the given events, skipping any that a concurrent transaction is\n * referencing from a new delivery (a foreign key check holds `FOR KEY\n * SHARE`, which conflicts with this lock). Parameters: `[eventIdsJson]`.\n */\n get lockEvents(): string {\n return `SELECT id FROM ${this.#names.events}\nWHERE id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\nFOR UPDATE SKIP LOCKED`;\n }\n\n /**\n * Deletes events that no delivery references and whose last completion is older than\n * `$2`, checked again under the fresh snapshot of this statement: a completion recorded\n * after the sweep selected the event moves its time and keeps the event. Parameters:\n * `[eventIdsJson, cutoff]`.\n */\n get deleteExpiredCompletedOrphanEvents(): string {\n return countChanged(`DELETE FROM ${this.#names.events} AS event\nWHERE event.id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\n AND ${this.#unreferenced('event')}\n AND EXISTS (\n SELECT 1 FROM ${this.#names.eventCompletions} AS completion\n WHERE completion.event_id = event.id AND completion.completed_at < $2::timestamptz\n )`);\n }\n\n /**\n * Deletes locked events that no delivery references and that never had a delivery complete.\n * It must run as a statement of its own after {@link lockEvents}: it then takes a fresh\n * snapshot that includes every delivery committed before the lock was granted, so an event\n * that just gained a delivery is never cascaded away. Keeps events that had a delivery complete:\n * deleting dead letters must not shorten the retention of completed work.\n */\n get deleteOrphanEventsWithoutCompletion(): string {\n return countChanged(`DELETE FROM ${this.#names.events} AS event\nWHERE event.id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\n AND ${this.#unreferenced('event')}\n AND NOT EXISTS (SELECT 1 FROM ${this.#names.eventCompletions} AS completion WHERE completion.event_id = event.id)`);\n }\n\n /** True when no delivery and no completion history record references the event. */\n #unreferenced(eventAlias: string): string {\n const history = this.#names.completionHistory\n ? ` AND NOT EXISTS (SELECT 1 FROM ${this.#names.completions} AS done WHERE done.event_id = ${eventAlias}.id)`\n : '';\n return `NOT EXISTS (SELECT 1 FROM ${this.#names.deliveries} AS delivery WHERE delivery.event_id = ${eventAlias}.id)${history}`;\n }\n\n #purgeBatch(\n table: string,\n { condition, orderColumn }: { readonly condition: string; readonly orderColumn: string },\n ): string {\n return `WITH batch AS MATERIALIZED (\n SELECT id FROM ${table}\n WHERE ${condition}\n ORDER BY ${orderColumn}, id\n LIMIT $2::int\n FOR UPDATE SKIP LOCKED\n), deleted AS (\n DELETE FROM ${table} AS delivery USING batch WHERE delivery.id = batch.id RETURNING delivery.event_id\n)\nSELECT event_id FROM deleted`;\n }\n}\n","import type { DeliveryQuery } from '@relaybus/core';\nimport type { PostgresParameter } from './executor.js';\nimport type { PostgresNames } from './names.js';\nimport { isoText } from './sql-fragments.js';\nimport {\n countChanged,\n eventColumns,\n noRunningDelivery,\n type PostgresStatement,\n} from './statement-fragments.js';\n\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** The bound placeholders of the filters of a listing; undefined where the query has none. */\ntype ListFilters = {\n readonly handler: string | undefined;\n readonly eventType: string | undefined;\n readonly eventId: string | undefined;\n readonly status: string | undefined;\n};\n\n/** Binds the filters, then the limit, as parameters in that order. */\nfunction bindListFilters(query: DeliveryQuery): {\n parameters: PostgresParameter[];\n filters: ListFilters;\n limit: string;\n} {\n const parameters: PostgresParameter[] = [];\n const bind = (value: PostgresParameter): string => {\n parameters.push(value);\n return `$${parameters.length}::${typeof value === 'number' ? 'int' : 'text'}`;\n };\n const filters = {\n handler: query.handler === undefined ? undefined : bind(query.handler),\n eventType: query.eventType === undefined ? undefined : bind(query.eventType),\n eventId: query.eventId === undefined ? undefined : bind(query.eventId),\n status: query.status === undefined ? undefined : bind(query.status),\n };\n const limit = bind(query.limit ?? DEFAULT_LIST_LIMIT);\n return { parameters, filters, limit };\n}\n\n/** The conditions of the handler, event type and event id filters on the rows of `alias`. */\nfunction listConditions(filters: ListFilters, alias: string): string[] {\n return [\n ...(filters.handler === undefined ? [] : [`${alias}.handler = ${filters.handler}`]),\n ...(filters.eventType === undefined ? [] : [`event.type = ${filters.eventType}`]),\n ...(filters.eventId === undefined ? [] : [`${alias}.event_id = ${filters.eventId}`]),\n ];\n}\n\n/** Statements for listing, requeueing and statistics. */\nexport class QueryStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /** Parameters: `[deliveryIdsJson, now]`. The dead rows are locked in id order first. */\n get requeue(): string {\n const deliveries = this.#names.deliveries;\n return countChanged(`WITH dead AS MATERIALIZED (\n SELECT delivery.id FROM ${deliveries} AS delivery\n WHERE delivery.id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb))) AND delivery.status = 'dead'\n ORDER BY delivery.id\n FOR NO KEY UPDATE\n)\nUPDATE ${deliveries} AS delivery\nSET status = 'pending', attempts = 0, available_at = $2::timestamptz, updated_at = $2::timestamptz\nFROM dead\nWHERE delivery.id = dead.id AND delivery.status = 'dead'`);\n }\n\n /**\n * Builds the filtered, creation-ordered listing. A delivery is `processing`\n * while its row exists as `pending` and its lane lists its id; its attempt\n * count, lease owner and lease expiry then come from the claim and the lane.\n * Records of the completion history (when kept) are listed as `completed`.\n */\n listDeliveries(query: DeliveryQuery): PostgresStatement {\n const { parameters, filters, limit } = bindListFilters(query);\n const current = this.#currentDeliveries(filters);\n const includeHistory =\n this.#names.completionHistory && (query.status === undefined || query.status === 'completed');\n if (!includeHistory) {\n return {\n sql: `${current}\\nORDER BY delivery.created_at, delivery.id\\nLIMIT ${limit}`,\n parameters,\n };\n }\n const history = this.#completionHistory(filters);\n return {\n sql: `SELECT * FROM (\\n${current}\\nUNION ALL\\n${history}\\n) AS listed\\nORDER BY created_at, delivery_id\\nLIMIT ${limit}`,\n parameters,\n };\n }\n\n /** The deliveries that still exist, with a running one reported as `processing`. */\n #currentDeliveries(filters: ListFilters): string {\n const inFlight = `(delivery.status = 'pending' AND delivery.id = ANY (lane.in_flight))`;\n const whereCurrent = [\n ...listConditions(filters, 'delivery'),\n ...(filters.status === undefined\n ? []\n : [\n `(CASE WHEN ${inFlight} THEN 'processing' ELSE delivery.status END) = ${filters.status}`,\n ]),\n ];\n return `SELECT delivery.id AS delivery_id, delivery.handler,\n CASE WHEN ${inFlight} THEN 'processing' ELSE delivery.status END AS status,\n (delivery.attempts + CASE WHEN ${inFlight} THEN 1 ELSE 0 END)::int AS attempts,\n ${isoText('delivery.available_at')} AS available_at,\n CASE WHEN ${inFlight} THEN lane.lease_owner END AS lease_owner,\n CASE WHEN ${inFlight} THEN ${isoText('lane.lease_expires_at')} END AS lease_expires_at,\n delivery.last_error::text AS last_error,\n ${isoText('delivery.created_at')} AS created_at,\n ${isoText('delivery.updated_at')} AS updated_at,\n ${isoText('delivery.completed_at')} AS completed_at,\n ${eventColumns('event')}\nFROM ${this.#names.deliveries} AS delivery\nJOIN ${this.#names.lanes} AS lane ON lane.lane = delivery.lane\nJOIN ${this.#names.events} AS event ON event.id = delivery.event_id\n${whereCurrent.length === 0 ? '' : `WHERE ${whereCurrent.join(' AND ')}`}`;\n }\n\n /** The completion history records, listed as `completed`. */\n #completionHistory(filters: ListFilters): string {\n const common = (alias: string): string[] => listConditions(filters, alias);\n return `SELECT done.id AS delivery_id, done.handler, 'completed' AS status, done.attempts,\n ${isoText('done.available_at')} AS available_at,\n NULL AS lease_owner,\n NULL AS lease_expires_at,\n NULL AS last_error,\n ${isoText('done.created_at')} AS created_at,\n ${isoText('done.completed_at')} AS updated_at,\n ${isoText('done.completed_at')} AS completed_at,\n ${eventColumns('event')}\nFROM ${this.#names.completions} AS done\nJOIN ${this.#names.events} AS event ON event.id = done.event_id\n${common('done').length === 0 ? '' : `WHERE ${common('done').join(' AND ')}`}`;\n }\n\n /**\n * Counts of rows by stored status (`pending` includes running deliveries;\n * `completed` rows exist only after an upgrade from 0.1.0). Each count is\n * answered from a partial index.\n */\n get countByStatus(): string {\n const deliveries = this.#names.deliveries;\n return ['pending', 'dead', 'completed']\n .map(\n (status) =>\n `SELECT '${status}' AS status, count(*)::text AS count FROM ${deliveries} WHERE status = '${status}'`,\n )\n .join('\\nUNION ALL\\n');\n }\n\n /** Deliveries that are running: listed by a lane and still pending as rows. */\n get countRunning(): string {\n return `SELECT count(*)::text AS count\nFROM ${this.#names.lanes} AS lane\nCROSS JOIN LATERAL unnest(lane.in_flight) AS flying (id)\nJOIN ${this.#names.deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'`;\n }\n\n get countCompletionHistory(): string {\n return `SELECT count(*)::text AS count FROM ${this.#names.completions}`;\n }\n\n /**\n * Oldest instant at which a delivery became claimable: `available_at` of a\n * pending delivery that nobody runs, or the lease expiry of a lane that runs\n * deliveries. Parameters: `[now]`.\n */\n get oldestDue(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `SELECT ${isoText('min(due.due_at)')} AS oldest_due_at FROM (\n SELECT waiting.available_at AS due_at\n FROM ${lanes} AS lane\n CROSS JOIN LATERAL (\n SELECT delivery.available_at FROM ${deliveries} AS delivery\n WHERE delivery.lane = lane.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND delivery.id <> ALL (lane.in_flight)\n ORDER BY delivery.available_at LIMIT 1\n ) AS waiting\n UNION ALL\n SELECT lane.lease_expires_at AS due_at\n FROM ${lanes} AS lane\n WHERE lane.lease_expires_at <= $1::timestamptz AND NOT ${noRunningDelivery(this.#names, 'lane')}\n) AS due`;\n }\n}\n","import type { PostgresNames } from './names.js';\n\n/** Statements of `setup`: the setup lock and the schema check. */\nexport class SetupStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Lock advisory key text for {@link setupLock}. It is derived from the schema\n * name only, so stores with different table prefixes in one schema also\n * serialize their `CREATE SCHEMA IF NOT EXISTS`, which is not race-free.\n */\n get setupLockKey(): string {\n return `relaybus:${this.#names.schema}`;\n }\n\n /**\n * The state of the schema, taking no table lock. Parameters: `[marker]`. Columns: `marked`, whether\n * the lane table carries `marker` as its comment (the schema statements that produce it already\n * ran), and `payload_json`, whether the payload and headers columns of the event table are both\n * `json` (the conversion of the `jsonb` columns of schemas before 0.4.1 ran).\n */\n get schemaCurrent(): string {\n // Reads the catalogs with the statement's snapshot. `to_regclass` and `obj_description` would go\n // through the backend's catalog caches, which keep \"no such table\" until the session processes\n // invalidations; a setup that waited for the setup lock would then miss a schema created meanwhile.\n return `SELECT EXISTS (\n SELECT 1 FROM pg_catalog.pg_class AS c\n JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace\n JOIN pg_catalog.pg_description AS d\n ON d.objoid = c.oid AND d.classoid = 'pg_catalog.pg_class'::regclass AND d.objsubid = 0\n WHERE n.nspname = '${this.#names.schema}' AND c.relname = '${this.#names.lanesTableName}' AND d.description = $1::text\n) AS marked, (\n SELECT count(*) FROM pg_catalog.pg_attribute AS a\n JOIN pg_catalog.pg_class AS c ON c.oid = a.attrelid\n JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace\n WHERE n.nspname = '${this.#names.schema}' AND c.relname = '${this.#names.eventsTableName}'\n AND a.attname IN ('payload', 'headers') AND a.atttypid = 'pg_catalog.json'::pg_catalog.regtype\n AND NOT a.attisdropped\n) = 2 AS payload_json`;\n }\n\n /**\n * Takes the setup lock. Returns a boolean column rather than the `void` of the lock function, which\n * some libraries cannot read (Prisma's raw queries reject a `void` column).\n */\n get setupLock(): string {\n return 'SELECT true AS locked FROM pg_advisory_xact_lock(hashtextextended($1::text, 0))';\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { AppendStatements } from './statements-append.js';\nimport { ClaimStatements } from './statements-claim.js';\nimport { CompletionStatements } from './statements-completion.js';\nimport { LaneStatements } from './statements-lanes.js';\nimport { PurgeStatements } from './statements-purge.js';\nimport { QueryStatements } from './statements-queries.js';\nimport { SetupStatements } from './statements-setup.js';\n\nexport type { PostgresStatement } from './statement-fragments.js';\n\n/**\n * SQL text for every operation of the store. Statements take their data as\n * parameters; only validated identifiers are interpolated. Documents travel\n * as one JSON text parameter expanded server-side with `jsonb_to_recordset`,\n * which keeps the statements identical across drivers and avoids array\n * literal encoding differences. Events go through `json_to_recordset` instead:\n * it hands each payload and headers object to their `json` columns as the\n * exact text the producer serialized, key order included.\n *\n * Leasing is per lane, not per delivery. A lane row carries the owner, an\n * `epoch` (the fencing token: it grows every time the lane changes hands) and\n * `in_flight`, the ids of the deliveries the owner has claimed. A claim\n * therefore writes one lane row for a whole batch and no delivery row; a\n * completion deletes delivery rows and writes no lane row. `in_flight` may\n * list ids that were completed (their rows are gone): a delivery is in flight\n * only while its row exists as `pending` and its id is listed.\n *\n * **Lock order.** Every statement that can wait for a lock takes its locks in this order, and rows of\n * one table in key order, so no two of them can wait for each other in a cycle:\n *\n * 1. the setup advisory lock and the schema DDL ({@link SetupStatements.setupLock}); only while the schema is created or\n * upgraded, never on a current schema (see `PostgresEventStore.setup`);\n * 2. `key_sequences` rows, in key order ({@link AppendStatements.insertFreshEvents});\n * 3. `events` rows, in id order ({@link AppendStatements.lockExistingEvents}, the inserts of a publish, the foreign key\n * checks of new deliveries and completions);\n * 4. `lanes` rows, in lane order: `FOR NO KEY UPDATE` for the owner's held lanes, `FOR KEY SHARE` for\n * completions, `FOR UPDATE SKIP LOCKED` (never waits) for lanes taken from others;\n * 5. `deliveries` rows, only of lanes locked in step 4 (claims, completions, reschedules, takeovers),\n * or inserted new (publish), or `dead` ones in id order ({@link QueryStatements.requeue});\n * 6. `event_completions` rows, in event id order ({@link CompletionStatements.complete}).\n *\n * Publishing never touches `lanes`, and dispatching never touches `key_sequences`. Purging only takes\n * `SKIP LOCKED` row locks and then deletes rows nobody references, so it never waits in a cycle either.\n * A caller's own transaction (a transactional handler that completes and publishes) adds the locks of\n * its own statements in the order it runs them; as documented on `append`, keys appended in opposite\n * orders by two such transactions can still deadlock, and the database then rolls one back.\n */\nexport class PostgresStatements {\n readonly setup: SetupStatements;\n readonly append: AppendStatements;\n readonly lanes: LaneStatements;\n readonly claim: ClaimStatements;\n readonly completion: CompletionStatements;\n readonly queries: QueryStatements;\n readonly purge: PurgeStatements;\n\n constructor(names: PostgresNames) {\n this.setup = new SetupStatements(names);\n this.append = new AppendStatements(names);\n this.lanes = new LaneStatements(names);\n this.claim = new ClaimStatements(names);\n this.completion = new CompletionStatements(names);\n this.queries = new QueryStatements(names);\n this.purge = new PurgeStatements(names);\n }\n}\n","import {\n type AppendEntry,\n type AppendResult,\n type ClaimRequest,\n type ClaimedDelivery,\n type CloseOptions,\n type DeliveryQuery,\n type DeliveryRecord,\n type ErrorInfo,\n type EventStore,\n type EventStoreStatistics,\n type EventStoreTransactionOptions,\n type LeaseReference,\n type PurgeRequest,\n type PurgeResult,\n type RelayBusLogger,\n} from '@relaybus/core';\nimport { HandedOutLedger } from '@relaybus/core/internal';\nimport { Client, Pool, type PoolClient } from 'pg';\nimport type { PostgresExecutor } from './executor.js';\nimport { resolvePostgresNames } from './names.js';\nimport { NotificationListener } from './notification-listener.js';\nimport { PgExecutor } from './pg-executor.js';\nimport { withRootPool } from './root-pool-executor.js';\nimport { PostgresAppend } from './postgres-append.js';\nimport { PostgresClaims } from './postgres-claim.js';\nimport { PostgresCompletion } from './postgres-completion.js';\nimport { OwnedConnections } from './owned-connections.js';\nimport { PostgresMaintenance } from './postgres-maintenance.js';\nimport { PostgresSetup } from './postgres-setup.js';\nimport type { PostgresStoreState } from './postgres-store-state.js';\nimport { resolveStoreSettings, type PostgresEventStoreOptions } from './postgres-store-options.js';\nimport { createPostgresSchemaStatements, version040SchemaMarker } from './schema.js';\nimport { PostgresStatements } from './statements.js';\nimport { inBudgetedTransaction } from './transaction-timeouts.js';\n\nexport type {\n PostgresConnectionOptions,\n PostgresEventStoreOptions,\n PostgresEventStoreSettings,\n PostgresExecutorOptions,\n PostgresPoolOptions,\n PostgresWakeUp,\n} from './postgres-store-options.js';\n\n/**\n * PostgreSQL {@link EventStore} (PostgreSQL 13 or newer).\n *\n * The transaction handle is whatever the chosen driver uses: a `pg`\n * `PoolClient` by default, or a Kysely / Knex / TypeORM / Drizzle / Prisma\n * transaction through the adapters in `@relaybus/postgres/<library>`. Events\n * published with that handle commit and roll back together with the caller's\n * own writes.\n *\n * Guarantees:\n * - **Atomic publish.** Events and deliveries are written in the caller's transaction.\n * - **Per-key order.** Each key has a counter row in the key-sequence table.\n * Publishing locks that row and holds the lock until commit, so two\n * transactions publishing the same key are serialized and sequence order\n * equals commit order. Claiming then hands out only the lowest unfinished\n * sequence of a (handler, key), and all deliveries of a key live in one lane,\n * so one worker at a time sees them.\n * - **Lane leases.** Workers lease lanes (256 hash buckets of the ordering key\n * or event id), not single deliveries. A claim writes one lane row for a\n * whole batch and never writes a delivery row; a completion deletes the\n * delivery rows. Delivery rows are therefore inserted once and deleted once,\n * which leaves no dead index entries from updates on the normal path.\n * - **Fenced state changes.** Complete, reschedule, bury and extend only apply\n * with the epoch of the lane lease that claimed the delivery. A lane taken\n * over by another worker gets a new epoch, which fences everything the\n * previous holder still runs. Completion takes a key-share lock on the lane\n * row, so it cannot interleave with a takeover.\n * - **Attempts survive crashes.** A claim records which deliveries it put in\n * flight in the lane row. If the holder dies, the next holder charges one\n * attempt to each of them, so a poison message still reaches the retry limit.\n * - **App clock.** Every timestamp comes from the `now` the caller passes in,\n * never from the database clock.\n *\n * Completed deliveries are deleted. Pass `completionHistory: true` to keep an\n * append-only record for `listDeliveries({ status: 'completed' })`.\n */\nexport class PostgresEventStore<TTransaction = PoolClient> implements EventStore<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n readonly #appender: PostgresAppend<TTransaction>;\n readonly #claims: PostgresClaims<TTransaction>;\n readonly #completion: PostgresCompletion<TTransaction>;\n readonly #maintenance: PostgresMaintenance<TTransaction>;\n readonly #setup: PostgresSetup<TTransaction>;\n readonly #owned = new OwnedConnections();\n\n constructor(options: PostgresEventStoreOptions<TTransaction>) {\n const { purgeBatchSize, wakeUp, queryOptions } = resolveStoreSettings(options);\n const names = resolvePostgresNames(options);\n const statements = new PostgresStatements(names);\n const schemaStatements = createPostgresSchemaStatements(options);\n const logger = options.logger ?? console;\n const { executor, pool, ownedPool } = connect(options, { logger, owned: this.#owned });\n const state: PostgresStoreState<TTransaction> = {\n executor,\n statements,\n schemaStatements,\n setupLockKey: statements.setup.setupLockKey,\n schemaMarker: version040SchemaMarker(options),\n purgeBatchSize,\n completionHistory: names.completionHistory,\n logger,\n queryOptions,\n notifies: wakeUp === 'notify',\n query: ({ sql, parameters, transaction }) =>\n executor.query(sql, parameters, transaction, queryOptions),\n handedOut: new HandedOutLedger(),\n unreconciled: new Set(),\n generations: new Map(),\n drainingOwners: new Set(),\n ownedPool,\n pool,\n notificationChannel: names.notificationChannel,\n lastNotificationAt: Number.NEGATIVE_INFINITY,\n trailingNotification: undefined,\n closed: false,\n ownTransactions: new Map(),\n };\n this.#state = state;\n this.#appender = new PostgresAppend(state);\n this.#claims = new PostgresClaims(state);\n this.#completion = new PostgresCompletion(state);\n this.#maintenance = new PostgresMaintenance(state);\n this.#setup = new PostgresSetup(state, options);\n }\n\n /**\n * Creates the schema, tables and indexes if they do not exist. Safe to call\n * from many processes at once: a transaction-scoped advisory lock serializes\n * the DDL, so racing `CREATE TABLE IF NOT EXISTS` statements cannot collide.\n * When the lane table already carries the schema marker ({@link version040SchemaMarker})\n * and the payload columns are `json`, nothing runs and no table is locked, so instances\n * that start next to running dispatchers cannot deadlock with their claims.\n * Skip it (`setupStore: false`) when a migration tool applies\n * `createPostgresSchemaSql()` instead.\n */\n async setup(): Promise<void> {\n await this.#setup.run();\n }\n\n /**\n * Runs `work` in a transaction of the executor. With `options.timeoutMs` (from `bus.transaction`)\n * the server holds the transaction to the budget: `statement_timeout`, and for executors with\n * `sessionTimeouts` (`pg`) also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+,\n * `transaction_timeout`, all scoped to the transaction. An executor with `transactionWithBudget`\n * (`PgExecutor`) sets them with `BEGIN`, so the budget costs no round trip; on a pool the store\n * created they are kept per connection and sent only when the connection does not have them yet.\n */\n async transaction<T>(\n work: (transaction: TTransaction) => Promise<T>,\n options?: EventStoreTransactionOptions,\n ): Promise<T> {\n const own = { wake: false };\n const tracked = async (transaction: TTransaction): Promise<T> => {\n this.#state.ownTransactions.set(transaction, own);\n try {\n return await work(transaction);\n } finally {\n this.#state.ownTransactions.delete(transaction);\n }\n };\n const result = await (options === undefined\n ? this.#state.executor.transaction(tracked)\n : inBudgetedTransaction(this.#state, { work: tracked, timeoutMs: options.timeoutMs }));\n if (own.wake) {\n this.#appender.wakeAfterCommit();\n }\n return result;\n }\n\n /**\n * Writes the entries in `transaction`, normally with one statement\n * (`AppendStatements.insertFreshEvents`): keyed events reserve their sequence numbers (locking\n * the key rows in sorted order, so publishers cannot deadlock inside one call), then the new events and\n * their deliveries are inserted, ordered by primary key, and one notification wakes the dispatchers\n * when a delivery is due now. Events that already existed get their missing handlers' deliveries in\n * two more statements. Two transactions that append keys in opposite order across several calls can\n * still deadlock (40P01); the database rolls one back and the caller retries.\n * A duplicate event id still consumes a sequence number; gaps are harmless\n * because only the order of sequences matters.\n */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n append(\n transaction: TTransaction,\n entries: readonly AppendEntry[],\n now: Date,\n ): Promise<AppendResult> {\n return this.#appender.append(transaction, { entries, now });\n }\n\n /**\n * Claims up to `limit` due deliveries, normally with one statement\n * (`LaneStatements.claimLanes`): from the lanes this owner already holds, then from free lanes\n * it takes in the same statement, recording the batch in the lane rows. A claim that would have to take\n * over a lane whose previous holder still runs deliveries under an expired lease continues in a\n * transaction that charges their lost attempts first, taking free lanes a few at a time (4, 8, 16, ...);\n * so does a claim whose statement kept seeing a lane it holds change under it, and one that came up\n * short with more free lanes left than it looked at. The step that fails after\n * the first one has recorded deliveries returns those instead of failing: a recorded delivery nobody\n * received would be held for a whole lease. See `ClaimStatements.claim` for the rules a delivery\n * must satisfy.\n */\n claim(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n return this.#claims.claim(request);\n }\n\n extendLease(lease: LeaseReference, leaseExpiresAt: Date): Promise<boolean> {\n // A database answers with a promise; Promise.resolve returns it as it is.\n return Promise.resolve(this.#completion.extendLease({ lease, leaseExpiresAt }));\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n complete(lease: LeaseReference, now: Date, transaction?: TTransaction): Promise<boolean> {\n return this.#completion.complete(lease, { now, transaction });\n }\n\n completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]> {\n return this.#completion.completeMany(leases, now);\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n reschedule(\n lease: LeaseReference,\n availableAt: Date,\n error: ErrorInfo,\n now: Date,\n ): Promise<boolean> {\n return Promise.resolve(\n this.#completion.changeClaim({\n lease,\n change: { kind: 'reschedule', availableAt, error, now },\n }),\n );\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n bury(lease: LeaseReference, error: ErrorInfo, now: Date): Promise<boolean> {\n return Promise.resolve(\n this.#completion.changeClaim({ lease, change: { kind: 'bury', error, now } }),\n );\n }\n\n /** Returns a leased delivery to pending, due now, without counting the attempt. */\n release(lease: LeaseReference, now: Date): Promise<boolean> {\n return Promise.resolve(\n this.#completion.changeClaim({ lease, change: { kind: 'release', now } }),\n );\n }\n\n /**\n * Calls `listener` soon after a transaction that published deliveries due at once commits, in any\n * process: `append` sends one `pg_notify` per call (merged per transaction, none for delayed\n * deliveries), and this listens with `LISTEN` on a connection of its own, opened with the settings of\n * the store's pool (one connection more than the pool's `max`). A lost connection is replaced after a\n * second. Resolves with `undefined` for a store built on an `executor`, which has no connection of its\n * own to listen on, and with `wakeUp: 'poll'`: polling then finds new deliveries (and the bus still\n * wakes its own dispatcher).\n */\n async watchNewDeliveries(listener: () => void): Promise<(() => Promise<void>) | undefined> {\n if (this.#state.pool === undefined || !this.#state.notifies) {\n return undefined;\n }\n const options = this.#state.pool.options;\n const watcher = new NotificationListener(\n async () => {\n // A client of its own, with the pool's connection settings: the pool keeps all its connections.\n const client = new Client(options);\n this.#owned.track(client);\n await client.connect();\n return client;\n },\n this.#state.notificationChannel,\n listener,\n this.#state.logger,\n );\n await watcher.start();\n return () => watcher.close();\n }\n\n /** Frees the lanes `leaseOwner` holds that run no delivery, so other workers need not wait for the lease to expire. */\n relinquish(leaseOwner: string): Promise<void> {\n return this.#maintenance.relinquish(leaseOwner);\n }\n\n listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n return this.#maintenance.listDeliveries(query);\n }\n\n requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n return this.#maintenance.requeue(deliveryIds, now);\n }\n\n /**\n * Deletes purgeable deliveries in batches of `purgeBatchSize`, one short\n * transaction per batch, then the events those batches left without any\n * delivery. Finally, events created before the earliest given cutoff that\n * have no delivery at all are removed: they are what a publish leaves behind\n * when its last delivery was purged in the same instant, or when no handler\n * was subscribed. Events that a concurrent publish is attaching a delivery\n * to are skipped and kept.\n */\n purge(request: PurgeRequest): Promise<PurgeResult> {\n return this.#maintenance.purge(request);\n }\n\n statistics(now: Date): Promise<EventStoreStatistics> {\n return this.#maintenance.statistics(now);\n }\n\n /**\n * Ends the pool this store created from `connectionString`. Pools and executors you passed in stay\n * open. Once `options.signal` aborts (the shutdown deadline passed), the connections the store opened\n * itself are destroyed: queries still running on them fail at once instead of holding the shutdown.\n */\n async close(options: CloseOptions = {}): Promise<void> {\n this.#state.closed = true;\n this.#state.trailingNotification?.();\n this.#state.trailingNotification = undefined;\n const pool = this.#state.ownedPool;\n this.#state.ownedPool = undefined;\n const { signal } = options;\n const force = (): void => this.#owned.destroyAll();\n if (signal?.aborted === true) {\n force();\n }\n signal?.addEventListener('abort', force, { once: true });\n try {\n await pool?.end();\n } finally {\n signal?.removeEventListener('abort', force);\n }\n }\n}\n\n/**\n * The executor of the store: the one passed in, or a `pg` executor on the given pool or on a pool\n * of its own (`ownedPool`, which the store ends on close).\n */\nfunction connect<TTransaction>(\n options: PostgresEventStoreOptions<TTransaction>,\n { logger, owned }: { readonly logger: RelayBusLogger; readonly owned: OwnedConnections },\n): {\n executor: PostgresExecutor<TTransaction>;\n pool: Pool | undefined;\n ownedPool: Pool | undefined;\n} {\n if (options.executor !== undefined) {\n const { executor, pool } = options;\n return {\n executor:\n pool === undefined ? executor : withRootPool(executor, new PgExecutor(pool, { logger })),\n pool,\n ownedPool: undefined,\n };\n }\n const pool =\n options.pool ??\n new Pool({\n ...options.poolConfig,\n connectionString: options.connectionString,\n Client: owned.clientClass(),\n });\n let ownedPool: Pool | undefined;\n if (options.pool === undefined) {\n const poolLogger = options.logger ?? console;\n pool.on('error', (error) => {\n poolLogger.error(\n `[PostgresEventStore](connect) Idle connection failed, the pool replaces it | error=${error.message}`,\n );\n });\n ownedPool = pool;\n }\n // Without an executor the transaction type is PoolClient, as the default type argument states.\n // A pool of its own keeps the budget per connection; a pooler is what preparedStatements: false is for.\n const executor = new PgExecutor(pool, {\n logger,\n sessionBudget: ownedPool !== undefined && options.preparedStatements !== false,\n }) as unknown as PostgresExecutor<TTransaction>;\n return { executor, pool, ownedPool };\n}\n"]}
1
+ {"version":3,"sources":["../src/transaction-timeouts.ts","../src/transaction-isolation.ts","../src/pg-executor.ts","../src/identifiers.ts","../src/names.ts","../src/sql-fragments.ts","../src/schema.ts","../src/notification-listener.ts","../src/root-pool-executor.ts","../src/serialization-failure.ts","../src/row-mapping.ts","../src/postgres-append.ts","../src/errors.ts","../src/claim-rows.ts","../src/postgres-claim.ts","../src/postgres-completion.ts","../src/owned-connections.ts","../src/postgres-maintenance.ts","../src/postgres-setup.ts","../src/postgres-store-options.ts","../src/statements-append.ts","../src/statement-fragments.ts","../src/statements-claim.ts","../src/statements-completion.ts","../src/statements-candidates.ts","../src/statements-lanes.ts","../src/statements-purge.ts","../src/statements-queries.ts","../src/statements-setup.ts","../src/statements.ts","../src/postgres-event-store.ts"],"names":["ConfigurationError","createHash","connect","schedule","systemClock","LaneLeaseTokenFormat","inserted","CompositeKey","RelayBusError","OwnerSerializedClaims","LeaseSettlement","DeliveryLeaseIdentity","Client","PositiveInteger","HandedOutLedger","TRANSACTION_ISOLATION_LEVELS","executor","pool","Pool"],"mappings":";;;;;;;;;;AAiBO,SAAS,iBAAA,CAAkB,EAAE,KAAA,EAAO,eAAA,EAAiB,OAAM,EAA2B;AAC3F,EAAA,MAAM,QAAQ,KAAA,KAAU,aAAA;AACxB,EAAA,MAAM,gBAAA,GAAmB,CAAA,uCAAA,EAA0C,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA;AAClF,EAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,IAAA,OAAO,gBAAA;AAAA,EACT;AACA,EAAA,OACE,CAAA,EAAG,gBAAgB,CAAA,oDAAA,EAAuD,KAAK,KAAK,KAAK,CAAA,yGAAA,EAE/C,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,KAAA,CAAA;AAE7D;AAGO,IAAM,oBAAA,GACX,8JAAA;AAIK,SAAS,YAAY,SAAA,EAA2B;AACrD,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA,EAAA,CAAA;AAChC;AAOO,SAAS,sBACd,KAAA,EACA;AAAA,EACE,IAAA;AAAA,EACA;AACF,CAAA,EAIY;AACZ,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,EAAA,IAAI,QAAA,CAAS,0BAA0B,MAAA,EAAW;AAChD,IAAA,OAAO,QAAA,CAAS,qBAAA,CAAsB,IAAA,EAAM,SAAS,CAAA;AAAA,EACvD;AACA,EAAA,MAAM,MAAM,iBAAA,CAAkB;AAAA,IAC5B,KAAA,EAAO,IAAA;AAAA,IACP,eAAA,EAAiB,SAAS,eAAA,KAAoB,IAAA;AAAA,IAC9C,KAAA,EAAO;AAAA,GACR,CAAA;AACD,EAAA,OAAO,QAAA,CAAS,WAAA,CAAY,OAAO,WAAA,KAAgB;AACjD,IAAA,MAAM,KAAA,CAAM,KAAA,CAAM,EAAE,GAAA,EAAK,UAAA,EAAY,CAAC,WAAA,CAAY,SAAS,CAAC,CAAA,EAAG,WAAA,EAAa,CAAA;AAC5E,IAAA,OAAO,KAAK,WAAW,CAAA;AAAA,EACzB,CAAC,CAAA;AACH;;;AC/DA,IAAM,kBAAA,GAA0E;AAAA,EAC9E,gBAAA,EAAkB,gBAAA;AAAA,EAClB,iBAAA,EAAmB,iBAAA;AAAA,EACnB,YAAA,EAAc;AAChB,CAAA;AAGO,SAAS,kBAAkB,cAAA,EAAmD;AACnF,EAAA,MAAM,QAAA,GAAW,OAAO,MAAA,CAAO,kBAAA,EAAoB,cAAc,CAAA,GAC7D,kBAAA,CAAmB,cAAc,CAAA,GACjC,MAAA;AACJ,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,MAAM,IAAIA,uBAAA,CAAmB,CAAA,wBAAA,EAA2B,KAAK,SAAA,CAAU,cAAc,CAAC,CAAA,CAAE,CAAA;AAAA,EAC1F;AACA,EAAA,OAAO,QAAA;AACT;AAQO,SAAS,sBACd,KAAA,EACA;AAAA,EACE,IAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAKY;AACZ,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,EAAA,IAAI,QAAA,CAAS,6BAA6B,MAAA,EAAW;AACnD,IAAA,OAAO,SAAS,wBAAA,CAAyB,IAAA,EAAM,EAAE,cAAA,EAAgB,WAAW,CAAA;AAAA,EAC9E;AACA,EAAA,MAAM,QAAA,GAAW,kBAAkB,cAAc,CAAA;AACjD,EAAA,MAAM,SAAS,iBAAA,CAAkB;AAAA,IAC/B,KAAA,EAAO,IAAA;AAAA,IACP,eAAA,EAAiB,SAAS,eAAA,KAAoB,IAAA;AAAA,IAC9C,KAAA,EAAO;AAAA,GACR,CAAA;AACD,EAAA,OAAO,QAAA,CAAS,WAAA,CAAY,OAAO,WAAA,KAAgB;AACjD,IAAA,MAAM,SAAS,KAAA,CAAM,CAAA,gCAAA,EAAmC,QAAQ,CAAA,CAAA,EAAI,IAAI,WAAW,CAAA;AACnF,IAAA,MAAM,KAAA,CAAM,KAAA,CAAM,EAAE,GAAA,EAAK,MAAA,EAAQ,UAAA,EAAY,CAAC,WAAA,CAAY,SAAS,CAAC,CAAA,EAAG,WAAA,EAAa,CAAA;AACpF,IAAA,OAAO,KAAK,WAAW,CAAA;AAAA,EACzB,CAAC,CAAA;AACH;;;ACrCA,IAAM,yCAAyB,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AAyBzD,IAAM,qBAAA,GAAwB,EAAA;AAiBvB,IAAM,aAAN,MAAyD;AAAA,EACrD,KAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA,uBAAa,GAAA,EAAoB;AAAA,EAC1C,UAAA,GAAa,IAAA;AAAA,EACJ,cAAA;AAAA;AAAA,EAEA,cAAA,uBAAqB,OAAA,EAA4B;AAAA,EAE1D,WAAA,CAAY,IAAA,EAAY,OAAA,GAA6B,EAAC,EAAG;AACvD,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,MAAA,IAAU,OAAA;AACjC,IAAA,IAAA,CAAK,cAAA,GAAiB,QAAQ,aAAA,KAAkB,IAAA;AAAA,EAClD;AAAA;AAAA,EAGS,eAAA,GAAkB,IAAA;AAAA,EAE3B,YAAe,IAAA,EAA2D;AAExE,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,MAAa,IAAA;AAAA,MAAM,CAAC,WAC9B,IAAA,CAAK,cAAA,KAAmB,CAAC,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,MAAM,KACtE,EAAE,KAAA,EAAO,UAAU,oBAAoB,CAAA,CAAA,EAAI,cAAc,IAAA,EAAK,GAC9D,EAAE,KAAA,EAAO,OAAA;AAAQ,KACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAAA,CACE,MACA,SAAA,EACY;AACZ,IAAA,OAAO,KAAK,YAAA,CAAa,IAAA,EAAM,KAAK,YAAA,CAAa,SAAA,EAAW,OAAO,CAAC,CAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAA,CACE,IAAA,EACA,EAAE,cAAA,EAAgB,WAAU,EAChB;AACZ,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,MACV,IAAA;AAAA,MACA,KAAK,YAAA,CAAa,SAAA,EAAW,yBAAyB,iBAAA,CAAkB,cAAc,CAAC,CAAA,CAAE;AAAA,KAC3F;AAAA,EACF;AAAA;AAAA,EAGA,YAAA,CAAa,WAAmB,KAAA,EAAyD;AACvF,IAAA,MAAM,KAAA,GAAQ,YAAY,SAAS,CAAA;AACnC,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAChB,iBAAA,CAAkB,EAAE,KAAA,EAAO,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAA,EAAK,eAAA,EAAiB,IAAA,EAAM,KAAA,EAAO,CAAA;AACzE,IAAA,OAAO,CAAC,MAAA,KAAW;AACjB,MAAA,IAAI,CAAC,IAAA,CAAK,mBAAA,EAAoB,EAAG;AAC/B,QAAA,OAAO,EAAE,OAAO,CAAA,EAAG,KAAK,KAAK,QAAA,CAAS,aAAa,CAAC,CAAA,CAAA,EAAG;AAAA,MACzD;AACA,MAAA,OAAO,KAAK,cAAA,CAAe,GAAA,CAAI,MAAM,CAAA,KAAM,KAAA,GACvC,EAAE,KAAA,EAAM,GACR,EAAE,KAAA,EAAO,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,QAAA,CAAS,SAAS,CAAC,CAAA,CAAA,EAAI,cAAc,KAAA,EAAM;AAAA,IACvE,CAAA;AAAA,EACF;AAAA,EAEA,cAAA,CAAe,QAAoB,YAAA,EAA+C;AAChF,IAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,MAAA,IAAA,CAAK,cAAA,CAAe,OAAO,MAAM,CAAA;AAAA,IACnC,CAAA,MAAA,IAAW,iBAAiB,MAAA,EAAW;AACrC,MAAA,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,MAAA,EAAQ,YAAY,CAAA;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA,EAGA,mBAAA,GAA+B;AAC7B,IAAA,OAAO,IAAA,CAAK,kBAAkB,IAAA,CAAK,UAAA;AAAA,EACrC;AAAA,EAEA,MAAM,YAAA,CACJ,IAAA,EACA,KAAA,EACY;AACZ,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,EAAQ;AACxC,IAAA,IAAI,QAAA,GAAW,KAAA;AACf,IAAA,MAAM,OAAA,GAAU,CAAC,OAAA,KAA2B;AAC1C,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA;AAAA,MACF;AACA,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,MAAA,CAAO,cAAA,CAAe,SAAS,cAAc,CAAA;AAC7C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAA,CAAO,QAAQ,IAAI,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,MACjB;AAAA,IACF,CAAA;AAKA,IAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,KAAuB;AAC7C,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA;AAAA,QACX,CAAA,6GAAA,EAAgH,MAAM,OAAO,CAAA;AAAA,OAC/H;AACA,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAA;AACA,IAAA,MAAA,CAAO,EAAA,CAAG,SAAS,cAAc,CAAA;AACjC,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAa,GAAI,MAAM,MAAM,CAAA;AAC5C,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,MAAM,KAAK,CAAA;AACxB,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAM,CAAA;AAChC,MAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,MAAA,CAAO,MAAM,QAAQ,CAAA;AAG/C,MAAA,IAAI,YAAY,QAAA,EAAU;AACxB,QAAA,IAAA,CAAK,cAAA,CAAe,QAAQ,YAAY,CAAA;AAAA,MAC1C;AACA,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,OAAO,CAAA;AAC9C,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAA,CACJ,GAAA,EACA,UAAA,EACA,aACA,OAAA,EACiC;AACjC,IAAA,MAAM,SAAA,GAAY,eAAe,IAAA,CAAK,KAAA;AACtC,IAAA,MAAM,MAAA,GAAS,CAAC,GAAG,UAAU,CAAA;AAC7B,IAAA,IAAI,OAAA,EAAS,OAAA,KAAY,IAAA,IAAQ,CAAC,KAAK,UAAA,EAAY;AACjD,MAAA,OAAA,CAAQ,MAAM,SAAA,CAAU,KAAA,CAAmB,GAAA,EAAK,MAAM,CAAA,EAAG,IAAA;AAAA,IAC3D;AACA,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,MAAM,SAAA,CAAU,KAAA,CAAmB,EAAE,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA,EAAG,IAAA,EAAM,GAAA,EAAK,MAAA,EAAQ,CAAA,EACtF,IAAA;AAAA,IACL,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,sBAAA,CAAuB,GAAA,CAAK,KAAA,CAA6B,IAAc,CAAA,EAAG;AAC7E,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,IAAI,KAAK,UAAA,EAAY;AACnB,QAAA,IAAA,CAAK,UAAA,GAAa,KAAA;AAClB,QAAA,IAAA,CAAK,OAAA,CAAQ,IAAA;AAAA,UACX,CAAA,qLAAA,EAAwL,MAAA,CAAQ,KAAA,CAA6B,IAAI,CAAC,CAAA;AAAA,SACpO;AAAA,MACF;AACA,MAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,OAAA,CAAQ,MAAM,SAAA,CAAU,KAAA,CAAmB,GAAA,EAAK,MAAM,CAAA,EAAG,IAAA;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ,GAAA,EAAqB;AAC3B,IAAA,IAAI,IAAA,GAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC9B,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,IAAA,GAAO,CAAA,SAAA,EAAYC,iBAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,GAAG,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,qBAAqB,CAAC,CAAA,CAAA;AACjG,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,IAC3B;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,mBAAA,CACJ,MAAA,EACA,OAAA,EACe;AACf,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,MAAM,UAAU,CAAA;AAC7B,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA,CAAA,MAAQ;AACN,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd;AAAA,EACF;AACF;AChPA,IAAM,kBAAA,GAAqB,oBAAA;AAC3B,IAAM,yBAAA,GAA4B,EAAA;AAQ3B,SAAS,gBAAA,CAAiB,OAAe,KAAA,EAAqB;AACnE,EAAA,IAAI,CAAC,kBAAA,CAAmB,IAAA,CAAK,KAAK,CAAA,IAAK,KAAA,CAAM,SAAS,yBAAA,EAA2B;AAC/E,IAAA,MAAM,IAAID,uBAAAA;AAAA,MACR,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,KAAK,gBAAgB,MAAA,CAAO,kBAAkB,CAAC,CAAA,gBAAA,EAAmB,yBAAyB,CAAA,WAAA;AAAA,KAC1G;AAAA,EACF;AACF;AAGO,SAAS,gBAAgB,KAAA,EAAuB;AACrD,EAAA,OAAO,IAAI,KAAK,CAAA,CAAA,CAAA;AAClB;;;AC8CO,IAAM,UAAA,GAAa,GAAA;AAE1B,IAAM,cAAA,GAAiB,QAAA;AACvB,IAAM,sBAAA,GAAyB,EAAA;AAC/B,IAAM,oBAAA,GAAuB,WAAA;AAC7B,IAAM,oBAAA,GAAuB,cAAA;AAG7B,SAAS,WAAW,KAAA,EAA6D;AAC/E,EAAA,OAAO;AAAA,IACL,oBAAA,EAAsB,MAAM,iCAAiC,CAAA;AAAA,IAC7D,eAAA,EAAiB,MAAM,yBAAyB,CAAA;AAAA,IAChD,kBAAA,EAAoB,MAAM,4BAA4B,CAAA;AAAA,IACtD,YAAA,EAAc,MAAM,oBAAoB,CAAA;AAAA,IACxC,iBAAA,EAAmB,MAAM,0BAA0B,CAAA;AAAA,IACnD,YAAA,EAAc,MAAM,qBAAqB,CAAA;AAAA,IACzC,mBAAA,EAAqB,MAAM,oCAAoC,CAAA;AAAA,IAC/D,yBAAA,EAA2B,MAAM,iCAAiC,CAAA;AAAA,IAClE,QAAA,EAAU;AAAA,MACR,MAAM,oBAAoB,CAAA;AAAA,MAC1B,MAAM,4BAA4B,CAAA;AAAA,MAClC,MAAM,gCAAgC,CAAA;AAAA,MACtC,MAAM,+BAA+B,CAAA;AAAA,MACrC,MAAM,+BAA+B,CAAA;AAAA,MACrC,MAAM,+BAA+B;AAAA;AACvC,GACF;AACF;AAQO,SAAS,oBAAA,CAAqB,OAAA,GAAiC,EAAC,EAAkB;AACvF,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,cAAA;AACjC,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,oBAAA;AAC3C,EAAA,gBAAA,CAAiB,UAAU,MAAM,CAAA;AACjC,EAAA,IAAI,CAAC,oBAAA,CAAqB,IAAA,CAAK,WAAW,CAAA,EAAG;AAC3C,IAAA,MAAM,IAAIA,uBAAAA;AAAA,MACR,CAAA,aAAA,EAAgB,WAAW,CAAA,aAAA,EAAgB,MAAA,CAAO,oBAAoB,CAAC,CAAA;AAAA,KACzE;AAAA,EACF;AACA,EAAA,MAAM,IAAA,GAAO,CAAC,MAAA,KAA2B;AACvC,IAAA,MAAM,UAAA,GAAa,CAAA,EAAG,WAAW,CAAA,EAAG,MAAM,CAAA,CAAA;AAC1C,IAAA,gBAAA,CAAiB,CAAA,aAAA,EAAgB,WAAW,CAAA,mBAAA,CAAA,EAAuB,UAAU,CAAA;AAC7E,IAAA,OAAO,UAAA;AAAA,EACT,CAAA;AACA,EAAA,MAAM,YAAA,GAAe,gBAAgB,MAAM,CAAA;AAC3C,EAAA,MAAM,KAAA,GAAQ,CAAC,MAAA,KAA2B,CAAA,EAAG,YAAY,IAAI,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAC,CAAC,CAAA,CAAA;AAC1F,EAAA,MAAM,QAAQ,CAAC,MAAA,KAA2B,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAC,CAAA;AACtE,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,YAAA;AAAA,IACA,MAAA,EAAQ,MAAM,QAAQ,CAAA;AAAA,IACtB,eAAA,EAAiB,KAAK,QAAQ,CAAA;AAAA,IAC9B,UAAA,EAAY,MAAM,YAAY,CAAA;AAAA,IAC9B,YAAA,EAAc,MAAM,eAAe,CAAA;AAAA,IACnC,KAAA,EAAO,MAAM,OAAO,CAAA;AAAA,IACpB,cAAA,EAAgB,KAAK,OAAO,CAAA;AAAA,IAC5B,gBAAA,EAAkB,MAAM,mBAAmB,CAAA;AAAA,IAC3C,WAAA,EAAa,MAAM,sBAAsB,CAAA;AAAA,IACzC,iBAAA,EAAmB,QAAQ,iBAAA,IAAqB,KAAA;AAAA,IAChD,qBAAqB,WAAA,CAAY,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,WAAW,CAAA,UAAA,CAAY,CAAA;AAAA,IACrE,OAAA,EAAS,WAAW,KAAK;AAAA,GAC3B;AACF;AAGA,IAAM,mBAAA,GAAsB,EAAA;AAG5B,SAAS,YAAY,QAAA,EAA0B;AAC7C,EAAA,OAAO,SAAS,MAAA,IAAU,sBAAA,GACtB,QAAA,GACA,CAAA,SAAA,EAAYC,kBAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,QAAQ,EAAE,MAAA,CAAO,KAAK,EAAE,KAAA,CAAM,CAAA,EAAG,mBAAmB,CAAC,CAAA,CAAA;AACnG;;;AC1IO,SAAS,QAAQ,UAAA,EAA4B;AAClD,EAAA,OAAO,WAAW,UAAU,CAAA,qDAAA,CAAA;AAC9B;AAQO,SAAS,cAAA,CAAe,eAAuB,iBAAA,EAAmC;AACvF,EAAA,OAAO,8BAA8B,aAAa,CAAA,EAAA,EAAK,iBAAiB,CAAA,QAAA,EAAW,aAAa,CAAC,CAAA,WAAA,CAAA;AACnG;;;ACTA,IAAM,oBAAA,GAAuB,EAAA;AAG7B,IAAM,eAAA,GAAkB,CAAA;AAAA,2CAAA,CAAA;AAExB,IAAM,qBAAA,GAAwB,CAAA;AAAA,6CAAA,CAAA;AAsBvB,SAAS,8BAAA,CAA+B,OAAA,GAAiC,EAAC,EAAa;AAC5F,EAAA,MAAM,KAAA,GAAQ,qBAAqB,OAAO,CAAA;AAC1C,EAAA,MAAM,UAAA,GAAa,qBAAqB,KAAK,CAAA;AAC7C,EAAA,UAAA,CAAW,IAAA,CAAK,oBAAoB,KAAA,CAAM,KAAK,QAAQ,gBAAA,CAAiB,KAAA,EAAO,UAAU,CAAC,CAAA,CAAA,CAAG,CAAA;AAC7F,EAAA,OAAO,UAAA;AACT;AAGA,SAAS,qBAAqB,KAAA,EAAgC;AAC5D,EAAA,MAAM,UAAA,GAAa,CAAC,GAAG,0BAAA,CAA2B,KAAK,CAAA,EAAG,GAAG,2BAAA,CAA4B,KAAK,CAAC,CAAA;AAC/F,EAAA,IAAI,MAAM,iBAAA,EAAmB;AAC3B,IAAA,UAAA,CAAW,IAAA,CAAK,GAAG,2BAAA,CAA4B,KAAK,CAAC,CAAA;AAAA,EACvD;AACA,EAAA,IAAI,KAAA,CAAM,WAAW,QAAA,EAAU;AAC7B,IAAA,UAAA,CAAW,OAAA,CAAQ,CAAA,4BAAA,EAA+B,KAAA,CAAM,YAAY,CAAA,CAAE,CAAA;AAAA,EACxE;AACA,EAAA,OAAO,UAAA;AACT;AAGA,SAAS,2BAA2B,KAAA,EAAgC;AAClE,EAAA,OAAO,CAAC,GAAG,6BAAA,CAA8B,KAAK,GAAG,GAAG,kBAAA,CAAmB,KAAK,CAAC,CAAA;AAC/E;AAGA,SAAS,8BAA8B,KAAA,EAAgC;AACrE,EAAA,OAAO;AAAA,IACL,CAAA,2BAAA,EAA8B,MAAM,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5C,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAAA,IAOb,qBAAqB,KAAK,CAAA;AAAA,IAC1B,8BAA8B,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAA,IAAA,EAAO,MAAM,MAAM,CAAA,iBAAA,CAAA;AAAA,IAC3E,CAAA,2BAAA,EAA8B,MAAM,YAAY,CAAA;AAAA;AAAA;AAAA,CAAA;AAAA,GAIlD;AACF;AAGA,SAAS,mBAAmB,KAAA,EAAgC;AAC1D,EAAA,OAAO;AAAA,IACL,CAAA,2BAAA,EAA8B,MAAM,UAAU,CAAA;AAAA;AAAA,oCAAA,EAEZ,MAAM,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAAA,EAanC,KAAA,CAAM,QAAQ,oBAAoB,CAAA;AAAA,sFAAA,CAAA;AAAA,IAE7C,sBAAsB,KAAK,CAAA;AAAA,IAC3B,CAAA,YAAA,EAAe,MAAM,UAAU,CAAA,2DAAA,CAAA;AAAA,IAC/B,CAAA,YAAA,EAAe,MAAM,UAAU,CAAA,oFAAA,CAAA;AAAA,IAC/B,GAAG,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,GAAA,CAAI,CAAC,KAAA,KAAU,CAAA,qBAAA,EAAwB,KAAA,CAAM,YAAY,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE,CAAA;AAAA,IAC9F,8BAA8B,KAAA,CAAM,OAAA,CAAQ,eAAe,CAAA,IAAA,EAAO,MAAM,UAAU,CAAA,kDAAA,CAAA;AAAA,IAClF,8BAA8B,KAAA,CAAM,OAAA,CAAQ,kBAAkB,CAAA,IAAA,EAAO,MAAM,UAAU,CAAA,4EAAA,CAAA;AAAA,IACrF,8BAA8B,KAAA,CAAM,OAAA,CAAQ,iBAAiB,CAAA,IAAA,EAAO,MAAM,UAAU,CAAA,8CAAA,CAAA;AAAA,IACpF,8BAA8B,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAA,IAAA,EAAO,MAAM,UAAU,CAAA,uCAAA;AAAA,GACjF;AACF;AAGA,SAAS,4BAA4B,KAAA,EAAgC;AACnE,EAAA,OAAO;AAAA,IACL,CAAA,2BAAA,EAA8B,MAAM,KAAK,CAAA;AAAA,wDAAA,EACa,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAA,CAAA;AAAA,IAOhE,CAAA,YAAA,EAAe,MAAM,KAAK,CAAA,+DAAA,CAAA;AAAA,IAC1B,CAAA,2BAAA,EAA8B,MAAM,gBAAgB,CAAA;AAAA,uCAAA,EACf,MAAM,MAAM,CAAA;AAAA;AAAA,CAAA,CAAA;AAAA,IAGjD,8BAA8B,KAAA,CAAM,OAAA,CAAQ,yBAAyB,CAAA,IAAA,EAAO,MAAM,gBAAgB,CAAA,yBAAA,CAAA;AAAA,IAClG,CAAA,YAAA,EAAe,KAAA,CAAM,KAAK,CAAA,kCAAA,EAAqC,aAAa,CAAC,CAAA,yCAAA;AAAA,GAC/E;AACF;AAGA,SAAS,4BAA4B,KAAA,EAAgC;AACnE,EAAA,OAAO;AAAA,IACL,CAAA,2BAAA,EAA8B,MAAM,WAAW,CAAA;AAAA;AAAA,oCAAA,EAEb,MAAM,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAAA,IAO9C,8BAA8B,KAAA,CAAM,OAAA,CAAQ,mBAAmB,CAAA,IAAA,EAAO,MAAM,WAAW,CAAA,mBAAA;AAAA,GACzF;AACF;AAQA,SAAS,qBAAqB,UAAA,EAAuC;AACnE,EAAA,OAAO,mBAAmBA,iBAAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,WAAW,IAAA,CAAK,GAAG,CAAC,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,oBAAoB,CAAC,CAAA,CAAA;AAC1H;AAWA,SAAS,sBAAsB,KAAA,EAAwD;AACrF,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,sBAAA,EAIe,MAAM,UAAU,CAAA;AAAA;AAAA,gBAAA,EAEtB,MAAM,MAAM,CAAA;AAAA,WAAA,EACjB,MAAM,MAAM,CAAA;AAAA;AAAA,2DAAA,EAEoC,MAAM,UAAU,CAAA;AAAA;AAAA;AAAA,gBAAA,EAG3D,MAAM,UAAU,CAAA;AAAA,WAAA,EACrB,MAAM,UAAU,CAAA,YAAA,EAAe,cAAA,CAAe,KAAA,EAAO,UAAU,CAAC,CAAA;AAAA,gBAAA,EAC3D,MAAM,UAAU,CAAA;AAAA,WAAA,EACrB,MAAM,UAAU,CAAA;AAAA,gBAAA,EACX,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA,kBAAA,CAAA;AAKlC;AAWO,SAAS,qBAAqB,KAAA,EAA8B;AACjE,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,kCAAA,EAI2B,MAAM,MAAM,CAAA;AAAA;AAAA;AAAA,gBAAA,EAG9B,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAA,CAAA;AAQ9B;AASO,SAAS,sBAAA,CAAuB,OAAA,GAAiC,EAAC,EAAW;AAClF,EAAA,MAAM,KAAA,GAAQ,qBAAqB,OAAO,CAAA;AAC1C,EAAA,OAAO,gBAAA,CAAiB,KAAA,EAAO,oBAAA,CAAqB,KAAK,CAAC,CAAA;AAC5D;AAGA,SAAS,gBAAA,CAAiB,OAAsB,UAAA,EAAuC;AACrF,EAAA,MAAM,UAAA,GAAa,qBAAqB,KAAK,CAAA;AAC7C,EAAA,OAAO,oBAAA;AAAA,IACL,UAAA,CACG,MAAA,CAAO,CAAC,SAAA,KAAc,cAAc,UAAU,CAAA,CAC9C,GAAA,CAAI,CAAC,SAAA,KAAc,SAAA,CAAU,OAAA,CAAQ,eAAA,EAAiB,qBAAqB,CAAC;AAAA,GACjF;AACF;AAMO,SAAS,uBAAA,CAAwB,OAAA,GAAiC,EAAC,EAAW;AACnF,EAAA,OAAO,GAAG,8BAAA,CAA+B,OAAO,CAAA,CAAE,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,CAAA;AACjE;ACvPA,IAAM,kBAAA,GAAqB,GAAA;AAe3B,SAAS,OAAA,CAAQ,YAAiC,KAAA,EAAgD;AAChG,EAAA,IAAI,MAAA,GAAwB,QAAQ,OAAA,EAAQ;AAC5C,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,CAAC,MAAM,KAAA,EAAO;AAChB,MAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AACd,MAAA,MAAA,GAAS,UAAA,CAAW,GAAA,EAAI,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,IACjD;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAQO,IAAM,uBAAN,MAA2B;AAAA,EACvB,QAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA;AAAA,EAET,KAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA,GAAU,KAAA;AAAA,EAEV,WAAA,CACEC,QAAAA,EACA,OAAA,EACA,QAAA,EACA,MAAA,EACA;AACA,IAAA,IAAA,CAAK,QAAA,GAAWA,QAAAA;AAChB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,QAAA,EAAS;AACvC,IAAA,MAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,KAAA,EAAM;AAC7B,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,UAAA,EAAY,KAAK,CAAA;AACrC,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,GAAA,EAAI;AACV,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,KAAA,GAAQ,GAAA;AACb,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAAwB;AACtC,MAAA,IAAI,CAAC,SAAA,IAAa,KAAA,CAAM,KAAA,EAAO;AAE7B,QAAA;AAAA,MACF;AACA,MAAA,KAAK,GAAA,EAAI;AAET,MAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA;AAAA,QACX,sFAAsF,IAAA,CAAK,QAAQ,CAAA,SAAA,EAAY,KAAA,EAAO,WAAW,kBAAkB,CAAA;AAAA,OACrJ;AACA,MAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,IAC1B,CAAA;AACA,IAAA,UAAA,CAAW,EAAA,CAAG,SAAS,MAAM,CAAA;AAC7B,IAAA,UAAA,CAAW,EAAA,CAAG,KAAA,EAAO,MAAM,MAAA,EAAQ,CAAA;AACnC,IAAA,UAAA,CAAW,EAAA,CAAG,cAAA,EAAgB,MAAM,IAAA,CAAK,WAAW,CAAA;AACpD,IAAA,IAAI;AACF,MAAA,MAAM,UAAA,CAAW,KAAA,CAAM,CAAA,QAAA,EAAW,IAAA,CAAK,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAA,CAAK,oBAAA,CAAqB,GAAA,EAAK,KAAK,CAAA;AAC1C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,GAAA,EAAI;AACV,MAAA;AAAA,IACF;AACA,IAAA,SAAA,GAAY,IAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,oBAAA,CAAqB,GAAA,EAA0B,KAAA,EAA+B;AAClF,IAAA,IAAI,IAAA,CAAK,UAAU,GAAA,EAAK;AACtB,MAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AAAA,IACf;AACA,IAAA,MAAM,GAAA,EAAI;AACV,IAAA,IAAI,KAAK,OAAA,EAAS;AAEhB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AAAA,EAEA,kBAAA,GAA2B;AACzB,IAAA,IAAA,CAAK,eAAA,GAAkBC,kBAASC,gBAAA,EAAa;AAAA,MAC3C,KAAK,MAAM;AACT,QAAA,IAAA,CAAK,eAAA,GAAkB,MAAA;AACvB,QAAA,IAAA,CAAK,OAAM,CAAE,IAAA;AAAA,UACX,MAAM;AACJ,YAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,cAAA,IAAA,CAAK,SAAA,EAAU;AAAA,YACjB;AAAA,UACF,CAAA;AAAA,UACA,CAAC,KAAA,KAAmB;AAClB,YAAA,IAAA,CAAK,OAAA,CAAQ,IAAA;AAAA,cACX,CAAA,qFAAA,EAAwF,IAAA,CAAK,QAAQ,CAAA,SAAA,EAAY,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,aACzK;AACA,YAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,cAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,YAC1B;AAAA,UACF;AAAA,SACF;AAAA,MACF,CAAA;AAAA,MACA,OAAA,EAAS,kBAAA;AAAA,MACT,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,eAAA,IAAkB;AACvB,IAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,IAAA,MAAM,IAAA,IAAO;AAAA,EACf;AACF,CAAA;;;AC1IO,SAAS,YAAA,CACd,UACA,IAAA,EACgC;AAChC,EAAA,OAAO;AAAA,IACL,GAAI,SAAS,eAAA,KAAoB,MAAA,GAC7B,EAAC,GACD,EAAE,eAAA,EAAiB,QAAA,CAAS,eAAA,EAAgB;AAAA,IAChD,WAAA,EAAa,CAAC,IAAA,KAAS,QAAA,CAAS,YAAY,IAAI,CAAA;AAAA,IAChD,GAAI,QAAA,CAAS,qBAAA,KAA0B,MAAA,GACnC,EAAC,GACD;AAAA,MACE,uBAAuB,CAAC,IAAA,EAAM,cAC5B,QAAA,CAAS,qBAAA,CAAuB,MAAM,SAAS;AAAA,KACnD;AAAA,IACJ,GAAI,QAAA,CAAS,wBAAA,KAA6B,MAAA,GACtC,EAAC,GACD;AAAA,MACE,0BAA0B,CAAC,IAAA,EAAM,YAC/B,QAAA,CAAS,wBAAA,CAA0B,MAAM,OAAO;AAAA,KACpD;AAAA,IACJ,GAAI,QAAA,CAAS,sBAAA,KAA2B,MAAA,GACpC,EAAC,GACD,EAAE,sBAAA,EAAwB,CAAC,KAAA,KAAU,QAAA,CAAS,sBAAA,CAAwB,KAAK,CAAA,EAAE;AAAA;AAAA,IAEjF,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,aAAa,OAAA,KACpC,WAAA,KAAgB,SACZ,IAAA,CAAK,KAAA,CAAM,KAAK,UAAA,EAAY,MAAA,EAAW,OAAO,CAAA,GAC9C,QAAA,CAAS,MAAM,GAAA,EAAK,UAAA,EAAY,aAAa,OAAO;AAAA,GAC5D;AACF;;;ACrCA,IAAM,qBAAA,GAAwB,OAAA;AAM9B,IAAM,qBAAA,GAAwB,OAAA;AAE9B,IAAM,cAAA,uBAA2C,GAAA,CAAI;AAAA,EACnD,qBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGD,IAAM,aAAA,GAAgB,CAAA;AAGtB,IAAM,kBAAA,GAAqB,CAAC,OAAA,EAAS,aAAA,EAAe,eAAe,CAAA;AAgB5D,SAAS,8BAAA,CAA+B,KAAA,EAAgB,KAAA,GAAQ,CAAA,EAAY;AACjF,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,QAAQ,aAAA,EAAe;AACxE,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,KAAA,GAAQ,KAAA;AACd,EAAA,IAAI,eAAe,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,IAAK,KAAA,CAAM,iBAAiB,qBAAA,EAAuB;AAClF,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,EAAA,IACE,8BAAA,CAA+B,IAAA,EAAM,KAAA,GAAQ,CAAC,CAAA,IAC9C,+BAA+B,IAAA,EAAM,kBAAA,EAAoB,KAAA,GAAQ,CAAC,CAAA,EAClE;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,kBAAA,CAAmB,IAAA,CAAK,CAAC,GAAA,KAAQ,8BAAA,CAA+B,MAAM,GAAG,CAAA,EAAG,KAAA,GAAQ,CAAC,CAAC,CAAA;AAC/F;ACnCA,SAAS,IAAA,CAAK,KAAkB,MAAA,EAAwB;AACtD,EAAA,OAAO,IAAI,MAAM,CAAA;AACnB;AAEA,SAAS,YAAA,CAAa,KAAkB,MAAA,EAA+B;AACrE,EAAA,OAAO,IAAI,MAAM,CAAA;AACnB;AAEA,SAAS,YAAA,CAAa,KAAkB,MAAA,EAA6B;AACnE,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,GAAA,EAAK,MAAM,CAAA;AACtC,EAAA,OAAO,KAAA,KAAU,IAAA,GAAO,IAAA,GAAO,IAAI,KAAK,KAAK,CAAA;AAC/C;AAGO,SAAS,SAAA,CAAU,KAAkB,MAAA,EAAwB;AAClE,EAAA,OAAO,MAAA,CAAO,GAAA,CAAI,MAAM,CAAC,CAAA;AAC3B;AAEO,SAAS,iBAAiB,GAAA,EAAiC;AAChE,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,IAAA,CAAK,GAAA,EAAK,UAAU,CAAA;AAAA,IACxB,IAAA,EAAM,IAAA,CAAK,GAAA,EAAK,YAAY,CAAA;AAAA,IAC5B,MAAA,EAAQ,IAAA,CAAK,GAAA,EAAK,cAAc,CAAA;AAAA,IAChC,GAAA,EAAK,YAAA,CAAa,GAAA,EAAK,WAAW,CAAA;AAAA,IAClC,SAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,EAAK,eAAe,CAAC,CAAA;AAAA,IAC9C,SAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,EAAK,eAAe,CAAC,CAAA;AAAA,IAC9C,aAAA,EAAe,YAAA,CAAa,GAAA,EAAK,sBAAsB,CAAA;AAAA,IACvD,WAAA,EAAa,YAAA,CAAa,GAAA,EAAK,oBAAoB,CAAA;AAAA,IACnD,YAAY,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,mBAAmB,CAAC;AAAA,GACrD;AACF;AAGA,IAAM,YAAA,GAAe,IAAIC,6BAAA,CAAqB;AAAA,EAC5C,SAAA,EAAW,UAAA;AAAA,EACX,WAAA,EAAa,EAAA;AAAA,EACb,YAAA,EAAc;AAChB,CAAC,CAAA;AAMM,SAAS,gBAAA,CACd,IAAA,EACA,EAAE,KAAA,EAAO,QAAO,EACR;AACR,EAAA,OAAO,aAAa,MAAA,CAAO,IAAA,EAAM,EAAE,KAAA,EAAO,QAAQ,CAAA;AACpD;AAUO,SAAS,gBAAgB,KAAA,EAAsC;AACpE,EAAA,OAAO,YAAA,CAAa,MAAM,KAAK,CAAA;AACjC;AAEO,SAAS,kBAAA,CAAmB,KAAkB,cAAA,EAAuC;AAC1F,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,IAAA,CAAK,GAAA,EAAK,aAAa,CAAA;AAAA,IACnC,UAAA,EAAY,gBAAA,CAAiB,SAAA,CAAU,GAAA,EAAK,MAAM,CAAA,EAAG;AAAA,MACnD,KAAA,EAAO,IAAA,CAAK,GAAA,EAAK,OAAO,CAAA;AAAA,MACxB,MAAA,EAAQ,SAAA,CAAU,GAAA,EAAK,QAAQ;AAAA,KAChC,CAAA;AAAA,IACD,OAAA,EAAS,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AAAA,IAC5B,OAAA,EAAS,SAAA,CAAU,GAAA,EAAK,SAAS,CAAA;AAAA,IACjC,cAAA;AAAA,IACA,KAAA,EAAO,iBAAiB,GAAG;AAAA,GAC7B;AACF;AAEO,SAAS,kBAAkB,GAAA,EAAkC;AAClE,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,GAAA,EAAK,YAAY,CAAA;AAChD,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,IAAA,CAAK,GAAA,EAAK,aAAa,CAAA;AAAA,IAC3B,OAAA,EAAS,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AAAA,IAC5B,MAAA,EAAQ,IAAA,CAAK,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC1B,QAAA,EAAU,SAAA,CAAU,GAAA,EAAK,UAAU,CAAA;AAAA,IACnC,aAAa,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,cAAc,CAAC,CAAA;AAAA,IAC/C,UAAA,EAAY,YAAA,CAAa,GAAA,EAAK,aAAa,CAAA;AAAA,IAC3C,cAAA,EAAgB,YAAA,CAAa,GAAA,EAAK,kBAAkB,CAAA;AAAA,IACpD,WAAW,SAAA,KAAc,IAAA,GAAO,IAAA,GAAQ,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,IAC5D,WAAW,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,YAAY,CAAC,CAAA;AAAA,IAC3C,WAAW,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,YAAY,CAAC,CAAA;AAAA,IAC3C,WAAA,EAAa,YAAA,CAAa,GAAA,EAAK,cAAc,CAAA;AAAA,IAC7C,KAAA,EAAO,iBAAiB,GAAG;AAAA,GAC7B;AACF;AAEO,SAAS,eAAe,IAAA,EAA2C;AACxE,EAAA,OAAO,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAI,eAAe,CAAA;AAC/C;;;AC/FA,IAAM,wBAAA,GAA2B,EAAA;AAoC1B,IAAM,iBAAN,MAAmC;AAAA,EAC/B,MAAA;AAAA,EAET,YAAY,KAAA,EAAyC;AACnD,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,MAAA,CACJ,WAAA,EACA,EAAE,OAAA,EAAS,KAAI,EACQ;AACvB,IAAA,MAAM,IAAA,GAAO,WAAW,OAAO,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC5B,MAAA,OAAO,EAAE,kBAAkB,EAAC,EAAG,mBAAmB,EAAC,EAAG,uBAAuB,CAAA,EAAE;AAAA,IACjF;AACA,IAAA,MAAM,SAAA,GAAY,IAAI,WAAA,EAAY;AAClC,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,CAAQ,IAAA,CAAK,YAAY,EAAE,GAAA,EAAK,aAAa,CAAA;AACjE,IAAA,MAAM,eAAA,GAAkB,iBAAA,CAAkB,IAAA,CAAK,UAAU,CAAA;AACzD,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,kBAAA,CAAmB,WAAA,EAAa;AAAA,MACvD,IAAA;AAAA,MACA,eAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,MAAM,mBAAmB,IAAI,GAAA;AAAA,MAC3B,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,KAAQ,IAAI,UAAU,CAAA,KAAM,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAI,CAAW;AAAA,KAClF;AACA,IAAA,IAAI,qBAAA,GAAwB,SAAA,CAAU,KAAA,CAAM,CAAC,GAAI,YAAY,CAAA;AAC7D,IAAA,MAAM,SAAA,GAAY,KAAK,UAAA,CAAW,MAAA;AAAA,MAChC,CAAC,QAAA,KAAa,CAAC,gBAAA,CAAiB,GAAA,CAAI,SAAS,QAAQ;AAAA,KACvD;AACA,IAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,MAAA,qBAAA,IAAyB,MAAM,IAAA,CAAK,uBAAA,CAAwB,WAAA,EAAa;AAAA,QACvE,IAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA,EAAY,SAAA;AAAA,QACZ,eAAA;AAAA,QACA,gBAAA;AAAA,QACA,SAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,EAAE,GAAG,aAAA,CAAc,IAAA,EAAM,gBAAgB,GAAG,qBAAA,EAAsB;AAAA,EAC3E;AAAA;AAAA,EAGA,MAAM,mBACJ,WAAA,EACA;AAAA,IACE,IAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF,EAMiC;AACjC,IAAA,MAAM,SAAA,GAAY,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AACzC,IAAA,OAAO,IAAA,CAAK,OAAO,KAAA,CAAM;AAAA,MACvB,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,MAAA,CAAO,iBAAA;AAAA,MACnC,UAAA,EAAY;AAAA,QACV,IAAA,CAAK,SAAA;AAAA,UACH,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,OAAO,OAAA,MAAa;AAAA,YACnC,OAAA;AAAA,YACA,GAAG,UAAA,CAAW,KAAA,EAAO,EAAE,UAAU,IAAA,EAAM,QAAA,EAAU,eAAA,CAAgB,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,IAAK,IAAI;AAAA,WACxF,CAAE;AAAA,SACJ;AAAA,QACA,SAAA;AAAA,QACA,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,UAAU,CAAA;AAAA,QAC9B,KAAK,SAAA,CAAU,CAAC,GAAG,SAAS,EAAE,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,MAAO,EAAE,GAAA,EAAK,KAAA,GAAQ,CAAC,CAAA;AAAA,QACrE;AAAA,OACF;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,mBAAA,CACJ,WAAA,EACA,QAAA,EACsB;AACtB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,MACrC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,MAAA,CAAO,kBAAA;AAAA,MACnC,UAAA,EAAY,CAAC,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,EAAE,CAAA,CAAE,IAAA,EAAM,CAAC,CAAA;AAAA,MACjE;AAAA,KACD,CAAA;AACD,IAAA,OAAO,IAAI,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAI,CAAW,CAAC,CAAA;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAA,CACE,UAAA,EACA,EAAE,GAAA,EAAK,aAAY,EACJ;AACf,IAAA,IACE,CAAC,IAAA,CAAK,MAAA,CAAO,QAAA,IACb,CAAC,WAAW,IAAA,CAAK,CAAC,QAAA,KAAa,IAAA,CAAK,MAAM,QAAA,CAAS,YAAY,KAAK,GAAA,CAAI,OAAA,EAAS,CAAA,EACjF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,IAAI,WAAW,CAAA;AACvD,IAAA,IACE,GAAA,KAAQ,UACR,IAAA,CAAK,GAAA,KAAQ,IAAA,CAAK,MAAA,CAAO,qBAAqB,wBAAA,EAC9C;AACA,MAAA,GAAA,CAAI,IAAA,GAAO,IAAA;AACX,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,kBAAA,GAAqB,IAAA,CAAK,GAAA,EAAI;AAC1C,IAAA,OAAO,IAAI,WAAA,EAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAAA,GAAwB;AACtB,IAAA,IAAI,KAAK,MAAA,CAAO,oBAAA,KAAyB,MAAA,IAAa,IAAA,CAAK,OAAO,MAAA,EAAQ;AACxE,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,oBAAA,GAAuBF,iBAAAA,CAASC,gBAAAA,EAAa;AAAA,MACvD,KAAK,MAAM;AACT,QAAA,IAAA,CAAK,OAAO,oBAAA,GAAuB,MAAA;AACnC,QAAA,IAAI,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,MAAA,KAAW,IAAA,EAAM;AACrC,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,MAAA,CAAO,kBAAA,GAAqB,IAAA,CAAK,GAAA,EAAI;AAC1C,QAAA,IAAA,CAAK,OACF,KAAA,CAAM,EAAE,GAAA,EAAK,IAAA,CAAK,OAAO,UAAA,CAAW,MAAA,CAAO,MAAA,EAAQ,UAAA,EAAY,EAAC,EAAG,CAAA,CACnE,KAAA,CAAM,CAAC,KAAA,KAAmB;AACzB,UAAA,IAAA,CAAK,OAAO,MAAA,CAAO,KAAA;AAAA,YACjB,oHAAoH,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,WAC5K;AAAA,QACF,CAAC,CAAA;AAAA,MACL,CAAA;AAAA,MACA,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,OAAO,kBAAA,GAAqB,wBAAA,GAA2B,IAAA,CAAK,GAAA,EAAK;AAAA,KAC5F,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,uBAAA,CACJ,WAAA,EACA,KAAA,EACiB;AACjB,IAAA,MAAM,EAAE,MAAM,KAAA,EAAO,UAAA,EAAY,iBAAiB,gBAAA,EAAkB,SAAA,EAAW,QAAO,GAAI,KAAA;AAC1F,IAAA,MAAM,YAAY,IAAI,GAAA;AAAA,MACpB,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,CAAI,IAAI,CAAA,EAAa,GAAA,CAAI,UAAU,CAAkB,CAAC;AAAA,KAC5E;AACA,IAAA,MAAM,aAAuB,EAAC;AAC9B,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,MAAA,CACjB,MAAA,CAAO,CAAC,KAAA,KAAU,CAAC,gBAAA,CAAiB,GAAA,CAAI,KAAA,CAAM,EAAE,CAAC,CAAA,CACjD,GAAA;AAAA,MAAI,CAAC,KAAA,KACJ,UAAA,CAAW,KAAA,EAAO;AAAA,QAChB,QAAA,EAAU,SAAA,CAAU,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA;AAAA,QAChC,UAAU,eAAA,CAAgB,GAAA,CAAI,KAAA,CAAM,EAAE,KAAK;AAAC,OAC7C;AAAA,KACH;AACF,IAAA,OAAO,QAAA,CAAS,SAAS,CAAA,EAAG;AAC1B,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,mBAAA,CAAoB,aAAa,QAAQ,CAAA;AACnE,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,MAAA,CAAO,CAAC,GAAA,KAAQ,CAAC,MAAA,CAAO,GAAA,CAAI,GAAA,CAAI,EAAE,CAAC,CAAA;AACzD,MAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,QAAA,MAAME,SAAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,UACvC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,MAAA,CAAO,YAAA;AAAA,UACnC,YAAY,CAAC,IAAA,CAAK,SAAA,CAAU,IAAI,GAAG,SAAS,CAAA;AAAA,UAC5C;AAAA,SACD,CAAA;AACD,QAAA,KAAA,MAAW,OAAOA,SAAAA,EAAU;AAC1B,UAAA,gBAAA,CAAiB,GAAA,CAAI,GAAA,CAAI,IAAI,CAAW,CAAA;AACxC,UAAA,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,IAAI,CAAW,CAAA;AAAA,QACrC;AAAA,MACF;AACA,MAAA,QAAA,GAAW,IAAA,CAAK,OAAO,CAAC,GAAA,KAAQ,CAAC,gBAAA,CAAiB,GAAA,CAAI,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IAC/D;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,MACvC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,MAAA,CAAO,gBAAA;AAAA,MACnC,UAAA,EAAY,CAAC,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,EAAG,SAAA,EAAW,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,EAAG,MAAM,CAAA;AAAA,MACtF;AAAA,KACD,CAAA;AACD,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB;AACF,CAAA;AAUA,SAAS,WAAW,OAAA,EAA6C;AAC/D,EAAA,MAAM,SAA0B,EAAC;AACjC,EAAA,MAAM,aAA4B,EAAC;AACnC,EAAA,MAAM,WAA0D,EAAC;AACjE,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAY;AACrC,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AACvC,EAAA,KAAA,MAAW,EAAE,KAAA,EAAO,UAAA,EAAY,aAAA,MAAmB,OAAA,EAAS;AAC1D,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA;AAC1C,IAAA,YAAA,CAAa,GAAA,CAAI,MAAM,EAAE,CAAA;AACzB,IAAA,QAAA,CAAS,KAAK,EAAE,OAAA,EAAS,KAAA,CAAM,EAAA,EAAI,UAAU,CAAA;AAC7C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AACA,IAAA,KAAA,MAAW,YAAY,aAAA,EAAe;AACpC,MAAA,MAAM,WAAWC,qBAAA,CAAa,EAAA,CAAG,KAAA,CAAM,EAAA,EAAI,SAAS,OAAO,CAAA;AAC3D,MAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,QAAQ,CAAA,EAAG;AACjC,QAAA,cAAA,CAAe,IAAI,QAAQ,CAAA;AAC3B,QAAA,UAAA,CAAW,IAAA,CAAK;AAAA,UACd,IAAI,QAAA,CAAS,EAAA;AAAA,UACb,UAAU,KAAA,CAAM,EAAA;AAAA,UAChB,SAAS,QAAA,CAAS,OAAA;AAAA,UAClB,YAAA,EAAc,QAAA,CAAS,WAAA,CAAY,WAAA;AAAY,SAChD,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAS;AACxC;AAEA,SAAS,WACP,KAAA,EACA;AAAA,EACE,QAAA;AAAA,EACA;AACF,CAAA,EACU;AACV,EAAA,OAAO;AAAA,IACL,IAAI,KAAA,CAAM,EAAA;AAAA,IACV,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,QAAA;AAAA,IACA,SAAS,KAAA,CAAM,OAAA;AAAA,IACf,SAAS,KAAA,CAAM,OAAA;AAAA,IACf,gBAAgB,KAAA,CAAM,aAAA;AAAA,IACtB,cAAc,KAAA,CAAM,WAAA;AAAA,IACpB,WAAA,EAAa,KAAA,CAAM,UAAA,CAAW,WAAA,EAAY;AAAA,IAC1C;AAAA,GACF;AACF;AAGA,SAAS,kBAAkB,UAAA,EAA2D;AACpF,EAAA,MAAM,eAAA,uBAAsB,GAAA,EAAsB;AAClD,EAAA,KAAA,MAAW,YAAY,UAAA,EAAY;AACjC,IAAA,eAAA,CAAgB,GAAA,CAAI,SAAS,QAAA,EAAU;AAAA,MACrC,GAAI,eAAA,CAAgB,GAAA,CAAI,QAAA,CAAS,QAAQ,KAAK,EAAC;AAAA,MAC/C,QAAA,CAAS;AAAA,KACV,CAAA;AAAA,EACH;AACA,EAAA,OAAO,eAAA;AACT;AAGA,SAAS,YAAY,MAAA,EAAmD;AACtE,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAoB;AAC1C,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,KAAA,CAAM,QAAQ,IAAA,EAAM;AACtB,MAAA,SAAA,CAAU,GAAA,CAAI,MAAM,GAAA,EAAA,CAAM,SAAA,CAAU,IAAI,KAAA,CAAM,GAAG,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA;AAAA,IAC9D;AAAA,EACF;AACA,EAAA,OAAO,SAAA;AACT;AAGA,SAAS,aAAA,CACP,MACA,gBAAA,EAC6D;AAC7D,EAAA,MAAM,mBAA6B,EAAC;AACpC,EAAA,MAAM,oBAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,QAAA,EAAS,IAAK,KAAK,QAAA,EAAU;AACjD,IAAA,CAAC,CAAC,QAAA,IAAY,gBAAA,CAAiB,IAAI,OAAO,CAAA,GAAI,mBAAmB,iBAAA,EAAmB,IAAA;AAAA,MAClF;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,EAAE,kBAAkB,iBAAA,EAAkB;AAC/C;ACtVO,IAAM,oBAAA,GAAN,cAAmCC,kBAAA,CAAc;AAAA,EAC7C,IAAA,GAAO,sBAAA;AAAA,EACE,IAAA,GAAe,oCAAA;AACnC;ACJO,SAAS,eAAe,GAAA,EAA2B;AACxD,EAAA,OACE,GAAA,CAAI,kBAAkB,CAAA,KAAM,IAAA,IAC5B,GAAA,CAAI,uBAAuB,CAAA,KAAM,IAAA,IACjC,GAAA,CAAI,OAAO,CAAA,KAAM,IAAA;AAErB;AAMO,SAAS,YAAA,CAAa,QAAgC,KAAA,EAA8B;AACzF,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,EAAA,MAAM,OAAO,CAAC,GAAG,MAAM,CAAA,CACpB,KAAK,CAAC,IAAA,EAAM,KAAA,KAAU,eAAA,CAAgB,MAAM,KAAK,CAAC,CAAA,CAClD,MAAA,CAAO,CAAC,GAAA,KAAQ;AACf,IAAA,IAAI,GAAA,CAAI,cAAc,CAAA,KAAM,IAAA,EAAM;AAChC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,KAAA,GAAQD,sBAAa,EAAA,CAAG,GAAA,CAAI,SAAS,CAAA,EAAa,GAAA,CAAI,cAAc,CAAW,CAAA;AACrF,IAAA,OAAO,CAAC,SAAS,GAAA,CAAI,KAAK,KAAK,OAAA,CAAQ,QAAA,CAAS,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EAC5D,CAAC,CAAA;AACH,EAAA,IAAA,CAAK,KAAK,UAAU,CAAA;AACpB,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA;AAC5B;AAEA,SAAS,eAAA,CAAgB,MAAmB,KAAA,EAA4B;AACtE,EAAA,MAAM,KAAA,GAAQ,WAAW,IAAI,CAAA;AAC7B,EAAA,MAAM,MAAA,GAAS,WAAW,KAAK,CAAA;AAC/B,EAAA,OAAO,OAAO,KAAA,GAAQ,MAAM,CAAA,GAAI,MAAA,CAAO,QAAQ,MAAM,CAAA;AACvD;AAGA,SAAS,WAAW,GAAA,EAA0B;AAC5C,EAAA,OAAO,MAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,IAAuB,CAAC,CAAA;AACvD;AAEO,SAAS,UAAA,CAAW,MAAmB,KAAA,EAA4B;AACxE,EAAA,OACE,WAAA,CAAY,IAAA,CAAK,QAAQ,CAAA,EAAa,MAAM,QAAQ,CAAW,CAAA,IAC/D,WAAA,CAAY,IAAA,CAAK,aAAa,CAAA,EAAa,KAAA,CAAM,aAAa,CAAW,CAAA;AAE7E;AAEA,SAAS,WAAA,CAAY,MAAc,KAAA,EAAuB;AACxD,EAAA,OAAO,OAAO,IAAA,GAAO,KAAK,CAAA,GAAI,MAAA,CAAO,OAAO,KAAK,CAAA;AACnD;;;AC5CA,IAAM,uBAAA,GAA0B,CAAA;AAGhC,IAAM,4BAAA,GAA+B,CAAA;AAO9B,IAAM,cAAA,GAAN,cAA2CE,8BAAA,CAAsB;AAAA,EAC7D,MAAA;AAAA,EAET,YAAY,KAAA,EAAyC;AACnD,IAAA,KAAA,EAAM;AACN,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA,EAEA,MAAgB,YAAY,OAAA,EAAmD;AAC7E,IAAA,MAAM,IAAA,CAAK,iBAAA,CAAkB,OAAA,CAAQ,UAAU,CAAA;AAG/C,IAAA,MAAM,YAAY,IAAA,CAAK,MAAA,CAAO,cAAA,CAAe,GAAA,CAAI,QAAQ,UAAU,CAAA;AACnE,IAAA,IAAI,IAAA,GAAO,MAAM,IAAA,CAAK,WAAA,CAAY,SAAS,SAAS,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA,CAAG,gBAAgB,CAAW,CAAa,CAAA;AACtF,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,QAAQ,UAAU,CAAA;AAC1D,IAAA,IAAI,SAAA,IAAa,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,KAAA,IAAS,KAAK,CAAC,CAAA,CAAG,OAAO,CAAA,KAAM,IAAA,EAAM;AAC7E,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,wBAAA,CAAyB,SAAS,OAAO,CAAA;AACrE,MAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,QAAA,OAAO,KAAK,kBAAA,CAAmB,OAAA,EAAS,EAAE,OAAA,EAAS,WAAW,CAAA;AAAA,MAChE;AACA,MAAA,IAAA,GAAO,QAAA;AAAA,IACT;AACA,IAAA,IAAI,OAAA,CAAQ,SAAS,OAAA,CAAQ,KAAA,IAAS,eAAe,IAAA,CAAK,CAAC,CAAE,CAAA,EAAG;AAC9D,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,OAAA,EAAS,OAAO,CAAA;AAAA,IAC7C;AACA,IAAA,OAAO,KAAK,kBAAA,CAAmB,OAAA,EAAS,EAAE,OAAA,EAAS,WAAW,CAAA;AAAA,EAChE;AAAA;AAAA,EAGA,MAAM,kBAAkB,KAAA,EAA8B;AACpD,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAA,CAAI,KAAK,CAAA,IAAK,CAAE,MAAM,IAAA,CAAK,UAAA,CAAW,KAAK,CAAA,EAAI;AAE1E,MAAA,MAAM,IAAI,oBAAA;AAAA,QACR,0GAA0G,KAAK,CAAA;AAAA,OACjH;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,OAAA,EAAuB,SAAA,EAAqD;AAC5F,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,oBAAA;AAAA,QAChB,OAAA;AAAA,QACA,SAAA,GACI,KAAK,MAAA,CAAO,UAAA,CAAW,MAAM,cAAA,GAC7B,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM;AAAA,OACnC;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAA,CAAK,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA;AACxC,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,wBAAA,CACJ,OAAA,EACA,OAAA,EAC6C;AAC7C,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,MAAM,IAAA,CAAK,oBAAA;AAAA,QAChB,EAAE,GAAG,OAAA,EAAS,OAAO,OAAA,CAAQ,KAAA,GAAQ,QAAQ,MAAA,EAAO;AAAA,QACpD,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM;AAAA,OAC/B;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAA,CAAK,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA;AACxC,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,QAAA,IAAA,CAAK,MAAA,CAAO,cAAA,CAAe,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AACpD,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,IAAA,CAAK,OAAO,MAAA,CAAO,KAAA;AAAA,QACjB,CAAA,8HAAA,EAAiI,OAAA,CAAQ,MAAM,CAAA,SAAA,EAAY,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,OACnN;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAA,CAAQ,KAAK,GAAG,IAAA,CAAK,aAAa,IAAA,EAAM,OAAA,CAAQ,UAAU,CAAC,CAAA;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,eAAA,CAAgB,OAAA,EAAuB,OAAA,EAAuC;AAClF,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,MAAM,IAAA,CAAK,UAAA,CAAW,OAAA,EAAS,QAAQ,MAAM,CAAA;AAC1D,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,OAAA,CAAQ,UAAU,CAAA;AACtC,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,IAAI,CAAA;AAAA,IACtB,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAA,CAAK,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA;AACxC,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,IAAA,CAAK,OAAO,MAAA,CAAO,KAAA;AAAA,QACjB,CAAA,8GAAA,EAAiH,OAAA,CAAQ,MAAM,CAAA,SAAA,EAAY,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,OACnM;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,YAAA,CAAa,MAA8B,UAAA,EAAmC;AAC5E,IAAA,MAAM,OAAA,GAAU,KAAK,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,aAAa,MAAM,IAAI,CAAA;AAChE,IAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,CAAC,GAAI,EAAE,UAAA,EAAY,SAAS,CAAA;AACtD,IAAA,IAAA,CAAK,QAAA,CAAS,SAAS,UAAU,CAAA;AACjC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,mBACE,OAAA,EACA;AAAA,IACE,OAAA;AAAA,IACA;AAAA,GACF,EACmB;AACnB,IAAA,IACE,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,KAAA,IAC1B,QAAQ,KAAA,CAAM,CAAC,GAAA,KAAQ,SAAA,CAAU,IAAI,SAAA,CAAU,GAAA,EAAK,MAAM,CAAC,CAAC,CAAA,EAC5D;AACA,MAAA,IAAA,CAAK,MAAA,CAAO,cAAA,CAAe,GAAA,CAAI,OAAA,CAAQ,UAAU,CAAA;AAAA,IACnD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAA,CAAO,cAAA,CAAe,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AAAA,IACtD;AAEA,IAAA,OAAA,CAAQ,KAAK,UAAU,CAAA;AACvB,IAAA,OAAO,OAAA,CAAQ,IAAI,CAAC,GAAA,KAAQ,mBAAmB,GAAA,EAAK,OAAA,CAAQ,cAAc,CAAC,CAAA;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBAAA,CACJ,OAAA,EACA,SAAA,EACiC;AACjC,IAAA,MAAM,UAAA,GAAa;AAAA,MACjB,OAAA,CAAQ,IAAI,WAAA,EAAY;AAAA,MACxB,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,QAAQ,CAAA;AAAA,MAC/B,OAAA,CAAQ,KAAA;AAAA,MACR,OAAA,CAAQ,UAAA;AAAA,MACR,OAAA,CAAQ,eAAe,WAAA,EAAY;AAAA,MACnC,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,UAAU,EAAE,QAAA;AAAS,KAChD;AACA,IAAA,IAAI,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,EAAE,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,CAAA;AACjE,IAAA,KAAA,IACM,OAAA,GAAU,CAAA,EACd,OAAA,GAAU,4BAAA,IAAgC,IAAA,CAAK,CAAC,CAAA,CAAG,OAAO,CAAA,KAAM,IAAA,EAChE,OAAA,IAAW,CAAA,EACX;AACA,MAAA,IAAA,GAAO,MAAM,KAAK,MAAA,CAAO,KAAA,CAAM,EAAE,GAAA,EAAK,SAAA,EAAW,YAAY,CAAA;AAAA,IAC/D;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAA,CAAW,OAAA,EAAuB,cAAA,EAAgD;AACtF,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,WAAA,EAAY;AACpC,IAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,cAAA,CAAe,WAAA,EAAY;AAC1D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,QAAQ,CAAA;AAEhD,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,UAAU,EAAE,QAAA,EAAS;AACjE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,WAAA,CAAY,OAAO,WAAA,KAAgB;AAC7D,MAAA,MAAM,UAAyB,EAAC;AAChC,MAAA,MAAM,SAAA,GAAY,MAAc,OAAA,CAAQ,KAAA,GAAQ,iBAAiB,OAAA,CAAQ,MAAA;AACzE,MAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AACnC,MAAA,KAAA,IAAS,SAAA,GAAY,uBAAA,EAAyB,SAAA,EAAU,GAAI,CAAA,IAAI;AAC9D,QAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,UACpC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,aAAA;AAAA,UAClC,UAAA,EAAY,CAAC,GAAA,EAAK,QAAA,EAAU,WAAW,OAAA,CAAQ,UAAA,EAAY,gBAAgB,UAAU,CAAA;AAAA,UACrF;AAAA,SACD,CAAA;AACD,QAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,UAAA;AAAA,QACF;AACA,QAAA,MAAM,KAAA,GAAQ,MAAM,GAAA,CAAI,CAAC,QAAQ,SAAA,CAAU,GAAA,EAAK,MAAM,CAAC,CAAA;AACvD,QAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,UAAA,UAAA,CAAW,IAAI,IAAI,CAAA;AAAA,QACrB;AACA,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,GAAI,MAAM,IAAA,CAAK,eAAA;AAAA,YACb,CAAC,KAAK,QAAA,EAAU,SAAA,IAAa,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,YAClD;AAAA;AACF,SACF;AACA,QAAA,SAAA,IAAa,CAAA;AAAA,MACf;AACA,MAAA,MAAM,IAAA,CAAK,aAAa,OAAA,EAAS,EAAE,OAAO,UAAA,EAAY,OAAA,EAAS,aAAa,CAAA;AAC5E,MAAA,OAAO,OAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAA,CAAY,KAAA,EAAe,OAAA,GAAU,KAAA,EAAe;AAClD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA,IAAK,MAAA,CAAO,IAAA,CAAK,GAAA,EAAK,CAAA;AACvE,IAAA,MAAM,IAAA,GAAO,OAAA,GACT,OAAA,GAAU,eAAA,GAAkB,OAAO,IAAA,CAAK,GAAA,EAAK,CAAA,GAC3C,UAAU,eAAA,GACV,MAAA,CAAO,IAAA,CAAK,GAAA,EAAK,CAAA,GACnB,OAAA;AACJ,IAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,KAAA,EAAO,IAAI,CAAA;AACvC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,QAAA,CAAS,MAA8B,UAAA,EAA0B;AAC/D,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,QAAQ,kBAAA,CAAmB,GAAA,kBAAK,IAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACjD,MAAA,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,QAAA,CAAS,KAAA,EAAO;AAAA,QACpC,KAAA,EAAO,UAAA;AAAA,QACP,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,GAAG,eAAA,CAAgB,KAAA,CAAM,UAAU;AAAA,OACpC,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBACE,GAAA,EACA;AAAA,IACE,UAAA;AAAA,IACA;AAAA,GACF,EACM;AAEN,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,IAAA,CAAK,MAAM,GAAA,CAAI,gBAAgB,CAAW,CAAa,CAAA;AACjF,IAAA,MAAM,OAAA,uBAAc,GAAA,CAAI;AAAA,MACtB,GAAI,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,aAAa,CAAW,CAAA;AAAA,MAC3C,GAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,CAAW;AAAA,KAC3D,CAAA;AACD,IAAA,IAAA,CAAK,OAAO,SAAA,CAAU,WAAA;AAAA,MACpB,CAAC,KAAA,KACC,KAAA,CAAM,KAAA,KAAU,cAAc,SAAA,CAAU,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,IAAK,CAAC,OAAA,CAAQ,GAAA,CAAI,MAAM,UAAU;AAAA,KAC5F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,UAAA,EAAsC;AAErD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,WAAA,CAAY,UAAA,EAAY,IAAI,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,KAAK,MAAA,CAAO,SAAA,CAC3B,UAAU,UAAU,CAAA,CACpB,IAAI,CAAC,EAAE,YAAY,IAAA,EAAM,KAAA,EAAO,QAAO,MAAO,EAAE,IAAI,UAAA,EAAY,IAAA,EAAM,KAAA,EAAO,MAAA,EAAO,CAAE,CAAA;AACzF,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,OAAO,KAAA,CAAM;AAAA,QACtB,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,eAAA;AAAA,QAClC,UAAA,EAAY,CAAC,UAAA,EAAY,IAAA,CAAK,UAAU,SAAS,CAAA,EAAG,UAAA,CAAW,QAAA,EAAU;AAAA,OAC1E,CAAA;AACD,MAAA,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,MAAA,CAAO,UAAU,CAAA;AAC1C,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAA,CAAI,UAAU,CAAA;AACvC,MAAA,IAAA,CAAK,OAAO,MAAA,CAAO,KAAA;AAAA,QACjB,CAAA,kHAAA,EAAqH,UAAU,CAAA,SAAA,EAAY,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,OACnM;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,eAAA,CACJ,UAAA,EACA,WAAA,EACwB;AACxB,IAAA,MAAM,KAAA,GAAQ,WAAW,CAAC,CAAA;AAC1B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,MACvC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,KAAA;AAAA,MAClC,UAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,MAAM,MAAA,GAAS,SAAS,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,aAAa,MAAM,IAAI,CAAA;AACnE,IAAA,IAAI,MAAA,CAAO,SAAS,KAAA,IAAS,QAAA,CAAS,CAAC,CAAA,CAAG,kBAAkB,MAAM,IAAA,EAAM;AACtE,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,QACvC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,sBAAA;AAAA,QAClC,UAAA;AAAA,QACA;AAAA,OACD,CAAA;AAGD,MAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,aAAa,CAAC,CAAC,CAAA;AACjE,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,GAAG,QAAA,CAAS,MAAA;AAAA,UACV,CAAC,GAAA,KAAQ,GAAA,CAAI,aAAa,CAAA,KAAM,IAAA,IAAQ,CAAC,SAAA,CAAU,GAAA,CAAI,GAAA,CAAI,aAAa,CAAC;AAAA;AAC3E,OACF;AAGA,MAAA,OAAO,YAAA,CAAa,QAAQ,KAAK,CAAA;AAAA,IACnC;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,aACJ,OAAA,EACA;AAAA,IACE,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,EAKe;AACf,IAAA,MAAM,SAAA,uBAAgB,GAAA,EAAsB;AAC5C,IAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,MAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,EAAK,MAAM,CAAA;AAClC,MAAA,SAAA,CAAU,GAAA,CAAI,IAAA,EAAM,CAAC,GAAI,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,IAAK,EAAC,EAAI,GAAA,CAAI,aAAa,CAAW,CAAC,CAAA;AAAA,IACpF;AACA,IAAA,MAAM,SAAA,GAAY,CAAC,GAAG,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,SAAA,CAAU,GAAA,CAAI,IAAI,CAAC,CAAA;AAClE,IAAA,IAAI,SAAA,CAAU,IAAA,KAAS,CAAA,IAAK,SAAA,CAAU,WAAW,CAAA,EAAG;AAClD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,CAAK,OAAO,KAAA,CAAM;AAAA,MACtB,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,WAAA;AAAA,MAClC,UAAA,EAAY;AAAA,QACV,KAAK,SAAA,CAAU,CAAC,GAAG,SAAS,EAAE,GAAA,CAAI,CAAC,CAAC,IAAA,EAAM,GAAG,CAAA,MAAO,EAAE,IAAA,EAAM,GAAA,GAAM,CAAC,CAAA;AAAA,QACnE,IAAA,CAAK,UAAU,SAAS,CAAA;AAAA,QACxB,OAAA,CAAQ,UAAA;AAAA,QACR,OAAA,CAAQ,eAAe,WAAA;AAAY,OACrC;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAA;AAGA,IAAM,eAAA,GAAkB,EAAA;AC9VjB,IAAM,kBAAA,GAAN,cAA+CC,wBAAA,CAA2B;AAAA,EACtE,MAAA;AAAA,EAET,YAAY,KAAA,EAAyC;AACnD,IAAA,KAAA,EAAM;AACN,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,QAAA,CACJ,KAAA,EACA,EAAE,GAAA,EAAK,aAAY,EACD;AAClB,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,eAAA,CAAgB,CAAC,KAAK,CAAA,EAAG,EAAE,GAAA,EAAK,WAAA,EAAa,CAAA,EAAG,CAAC,CAAA;AAAA,EACtE;AAAA;AAAA,EAGA,YAAA,CAAa,QAAmC,GAAA,EAA+B;AAC7E,IAAA,OAAO,KAAK,eAAA,CAAgB,MAAA,EAAQ,EAAE,GAAA,EAAK,WAAA,EAAa,QAAW,CAAA;AAAA,EACrE;AAAA;AAAA,EAGU,SAAS,KAAA,EAA8C;AAC/D,IAAA,OAAO,eAAA,CAAgB,MAAM,UAAU,CAAA;AAAA,EACzC;AAAA,EAEU,cAAA,CACR,IAAA,EACA,EAAE,KAAA,EAAO,gBAAe,EACN;AAClB,IAAA,OAAO,KAAK,QAAA,CAAS,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,WAAW,WAAA,EAAa;AAAA,MAClE,GAAG,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AAAA,MACtB,eAAe,WAAA;AAAY,KAC5B,CAAA;AAAA,EACH;AAAA,EAEU,WAAA,CAAY,IAAA,EAAiB,EAAE,KAAA,EAAO,QAAO,EAAkC;AACvF,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,IAAA,CAAK,MAAA,CAAO,UAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AACjC,IAAA,IAAI,MAAA,CAAO,SAAS,YAAA,EAAc;AAChC,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,UAAA,EAAY;AAAA,QAC1C,GAAG,KAAA;AAAA,QACH,MAAA,CAAO,YAAY,WAAA,EAAY;AAAA,QAC/B,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,QAC3B,MAAA,CAAO,IAAI,WAAA;AAAY,OACxB,CAAA;AAAA,IACH;AACA,IAAA,IAAI,MAAA,CAAO,SAAS,MAAA,EAAQ;AAC1B,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,IAAA,EAAM;AAAA,QACpC,GAAG,KAAA;AAAA,QACH,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,QAC3B,MAAA,CAAO,IAAI,WAAA;AAAY,OACxB,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,OAAA,EAAS,CAAC,GAAG,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AAAA,EAC/E;AAAA;AAAA,EAGU,gBAAgB,KAAA,EAA6B;AACrD,IAAA,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,QAAA,CAAS,GAAA,EAAa,UAAA,EAA4D;AACtF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,EAAE,GAAA,EAAK,YAAY,CAAA;AACxD,IAAA,OAAO,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,EAAI,OAAO,CAAA,GAAI,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAA,CACJ,MAAA,EACA,EAAE,GAAA,EAAK,aAAY,EACC;AACpB,IAAA,MAAM,MAAA,GAAS,aAAa,MAAM,CAAA;AAClC,IAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,QACnC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,UAAA,CAAW,QAAA;AAAA,QACvC,UAAA,EAAY,CAAC,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,EAAG,GAAA,CAAI,aAAa,CAAA;AAAA,QACtD;AAAA,OACD,CAAA;AACD,MAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,QAAA,SAAA,CAAU,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,KAAK,CAAC,CAAA;AAAA,MACrC;AAAA,IACF;AACA,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAE7B,MAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,QAAA,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,MACpC;AAAA,IACF;AACA,IAAA,OAAO,MAAA,CAAO,IAAI,CAAC,CAAA,EAAG,QAAQ,SAAA,CAAU,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,EAClD;AACF,CAAA;AAGA,SAAS,OAAA,CAAQ,OAAuB,IAAA,EAAsC;AAC5E,EAAA,OAAO,CAAC,MAAM,UAAA,EAAY,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,EAAO,KAAK,MAAM,CAAA;AAC9D;AAGA,SAAS,aACP,MAAA,EACgD;AAChD,EAAA,MAAM,SAAyD,EAAC;AAChE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC7B,IAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,KAAA,CAAM,UAAU,CAAA;AAC7C,IAAA,MAAM,WAAWC,8BAAA,CAAsB,EAAA,CAAG,KAAA,CAAM,UAAA,EAAY,MAAM,UAAU,CAAA;AAC5E,IAAA,IAAI,SAAS,MAAA,IAAa,CAAC,IAAA,CAAK,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC7C,MAAA,IAAA,CAAK,IAAI,QAAQ,CAAA;AACjB,MAAA,MAAA,CAAO,IAAA,CAAK,EAAE,GAAA,EAAK,EAAA,EAAI,MAAM,UAAA,EAAY,GAAG,MAAM,CAAA;AAAA,IACpD;AAAA,EACF,CAAC,CAAA;AACD,EAAA,OAAO,MAAA;AACT;AC9HO,IAAM,mBAAN,MAAuB;AAAA,EACnB,QAAA,uBAAe,GAAA,EAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpC,WAAA,GAA6B;AAE3B,IAAA,MAAM,KAAA,GAAQ,IAAA;AACd,IAAA,OAAO,MAAM,oBAAoBC,SAAA,CAAO;AAAA,MACtC,YAAY,MAAA,EAAgC;AAC1C,QAAA,KAAA,CAAM,MAAM,CAAA;AACZ,QAAA,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,MAClB;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MAAA,EAAsB;AAC1B,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,MAAM,CAAA;AACxB,IAAA,MAAA,CAAO,KAAK,KAAA,EAAO,MAAM,KAAK,QAAA,CAAS,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAA,GAAmB;AACjB,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,QAAA,EAAU;AAElC,MAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,MAAM,MAAS,CAAA;AAClC,MAAA,MAAA,CAAO,UAAA,CAAW,OAAO,OAAA,EAAQ;AAAA,IACnC;AACA,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EACtB;AACF,CAAA;;;AChCO,IAAM,sBAAN,MAAwC;AAAA,EACpC,MAAA;AAAA,EAET,YAAY,KAAA,EAAyC;AACnD,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,WAAW,UAAA,EAAmC;AAClD,IAAA,MAAM,IAAA,CAAK,OAAO,KAAA,CAAM;AAAA,MACtB,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,UAAA;AAAA,MAClC,UAAA,EAAY,CAAC,UAAU;AAAA,KACxB,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,eAAe,KAAA,EAAiD;AACpE,IAAA,MAAM,YAAY,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,eAAe,KAAK,CAAA;AACrE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,SAAS,KAAA,CAAM,SAAA,CAAU,GAAA,EAAK,SAAA,CAAU,UAAU,CAAA;AACjF,IAAA,OAAO,IAAA,CAAK,IAAI,iBAAiB,CAAA;AAAA,EACnC;AAAA;AAAA,EAGA,MAAM,OAAA,CAAQ,WAAA,EAAgC,GAAA,EAA4B;AACxE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,MACnC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,OAAA;AAAA,MACpC,UAAA,EAAY,CAAC,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA,EAAG,GAAA,CAAI,aAAa;AAAA,KAC5D,CAAA;AACD,IAAA,OAAO,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,EAAI,OAAO,CAAA;AAAA,EACpC;AAAA;AAAA,EAGA,MAAM,WAAW,GAAA,EAA0C;AACzD,IAAA,MAAM,SAAiC,EAAE,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA,EAAG,WAAW,CAAA,EAAE;AAC3E,IAAA,KAAA,MAAW,GAAA,IAAO,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,MACxC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,aAAA;AAAA,MACpC,YAAY;AAAC,KACd,CAAA,EAAG;AACF,MAAA,MAAA,CAAO,IAAI,QAAQ,CAAW,CAAA,GAAI,SAAA,CAAU,KAAK,OAAO,CAAA;AAAA,IAC1D;AACA,IAAA,MAAM,CAAC,OAAO,CAAA,GAAI,MAAM,IAAA,CAAK,OAAO,KAAA,CAAM;AAAA,MACxC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,YAAA;AAAA,MACpC,YAAY;AAAC,KACd,CAAA;AACD,IAAA,MAAM,UAAA,GAAa,SAAA,CAAU,OAAA,EAAU,OAAO,CAAA;AAC9C,IAAA,IAAI,SAAA,GAAY,OAAO,WAAW,CAAA;AAClC,IAAA,IAAI,IAAA,CAAK,OAAO,iBAAA,EAAmB;AACjC,MAAA,MAAM,CAAC,OAAO,CAAA,GAAI,MAAM,IAAA,CAAK,OAAO,KAAA,CAAM;AAAA,QACxC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,sBAAA;AAAA,QACpC,YAAY;AAAC,OACd,CAAA;AACD,MAAA,SAAA,IAAa,SAAA,CAAU,SAAU,OAAO,CAAA;AAAA,IAC1C;AACA,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,MACxC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,SAAA;AAAA,MACpC,UAAA,EAAY,CAAC,GAAA,CAAI,WAAA,EAAa;AAAA,KAC/B,CAAA;AACD,IAAA,OAAO;AAAA;AAAA,MAEL,SAAS,IAAA,CAAK,GAAA,CAAI,GAAG,MAAA,CAAO,SAAS,IAAK,UAAU,CAAA;AAAA,MACpD,UAAA;AAAA,MACA,SAAA;AAAA,MACA,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,MACnB,WAAA,EAAa,eAAe,SAAS;AAAA,KACvC;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MAAM,OAAA,EAA6C;AACvD,IAAA,MAAM,KAAA,GAAQ,EAAE,iBAAA,EAAmB,CAAA,EAAG,eAAe,CAAA,EAAE;AACvD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,eAAA,CAAgB,OAAO,CAAA;AAC5C,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,MAAA,EAAQ,aAAa,KAAK,OAAA,EAAS;AAClD,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,cAAA,GAAiB,KAAK,MAAA,CAAO,cAAA;AACjC,MAAA,OAAO,cAAA,KAAmB,IAAA,CAAK,MAAA,CAAO,cAAA,EAAgB;AACpD,QAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,KAAK,EAAE,MAAA,EAAQ,eAAe,CAAA;AACnE,QAAA,cAAA,GAAiB,KAAA,CAAM,iBAAA;AACvB,QAAA,KAAA,CAAM,qBAAqB,KAAA,CAAM,iBAAA;AACjC,QAAA,KAAA,CAAM,iBAAiB,KAAA,CAAM,aAAA;AAAA,MAC/B;AAAA,IACF;AACA,IAAA,KAAA,CAAM,aAAA,IAAiB,MAAM,IAAA,CAAK,qBAAA,CAAsB,OAAO,CAAA;AAC/D,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,gBAAgB,OAAA,EAAkE;AAChF,IAAA,MAAM,OAAA,GAAqD;AAAA,MACzD;AAAA,QACE,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,mBAAA,EAAoB;AAAA,QACjD,OAAA,CAAQ,eAAA;AAAA,QACR,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM;AAAA,OAC/B;AAAA,MACA;AAAA,QACE,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,cAAA,EAAe;AAAA,QAC5C,OAAA,CAAQ,UAAA;AAAA,QACR,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM;AAAA;AAC/B,KACF;AACA,IAAA,IAAI,IAAA,CAAK,OAAO,iBAAA,EAAmB;AACjC,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,2BAAA,EAA4B;AAAA,QACzD,OAAA,CAAQ,eAAA;AAAA,QACR,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM;AAAA,OAC9B,CAAA;AAAA,IACH;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,sBAAsB,OAAA,EAAwC;AAClE,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,MAAM,YAAA,GAAe,CAAC,OAAA,CAAQ,eAAA,EAAiB,OAAA,CAAQ,UAAU,CAAA,CAC9D,MAAA,CAAO,CAAC,MAAA,KAAW,MAAA,KAAW,MAAS,EACvC,IAAA,CAAK,CAAC,KAAA,EAAO,MAAA,KAAW,KAAA,CAAM,OAAA,KAAY,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,CAAC,CAAA;AAChE,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,aAAA,IAAiB,MAAM,IAAA,CAAK,kBAAA;AAAA,QAC1B,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,qBAAA;AAAA,QAC7B;AAAA,UACE,eAAA,EAAiB,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,mCAAA;AAAA,UAC9C,MAAA,EAAQ,YAAA;AAAA,UACR,aAAA,EAAe;AAAA;AACjB,OACF;AAAA,IACF;AACA,IAAA,IAAI,OAAA,CAAQ,oBAAoB,MAAA,EAAW;AACzC,MAAA,aAAA,IAAiB,MAAM,IAAA,CAAK,kBAAA;AAAA,QAC1B,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,8BAAA;AAAA,QAC7B;AAAA,UACE,eAAA,EAAiB,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,kCAAA;AAAA,UAC9C,QAAQ,OAAA,CAAQ,eAAA;AAAA,UAChB,aAAA,EAAe;AAAA;AACjB,OACF;AAAA,IACF;AACA,IAAA,OAAO,aAAA;AAAA,EACT;AAAA,EAEA,MAAM,mBACJ,aAAA,EACA;AAAA,IACE,eAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF,EACiB;AACjB,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,IAAI,cAAA,GAAiB,KAAK,MAAA,CAAO,cAAA;AACjC,IAAA,OAAO,cAAA,KAAmB,IAAA,CAAK,MAAA,CAAO,cAAA,EAAgB;AACpD,MAAA,cAAA,GAAiB,MAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,WAAA,CAAY,OAAO,WAAA,KAAgB;AAC7E,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,UACrC,GAAA,EAAK,aAAA;AAAA,UACL,YAAY,CAAC,MAAA,CAAO,aAAY,EAAG,IAAA,CAAK,OAAO,cAAc,CAAA;AAAA,UAC7D;AAAA,SACD,CAAA;AACD,QAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,KAAqB,GAAA,CAAI,IAAI,CAAW,CAAC,CAAA;AAChF,QAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,UACtC,GAAA,EAAK,eAAA;AAAA,UACL,UAAA,EAAY,gBAAgB,CAAC,GAAA,EAAK,OAAO,WAAA,EAAa,CAAA,GAAI,CAAC,GAAG,CAAA;AAAA,UAC9D;AAAA,SACD,CAAA;AACD,QAAA,OAAO,SAAA,CAAU,OAAA,CAAQ,CAAC,CAAA,EAAI,OAAO,CAAA;AAAA,MACvC,CAAC,CAAA;AACD,MAAA,aAAA,IAAiB,cAAA;AAAA,IACnB;AACA,IAAA,OAAO,aAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAA,CACJ,GAAA,EACA,EAAE,MAAA,EAAQ,eAAc,EACuC;AAC/D,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,WAAA,CAAY,OAAO,WAAA,KAAgB;AAC7D,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,QACtC,GAAA;AAAA,QACA,YAAY,CAAC,MAAA,CAAO,aAAY,EAAG,IAAA,CAAK,OAAO,cAAc,CAAA;AAAA,QAC7D;AAAA,OACD,CAAA;AACD,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,QAAA,OAAO,EAAE,iBAAA,EAAmB,CAAA,EAAG,aAAA,EAAe,CAAA,EAAE;AAAA,MAClD;AACA,MAAA,MAAM,QAAA,GAAW,KAAK,SAAA,CAAU;AAAA,QAC9B,GAAG,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAU,CAAW,CAAC;AAAA,OAC3D,CAAA;AACD,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,QACrC,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,UAAA;AAAA,QAClC,UAAA,EAAY,CAAC,QAAQ,CAAA;AAAA,QACrB;AAAA,OACD,CAAA;AACD,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM;AAAA,QACtC,GAAA,EAAK,aAAA;AAAA,QACL,UAAA,EAAY,CAAC,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,KAAqB,GAAA,CAAI,IAAI,CAAW,CAAC,CAAC,CAAA;AAAA,QAClF;AAAA,OACD,CAAA;AACD,MAAA,OAAO,EAAE,iBAAA,EAAmB,OAAA,CAAQ,MAAA,EAAQ,aAAA,EAAe,UAAU,OAAA,CAAQ,CAAC,CAAA,EAAI,OAAO,CAAA,EAAE;AAAA,IAC7F,CAAC,CAAA;AAAA,EACH;AACF,CAAA;;;ACjMO,IAAM,gBAAN,MAAkC;AAAA,EAC9B,MAAA;AAAA;AAAA,EAEA,eAAA;AAAA,EAET,WAAA,CAAY,OAAyC,OAAA,EAAgC;AACnF,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,IAAA,CAAK,eAAA,GAAkB,oBAAA,CAAqB,oBAAA,CAAqB,OAAO,CAAC,CAAA;AAAA,EAC3E;AAAA;AAAA,EAGA,MAAM,GAAA,GAAqB;AAEzB,IAAA,IAAI,SAAA,CAAU,MAAM,IAAA,CAAK,YAAA,EAAc,CAAA,EAAG;AACxC,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,OAAO,WAAA,KAAgB;AAChD,MAAA,MAAM,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,eAAA,EAAiB,WAAW,CAAA;AAAA,IACnD,CAAC,CAAA;AACD,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,OAAO,WAAA,EAAa,MAAA,KAAW;AAExD,MAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,QAAA,MAAM,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,eAAA,EAAiB,WAAW,CAAA;AACjD,QAAA;AAAA,MACF;AACA,MAAA,KAAA,MAAW,SAAA,IAAa,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAkB;AACpD,QAAA,MAAM,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,WAAW,CAAA;AAAA,MACxC;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBACJ,IAAA,EACe;AACf,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,WAAA,CAAY,OAAO,WAAA,KAAgB;AAC5D,MAAA,MAAM,IAAA,CAAK,OAAO,QAAA,CAAS,KAAA;AAAA,QACzB,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,SAAA;AAAA,QAC7B,CAAC,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAAA,QACzB;AAAA,OACF;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,YAAA,CAAa,WAAW,CAAA;AAClD,MAAA,IAAI,CAAC,SAAA,CAAU,MAAM,CAAA,EAAG;AACtB,QAAA,MAAM,IAAA,CAAK,aAAa,MAAM,CAAA;AAAA,MAChC;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,IAAA,CAAK,SAAA,EAAmB,WAAA,EAA0C;AACtE,IAAA,MAAM,KAAK,MAAA,CAAO,QAAA,CAAS,MAAM,SAAA,EAAW,IAAI,WAAW,CAAA;AAAA,EAC7D;AAAA,EAEA,MAAM,aAAa,WAAA,EAAkD;AACnE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,KAAA;AAAA,MACtC,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,aAAA;AAAA,MAC7B,CAAC,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAAA,MACzB;AAAA,KACF;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,CAAK,CAAC,EAAG,QAAQ,CAAA,KAAM,IAAA,EAAM,WAAA,EAAa,IAAA,CAAK,CAAC,CAAA,CAAG,cAAc,MAAM,IAAA,EAAK;AAAA,EAC/F;AACF,CAAA;AAGA,SAAS,UAAU,MAAA,EAA8B;AAC/C,EAAA,OAAO,MAAA,CAAO,UAAU,MAAA,CAAO,WAAA;AACjC;ACzCA,IAAM,QAAA,GAAsC,CAAC,QAAA,EAAU,MAAM,CAAA;AAyC7D,IAAM,wBAAA,GAA2B,GAAA;AAG1B,SAAS,qBACd,OAAA,EAKA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,OAAA,CAAQ,QAAA,IAAY,QAAQ,IAAA,EAAM,OAAA,CAAQ,gBAAgB,CAAA,CAAE,MAAA;AAAA,IAC3E,CAAC,WAAW,MAAA,KAAW;AAAA,GACzB;AACA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,IAAIZ,uBAAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,MAAM,iBAAiBa,wBAAA,CAAgB,EAAA;AAAA,IACrC,QAAQ,cAAA,IAAkB,wBAAA;AAAA,IAC1B;AAAA,GACF;AACA,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,QAAA;AACjC,EAAA,IAAI,CAAC,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAIb,uBAAAA,CAAmB,CAAA,4CAAA,EAA+C,MAAA,CAAO,MAAM,CAAC,CAAA,CAAE,CAAA;AAAA,EAC9F;AACA,EAAA,MAAM,kBAAA,GAAqB,QAAQ,kBAAA,IAAsB,IAAA;AACzD,EAAA,IAAI,OAAO,uBAAuB,SAAA,EAAW;AAC3C,IAAA,MAAM,IAAIA,uBAAAA;AAAA,MACR,CAAA,+CAAA,EAAkD,MAAA,CAAO,kBAAkB,CAAC,CAAA;AAAA,KAC9E;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,cAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA,EAAc,kBAAA,GAAqB,EAAE,OAAA,EAAS,MAAK,GAAI;AAAA,GACzD;AACF;;;ACzHO,IAAM,mBAAN,MAAuB;AAAA,EACnB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAI,iBAAA,GAA4B;AAC9B,IAAA,OAAO,CAAA,KAAA,EAAQ,KAAK,kBAAA,EAAoB,KAAK,IAAA,CAAK,eAAA,EAAiB,CAAA,EAAA,EAAK,IAAA,CAAK,iBAAiB,CAAA,EAAA,EAAK,KAAK,mBAAA,EAAqB,KAAK,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,uCAAA,CAAA;AAAA,EAM7K;AAAA;AAAA,EAGA,kBAAA,GAA6B;AAC3B,IAAA,OAAO,CAAA;AAAA,cAAA,EACK,IAAA,CAAK,OAAO,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAAA,EAOtC;AAAA;AAAA,EAGA,eAAA,GAA0B;AACxB,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAAA,EAWT;AAAA;AAAA,EAGA,eAAA,GAA0B;AACxB,IAAA,OAAO,CAAA;AAAA,cAAA,EACK,IAAA,CAAK,OAAO,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAAA,EAWhC;AAAA;AAAA,EAGA,mBAAA,GAA8B;AAC5B,IAAA,OAAO,CAAA;AAAA,cAAA,EACK,IAAA,CAAK,OAAO,UAAU;AAAA;AAAA,2DAAA,EAEuB,cAAA,CAAe,WAAA,EAAa,UAAU,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAAA,EAQlG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,MAAA,GAAiB;AACnB,IAAA,OAAO,CAAA,wCAAA,EAA2C,IAAA,CAAK,MAAA,CAAO,mBAAmB,CAAA,MAAA,CAAA;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAA,CAAQ,UAAkB,GAAA,EAAqB;AAC7C,IAAA,OAAO,CAAA;AAAA,oBAAA,EACW,IAAA,CAAK,OAAO,mBAAmB,CAAA;AAAA,kBAAA,EACjC,QAAQ,CAAA,OAAA,EAAU,QAAQ,CAAA,iBAAA,EAAoB,GAAG,CAAA;AAAA;AAAA,CAAA,CAAA;AAAA,EAGnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,YAAA,GAAuB;AACzB,IAAA,OAAO,CAAA,YAAA,EAAe,IAAA,CAAK,MAAA,CAAO,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAAA;AAAA,EAY1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,kBAAA,GAA6B;AAC/B,IAAA,OAAO,CAAA,eAAA,EAAkB,IAAA,CAAK,MAAA,CAAO,MAAM;AAAA;AAAA;AAAA,iBAAA,CAAA;AAAA,EAI7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,IAAI,gBAAA,GAA2B;AAC7B,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,cAAA,GAAiB,CAAA,kDAAA,CAAA;AACvB,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,gDAAA,EAIuC,cAAA,CAAe,WAAA,EAAa,UAAU,CAAC,CAAA;AAAA;AAAA,OAAA,EAEhF,MAAM,CAAA;AAAA,wBAAA,EACW,cAAc,CAAA;AAAA;AAAA,cAAA,EAExB,IAAA,CAAK,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAS3B,MAAM,CAAA;AAAA;AAAA;AAAA,oCAAA,EAGqB,cAAc,CAAA;AAAA;AAAA;AAAA;AAAA,GAAA,EAI/C,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,IAAI,CAAC;AAAA,+DAAA,CAAA;AAAA,EAEjC;AACF,CAAA;;;AC7KO,IAAM,iBAAA,GAAoB,GAAA;AAG1B,IAAM,gBAAA,GAAmB,EAAA;AAOzB,IAAM,cAAA,GAAiB,EAAA;AAGvB,IAAM,kBAAA,GAAqB,CAAA;AAE3B,IAAM,iBAAA,GAAoB,CAAA,2EAAA,CAAA;AAE1B,SAAS,aAAa,KAAA,EAAuB;AAClD,EAAA,OAAO,GAAG,KAAK,CAAA;AAAA,IAAA,EACX,KAAK,CAAA;AAAA,IAAA,EACL,KAAK,CAAA;AAAA,IAAA,EACL,KAAK,CAAA;AAAA,IAAA,EACL,KAAK,CAAA;AAAA,IAAA,EACL,KAAK,CAAA;AAAA,IAAA,EACL,KAAK,CAAA;AAAA,IAAA,EACL,KAAK,CAAA;AAAA,IAAA,EACL,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,YAAA,CAAc,CAAC,CAAA,qBAAA,CAAA;AACrC;AAGO,SAAS,aAAa,GAAA,EAAqB;AAChD,EAAA,OAAO,oBAAoB,GAAG,CAAA,wDAAA,CAAA;AAChC;AAWO,SAAS,QAAA,CAAS,OAAsB,KAAA,EAAuB;AACpE,EAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AAKzB,EAAA,MAAM,OAAA,GAAU,oBAAoB,KAAK,CAAA,sCAAA,CAAA;AACzC,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KACnB,CAAA,yFAAA,EAA4F,UAAU,EAAA,GAAK,EAAA,GAAK,CAAA,wBAAA,EAA2B,KAAK,CAAA,CAAE,CAAA,CAAA,CAAA;AACpJ,EAAA,OAAO;AAAA;AAAA,aAAA,EAEM,WAAA,CAAY,EAAE,CAAC,CAAA;AAAA;AAAA,6CAAA,EAEiB,WAAA,CAAY,cAAc,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,0CAAA,EAI9B,UAAU,CAAA;AAAA,sBAAA,EAC9B,OAAO,CAAA;AAAA;AAAA,0CAAA,EAEa,UAAU,CAAA;AAAA,sBAAA,EAC9B,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAA,EAWlB,UAAU,CAAA;AAAA,YAAA,EACT,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAAA;AAKrB;AAGO,SAAS,iBAAA,CAAkB,OAAsB,SAAA,EAA2B;AACjF,EAAA,OAAO,CAAA;AAAA,2BAAA,EACoB,SAAS,CAAA;AAAA,WAAA,EACzB,MAAM,UAAU,CAAA;AAAA,KAAA,CAAA;AAE7B;;;AC5FA,IAAM,SAAA,GAAY,CAAA,4DAAA,CAAA;AAGX,IAAM,kBAAN,MAAsB;AAAA,EAClB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,CAAA,KAAA,EAAQ,IAAA,CAAK,gBAAA,CAAiB,CAAA,kDAAA,EAAqD,IAAA,CAAK,OAAO,KAAK,CAAA,gCAAA,EAAmC,SAAS,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA,EAC7J,IAAA,CAAK,aAAa;AAAA;AAAA,EAElB,KAAK,WAAA,CAAY,CAAA,sCAAA,EAAyC,iBAAiB,CAAA,sEAAA,EAAyE,gBAAgB,IAAI,CAAC,CAAA,CAAA;AAAA,EACzK;AAAA;AAAA,EAGA,WAAA,GAAsB;AACpB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAKA,UAAU,CAAA;AAAA;AAAA,uDAAA,EAEoC,iBAAiB;AAAA;AAAA;AAAA,UAAA,EAG9D,gBAAgB;AAAA;AAAA;AAAA,QAAA,EAGlB,iBAAiB;AAAA;AAAA;AAAA;AAAA,OAAA,EAIlB,UAAU,CAAA;AAAA,qCAAA,EACoB,IAAA,CAAK,WAAA,CAAY,UAAU,CAAC,CAAA;AAAA;AAAA,eAAA,CAAA;AAAA,EAGjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAI,sBAAA,GAAiC;AACnC,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,CAAA,KAAA,EAAQ,IAAA,CAAK,gBAAA,CAAiB,CAAA,kDAAA,EAAqD,IAAA,CAAK,OAAO,KAAK,CAAA,gCAAA,EAAmC,SAAS,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,sBAAA,EAIvI,QAAA,CAAS,IAAA,CAAK,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAc3C,UAAU,CAAA;AAAA;AAAA,uDAAA,EAEoC,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBxE,IAAA,CAAK,WAAA,CAAY,OAAO,CAAC,CAAA,CAAA;AAAA,EACzB;AAAA;AAAA,EAGA,iBAAiB,UAAA,EAA4B;AAC3C,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,CAAA;AAAA,EAAA,EACP,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAKL,UAAU,CAAA;AAAA;AAAA,CAAA,CAAA;AAAA,EAGjB;AAAA;AAAA,EAGA,YAAY,KAAA,EAAuB;AACjC,IAAA,OAAO,CAAA;AAAA,sBAAA,EACa,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,6BAAA,EACf,KAAK,CAAA,4BAAA,EAA+B,KAAK,CAAA,2BAAA,EAA8B,KAAK,CAAA;AAAA;AAAA,iCAAA,EAExE,KAAK,CAAA;AAAA,WAAA,EAC3B,IAAA,CAAK,iBAAA,CAAkB,KAAK,CAAC,CAAA,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,kBAAkB,KAAA,EAAuB;AACvC,IAAA,OAAO,CAAA;AAAA;AAAA,gCAAA,EAEuB,KAAK,8BAA8B,KAAK,CAAA;AAAA,OAAA,CAAA;AAAA,EAExE;AAAA;AAAA,EAGA,YAAY,SAAA,EAA2B;AACrC,IAAA,OAAO,UAAU,SAAS,CAAA;AAAA;AAAA;AAAA,EAAA,EAG1B,IAAA,CAAK,mBAAmB;AAAA;AAAA,0CAAA,CAAA;AAAA,EAG1B;AAAA;AAAA,EAGA,iBAAA,GAA4B;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA,IAAA,EAEL,YAAA,CAAa,OAAO,CAAC;AAAA;AAAA;AAAA,OAAA,EAGlB,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,OAAA,EACtB,IAAA,CAAK,OAAO,MAAM,CAAA,yCAAA,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,IAAI,WAAA,GAAsB;AACxB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAMF,KAAK,CAAA;AAAA;AAAA,OAAA,EAEL,UAAU,CAAA;AAAA;AAAA;AAAA,SAAA,EAGR,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAQL,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA,QAAA,EAIN,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAC;AAAA;AAAA;AAAA,mGAAA,CAAA;AAAA,EAI9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,IAAI,eAAA,GAA0B;AAC5B,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,SAAA,GAAY,CAAA,0FAAA,CAAA;AAClB,IAAA,MAAM,IAAA,GAAO,CAAA,cAAA,EAAiB,SAAS,CAAA,MAAA,EAAS,UAAU,CAAA;AAAA,+HAAA,CAAA;AAE1D,IAAA,OAAO,CAAA;AAAA,wBAAA,EACe,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAKlC,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,gGAAA,EACwE,IAAI,CAAA;AAAA;AAAA;AAAA,+FAAA,CAAA;AAAA,EAIpG;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,CAAA;AAAA,wBAAA,EACe,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAKlC,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA;AAAA;AAAA,iEAAA,EAGyC,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAC,CAAA,CAAA;AAAA,EACvG;AACF,CAAA;;;ACxQO,IAAM,uBAAN,MAA2B;AAAA,EACvB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAA,GAAsB;AACxB,IAAA,OAAO,YAAA,CAAa,CAAA,OAAA,EAAU,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA,kBAAA,EAI/B,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA;AAAA,GAAA,CAEtC,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,IAAI,QAAA,GAAmB;AACrB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,KAAK,MAAA,CAAO,iBAAA;AAC5B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAKF,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAKV,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAMV,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAAA;AAAA;AAAA;AAAA,+DAAA,EAIqB,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAAA;AAAA,CAAA,EAGvF,OAAA,GACI,CAAA;AAAA,cAAA,EACM,IAAA,CAAK,OAAO,WAAW,CAAA;AAAA;AAAA;AAAA,CAAA,CAAA,GAI7B,EACN;AAAA,yBAAA,CAAA;AAAA,EAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,MACV,CAAA,wJAAA;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,MACV,CAAA,yIAAA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAA,GAAkB;AACpB,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,MACV,CAAA,8FAAA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,WAAA,EAA6B;AACxC,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA,wBAAA,EACe,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAIpB,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,aAAA,EAAgB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAMjD,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA,0CAAA,CAAA;AAAA,EAKd;AACF,CAAA;;;ACvHA,SAAS,UAAA,CAAW,SAAwB,KAAA,EAAuB;AACjE,EAAA,OAAO,OAAA,KAAY,OACf,MAAA,GACA,CAAA,0BAAA,EAA6B,OAAO,CAAA,oCAAA,EAAuC,KAAK,8BAA8B,KAAK,CAAA,KAAA,CAAA;AACzH;AAGO,IAAM,sBAAN,MAA0B;AAAA,EACtB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WACE,MAAA,EACA;AAAA,IACE,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,EACQ;AACR,IAAA,MAAM,IAAA,GAAsB,EAAE,MAAA,EAAQ,KAAA,EAAO,SAAS,KAAA,EAAM;AAC5D,IAAA,OAAO,KAAK,eAAA,CAAgB,IAAI,CAAA,GAAI,IAAA,CAAK,gBAAgB,IAAI,CAAA;AAAA,EAC/D;AAAA;AAAA,EAGA,gBAAgB,EAAE,MAAA,EAAQ,KAAA,EAAO,OAAA,EAAS,OAAM,EAA0B;AACxE,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,GAAG,MAAM,CAAA;AAAA;AAAA,OAAA,EAEX,KAAK;AAAA;AAAA;AAAA,SAAA,EAGH,UAAU,CAAA;AAAA,0BAAA,EACO,KAAK,CAAA;AAAA,uDAAA,EACwB,iBAAiB;AAAA,8BAAA,EAC1C,KAAK,CAAA;AAAA;AAAA,UAAA,EAEzB,gBAAgB;AAAA;AAAA;AAAA,QAAA,EAGlB,iBAAiB;AAAA,GAAA,EACtB,MAAM,CAAA;AAAA;AAAA,+DAAA,EAEsD,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAA,EAK1D,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAA,EAKK,UAAU,CAAA;AAAA;AAAA;AAAA,YAAA,EAGpB,UAAA,CAAW,OAAA,EAAS,MAAM,CAAC;AAAA;AAAA;AAAA,QAAA,EAG/B,KAAK;AAAA,CAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,IAAA,EAA6B;AAC3C,IAAA,OACE,KAAK,eAAA,CAAgB,IAAI,IACzB,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GACnB,IAAA,CAAK,WAAA,CAAY,IAAI,IACrB,IAAA,CAAK,cAAA,CAAe,IAAI,CAAA,GACxB,IAAA,CAAK,iBAAiB,IAAI,CAAA;AAAA,EAE9B;AAAA;AAAA,EAGA,eAAA,CAAgB,EAAE,MAAA,EAAQ,KAAA,EAAO,OAAM,EAA0B;AAC/D,IAAA,OAAO,MAAM,MAAM,CAAA;AAAA,SAAA,EACZ,KAAK,CAAA,OAAA,EAAU,KAAK,CAAA,gBAAA,EAAmB,KAAK;AAAA,8BAAA,EACvB,MAAM,YAAY,KAAK;AAAA,+BAAA,EACtB,MAAM,eAAe,iBAAiB;AAAA,SAAA,EAC5D,KAAK,CAAA;AAAA,mCAAA,EACqB,MAAM,CAAA;AAAA,mDAAA,EACU,gBAAgB;AAAA;AAAA,CAAA;AAAA,EAGnE;AAAA;AAAA,EAGA,SAAA,CAAU,EAAE,MAAA,EAAO,EAA0B;AAC3C,IAAA,OAAO,MAAM,MAAM,CAAA;AAAA;AAAA,OAAA,EAEd,MAAM,CAAA;AAAA,sBAAA,EACS,QAAA,CAAS,IAAA,CAAK,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,CAAA;AAAA,EAEpD;AAAA;AAAA,EAGA,WAAA,CAAY,EAAE,MAAA,EAAQ,OAAA,EAAS,OAAM,EAA0B;AAC7D,IAAA,OAAO,MAAM,MAAM,CAAA;AAAA;AAAA,OAAA,EAEd,MAAM,CAAA;AAAA,OAAA,EACN,MAAM,CAAA;AAAA,wFAAA,EAC2E,UAAA,CAAW,OAAA,EAAS,OAAO,CAAC;AAAA;AAAA,QAAA,EAE5G,KAAK;AAAA,CAAA;AAAA,EAEb;AAAA;AAAA,EAGA,cAAA,CAAe,EAAE,MAAA,EAAQ,KAAA,EAAM,EAA0B;AACvD,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,MAAM,MAAM,CAAA;AAAA;AAAA,OAAA,EAEd,MAAM,CAAA;AAAA;AAAA;AAAA,SAAA,EAGJ,UAAU,CAAA;AAAA;AAAA,uDAAA,EAEoC,iBAAiB;AAAA;AAAA;AAAA,UAAA,EAG9D,KAAK;AAAA;AAAA;AAAA,QAAA,EAGP,KAAK;AAAA,CAAA;AAAA,EAEb;AAAA;AAAA,EAGA,gBAAA,CAAiB,EAAE,MAAA,EAAQ,KAAA,EAAM,EAA0B;AACzD,IAAA,OAAO,MAAM,MAAM,CAAA;AAAA;AAAA,sDAAA,EAEiC,MAAM,CAAA;AAAA;AAAA,yDAAA,EAEH,MAAM,CAAA;AAAA;AAAA,+DAAA,EAEA,MAAM,CAAA;AAAA;AAAA;AAAA,QAAA,EAG7D,KAAK;AAAA,CAAA,CAAA;AAAA,EAEb;AACF,CAAA;;;AC7JA,IAAM,iBAAA,GAAoB,EAAA;AAG1B,IAAM,WAAW,CAAC,KAAA,KAChB,CAAA,CAAA,EAAI,KAAK,gCAAgC,KAAK,CAAA;AAAA,UAAA,EACpC,KAAK,+BAA+B,KAAK,CAAA,2BAAA,CAAA;AAGrD,IAAM,aAAA,GAAgB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AASf,IAAM,iBAAN,MAAqB;AAAA,EACjB,MAAA;AAAA,EACA,oBAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,IAAA,CAAK,oBAAA,GAAuB,IAAI,mBAAA,CAAoB,KAAK,CAAA;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,cAAA,GAAyB;AAC3B,IAAA,OAAO,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,EAC/B;AAAA,EAEA,YAAY,gBAAA,EAAmC;AAC7C,IAAA,MAAM,IAAA,GAAO,gBAAA,GACT,IAAA,CAAK,eAAA,EAAgB,GAAI,KAAK,cAAA,EAAe,GAAI,IAAA,CAAK,aAAA,EAAc,GACpE,aAAA;AACJ,IAAA,OACE,IAAA,CAAK,UAAA,EAAW,GAAI,IAAA,GAAO,IAAA,CAAK,WAAA,EAAY,GAAI,IAAA,CAAK,YAAA,EAAa,GAAI,IAAA,CAAK,aAAA,EAAc;AAAA,EAE7F;AAAA;AAAA,EAGA,UAAA,GAAqB;AACnB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA,OAAA,EAEF,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAWH,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EASP,UAAU,CAAA;AAAA;AAAA,GAAA,EAEd,IAAA,CAAK,oBAAA,CAAqB,UAAA,CAAW,MAAA,EAAQ,EAAE,KAAA,EAAO,YAAA,EAAc,OAAA,EAAS,cAAA,EAAgB,KAAA,EAAO,SAAA,EAAW,CAAC,CAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAInH;AAAA;AAAA,EAGA,eAAA,GAA0B;AACxB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,wCAAA,EAI+B,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAC,CAAA;AAAA,OAAA,EACvE,KAAK,CAAA;AAAA;AAAA;AAAA,SAAA,EAGH,UAAU,CAAA;AAAA;AAAA,uDAAA,EAEoC,iBAAiB;AAAA;AAAA;AAAA;AAAA,2CAAA,EAI7B,QAAA,CAAS,MAAM,CAAC;AAAA;AAAA,qCAAA,EAEtB,iBAAiB;AAAA,CAAA;AAAA,EAEtD;AAAA;AAAA,EAGA,cAAA,GAAyB;AACvB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA,8BAAA,EAGqB,kBAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAA,EAatB,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAIH,cAAc,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uFAAA,EAKwC,UAAU,CAAA;AAAA;AAAA,6DAAA,EAEpC,iBAAiB;AAAA;AAAA,gBAAA,EAE9D,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAO9B;AAAA;AAAA,EAGA,aAAA,GAAwB;AACtB,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA,OAAA,EAEF,KAAK,CAAA;AAAA;AAAA;AAAA,2BAAA,EAGe,kBAAkB,CAAA;AAAA;AAAA,QAAA,EAErC,QAAA,CAAS,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAAA,EAWrB,IAAA,CAAK,oBAAA,CAAqB,UAAA,CAAW,MAAA,EAAQ,EAAE,KAAA,EAAO,YAAA,EAAc,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,4BAAA,EAA8B,CAAC,CAAA,CAAA;AAAA,EAC5H;AAAA;AAAA,EAGA,WAAA,GAAsB;AACpB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,EAOL,YAAA,CAAa,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAOlB,UAAU,CAAA;AAAA,OAAA,EACV,IAAA,CAAK,OAAO,MAAM,CAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAIzB;AAAA;AAAA,EAGA,YAAA,GAAuB;AACrB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAOF,UAAU,CAAA;AAAA;AAAA;AAAA,SAAA,EAGR,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EASL,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAQd;AAAA;AAAA,EAGA,aAAA,GAAwB;AACtB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA,wFAAA,EAC+E,gBAAgB;AAAA;AAAA,SAAA,EAE/F,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6CAAA,EAM+B,iBAAiB;AAAA;AAAA,QAAA,EAEtD,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,mEAAA,EAKqB,iBAAiB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAK3E,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0CAAA,CAAA;AAAA,EAOnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,IAAI,aAAA,GAAwB;AAC1B,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAIF,KAAK,CAAA;AAAA;AAAA;AAAA,SAAA,EAGH,UAAU,CAAA;AAAA;AAAA,uDAAA,EAEoC,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAU/D,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAOV,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uEAAA,CAAA;AAAA,EAOd;AACF,CAAA;;;ACtWO,IAAM,kBAAN,MAAsB;AAAA,EAClB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAA,GAA8B;AAC5B,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAAA,MAC9C,SAAA,EAAW,CAAA,uDAAA,CAAA;AAAA,MACX,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAAA,EAEA,2BAAA,GAAsC;AACpC,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,WAAA,EAAa;AAAA,MAC/C,SAAA,EAAW,CAAA,8BAAA,CAAA;AAAA,MACX,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAAA,EAEA,cAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAAA,MAC9C,SAAA,EAAW,CAAA,gDAAA,CAAA;AAAA,MACX,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,qBAAA,GAAgC;AAClC,IAAA,OAAO,CAAA,qBAAA,EAAwB,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAAA;AAAA,MAAA,EAE7C,IAAA,CAAK,aAAA,CAAc,OAAO,CAAC;AAAA,gCAAA,EACD,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAAA;AAAA;AAAA,+BAAA,CAAA;AAAA,EAI5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,8BAAA,GAAyC;AAC3C,IAAA,OAAO,CAAA,qBAAA,EAAwB,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAAA,KAAA,EAC9C,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAAA;AAAA,MAAA,EAE3B,IAAA,CAAK,aAAA,CAAc,OAAO,CAAC;AAAA;AAAA;AAAA,+BAAA,CAAA;AAAA,EAIjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,CAAA,eAAA,EAAkB,IAAA,CAAK,MAAA,CAAO,MAAM;AAAA;AAAA,sBAAA,CAAA;AAAA,EAG7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,kCAAA,GAA6C;AAC/C,IAAA,OAAO,YAAA,CAAa,CAAA,YAAA,EAAe,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAAA;AAAA,MAAA,EAEjD,IAAA,CAAK,aAAA,CAAc,OAAO,CAAC;AAAA;AAAA,kBAAA,EAEf,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAAA;AAAA,GAAA,CAE5C,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,mCAAA,GAA8C;AAChD,IAAA,OAAO,YAAA,CAAa,CAAA,YAAA,EAAe,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAAA;AAAA,MAAA,EAEjD,IAAA,CAAK,aAAA,CAAc,OAAO,CAAC;AAAA,gCAAA,EACD,IAAA,CAAK,MAAA,CAAO,gBAAgB,CAAA,oDAAA,CAAsD,CAAA;AAAA,EAClH;AAAA;AAAA,EAGA,cAAc,UAAA,EAA4B;AACxC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,iBAAA,GACxB,CAAA,+BAAA,EAAkC,KAAK,MAAA,CAAO,WAAW,CAAA,+BAAA,EAAkC,UAAU,CAAA,IAAA,CAAA,GACrG,EAAA;AACJ,IAAA,OAAO,6BAA6B,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,uCAAA,EAA0C,UAAU,OAAO,OAAO,CAAA,CAAA;AAAA,EAC9H;AAAA,EAEA,WAAA,CACE,KAAA,EACA,EAAE,SAAA,EAAW,aAAY,EACjB;AACR,IAAA,OAAO,CAAA;AAAA,iBAAA,EACQ,KAAK;AAAA,QAAA,EACd,SAAS;AAAA,WAAA,EACN,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAIR,KAAK,CAAA;AAAA;AAAA,4BAAA,CAAA;AAAA,EAGnB;AACF,CAAA;;;AC3HA,IAAM,kBAAA,GAAqB,GAAA;AAW3B,SAAS,gBAAgB,KAAA,EAIvB;AACA,EAAA,MAAM,aAAkC,EAAC;AACzC,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAAqC;AACjD,IAAA,UAAA,CAAW,KAAK,KAAK,CAAA;AACrB,IAAA,OAAO,CAAA,CAAA,EAAI,WAAW,MAAM,CAAA,EAAA,EAAK,OAAO,KAAA,KAAU,QAAA,GAAW,QAAQ,MAAM,CAAA,CAAA;AAAA,EAC7E,CAAA;AACA,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,SAAS,KAAA,CAAM,OAAA,KAAY,SAAY,MAAA,GAAY,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IACrE,WAAW,KAAA,CAAM,SAAA,KAAc,SAAY,MAAA,GAAY,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,IAC3E,SAAS,KAAA,CAAM,OAAA,KAAY,SAAY,MAAA,GAAY,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IACrE,QAAQ,KAAA,CAAM,MAAA,KAAW,SAAY,MAAA,GAAY,IAAA,CAAK,MAAM,MAAM;AAAA,GACpE;AACA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,IAAS,kBAAkB,CAAA;AACpD,EAAA,OAAO,EAAE,UAAA,EAAY,OAAA,EAAS,KAAA,EAAM;AACtC;AAGA,SAAS,cAAA,CAAe,SAAsB,KAAA,EAAyB;AACrE,EAAA,OAAO;AAAA,IACL,GAAI,OAAA,CAAQ,OAAA,KAAY,MAAA,GAAY,EAAC,GAAI,CAAC,CAAA,EAAG,KAAK,CAAA,WAAA,EAAc,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AAAA,IACjF,GAAI,OAAA,CAAQ,SAAA,KAAc,MAAA,GAAY,KAAK,CAAC,CAAA,aAAA,EAAgB,OAAA,CAAQ,SAAS,CAAA,CAAE,CAAA;AAAA,IAC/E,GAAI,OAAA,CAAQ,OAAA,KAAY,MAAA,GAAY,EAAC,GAAI,CAAC,CAAA,EAAG,KAAK,CAAA,YAAA,EAAe,OAAA,CAAQ,OAAO,CAAA,CAAE;AAAA,GACpF;AACF;AAGO,IAAM,kBAAN,MAAsB;AAAA,EAClB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,IAAI,OAAA,GAAkB;AACpB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,YAAA,CAAa,CAAA;AAAA,0BAAA,EACI,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAK7B,UAAU,CAAA;AAAA;AAAA;AAAA,wDAAA,CAGsC,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAe,KAAA,EAAyC;AACtD,IAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,KAAA,EAAM,GAAI,gBAAgB,KAAK,CAAA;AAC5D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,kBAAA,CAAmB,OAAO,CAAA;AAC/C,IAAA,MAAM,cAAA,GACJ,KAAK,MAAA,CAAO,iBAAA,KAAsB,MAAM,MAAA,KAAW,MAAA,IAAa,MAAM,MAAA,KAAW,WAAA,CAAA;AACnF,IAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,MAAA,OAAO;AAAA,QACL,GAAA,EAAK,GAAG,OAAO;AAAA;AAAA,MAAA,EAAsD,KAAK,CAAA,CAAA;AAAA,QAC1E;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,kBAAA,CAAmB,OAAO,CAAA;AAC/C,IAAA,OAAO;AAAA,MACL,GAAA,EAAK,CAAA;AAAA,EAAoB,OAAO;AAAA;AAAA,EAAgB,OAAO;AAAA;AAAA;AAAA,MAAA,EAA0D,KAAK,CAAA,CAAA;AAAA,MACtH;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,mBAAmB,OAAA,EAA8B;AAC/C,IAAA,MAAM,QAAA,GAAW,CAAA,oEAAA,CAAA;AACjB,IAAA,MAAM,YAAA,GAAe;AAAA,MACnB,GAAG,cAAA,CAAe,OAAA,EAAS,UAAU,CAAA;AAAA,MACrC,GAAI,OAAA,CAAQ,MAAA,KAAW,MAAA,GACnB,EAAC,GACD;AAAA,QACE,CAAA,WAAA,EAAc,QAAQ,CAAA,+CAAA,EAAkD,OAAA,CAAQ,MAAM,CAAA;AAAA;AACxF,KACN;AACA,IAAA,OAAO,CAAA;AAAA,YAAA,EACG,QAAQ,CAAA;AAAA,iCAAA,EACa,QAAQ,CAAA;AAAA,EAAA,EACvC,OAAA,CAAQ,uBAAuB,CAAC,CAAA;AAAA,YAAA,EACtB,QAAQ,CAAA;AAAA,YAAA,EACR,QAAQ,CAAA,MAAA,EAAS,OAAA,CAAQ,uBAAuB,CAAC,CAAA;AAAA;AAAA,EAAA,EAE3D,OAAA,CAAQ,qBAAqB,CAAC,CAAA;AAAA,EAAA,EAC9B,OAAA,CAAQ,qBAAqB,CAAC,CAAA;AAAA,EAAA,EAC9B,OAAA,CAAQ,uBAAuB,CAAC,CAAA;AAAA,EAAA,EAChC,YAAA,CAAa,OAAO,CAAC;AAAA,KAAA,EAClB,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,KAAA,EACtB,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,KAAA,EACjB,IAAA,CAAK,OAAO,MAAM,CAAA;AAAA,EACvB,YAAA,CAAa,WAAW,CAAA,GAAI,EAAA,GAAK,SAAS,YAAA,CAAa,IAAA,CAAK,OAAO,CAAC,CAAA,CAAE,CAAA,CAAA;AAAA,EACtE;AAAA;AAAA,EAGA,mBAAmB,OAAA,EAA8B;AAC/C,IAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAA4B,cAAA,CAAe,SAAS,KAAK,CAAA;AACzE,IAAA,OAAO,CAAA;AAAA,EAAA,EACP,OAAA,CAAQ,mBAAmB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,EAAA,EAI5B,OAAA,CAAQ,iBAAiB,CAAC,CAAA;AAAA,EAAA,EAC1B,OAAA,CAAQ,mBAAmB,CAAC,CAAA;AAAA,EAAA,EAC5B,OAAA,CAAQ,mBAAmB,CAAC,CAAA;AAAA,EAAA,EAC5B,YAAA,CAAa,OAAO,CAAC;AAAA,KAAA,EAClB,IAAA,CAAK,OAAO,WAAW,CAAA;AAAA,KAAA,EACvB,IAAA,CAAK,OAAO,MAAM,CAAA;AAAA,EACvB,MAAA,CAAO,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA,GAAI,EAAA,GAAK,CAAA,MAAA,EAAS,MAAA,CAAO,MAAM,CAAA,CAAE,IAAA,CAAK,OAAO,CAAC,CAAA,CAAE,CAAA,CAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,aAAA,GAAwB;AAC1B,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,OAAO,CAAC,SAAA,EAAW,MAAA,EAAQ,WAAW,CAAA,CACnC,GAAA;AAAA,MACC,CAAC,MAAA,KACC,CAAA,QAAA,EAAW,MAAM,CAAA,0CAAA,EAA6C,UAAU,oBAAoB,MAAM,CAAA,CAAA;AAAA,KACtG,CACC,KAAK,eAAe,CAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,YAAA,GAAuB;AACzB,IAAA,OAAO,CAAA;AAAA,KAAA,EACJ,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA;AAAA,KAAA,EAEjB,IAAA,CAAK,OAAO,UAAU,CAAA,uEAAA,CAAA;AAAA,EAC3B;AAAA,EAEA,IAAI,sBAAA,GAAiC;AACnC,IAAA,OAAO,CAAA,oCAAA,EAAuC,IAAA,CAAK,MAAA,CAAO,WAAW,CAAA,CAAA;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,SAAA,GAAoB;AACtB,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,KAAA;AAC1B,IAAA,OAAO,CAAA,OAAA,EAAU,OAAA,CAAQ,iBAAiB,CAAC,CAAA;AAAA;AAAA,OAAA,EAEtC,KAAK,CAAA;AAAA;AAAA,sCAAA,EAE0B,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAOzC,KAAK,CAAA;AAAA,yDAAA,EAC6C,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAC;AAAA,QAAA,CAAA;AAAA,EAE/F;AACF,CAAA;;;AC9LO,IAAM,kBAAN,MAAsB;AAAA,EAClB,MAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,YAAA,GAAuB;AACzB,IAAA,OAAO,CAAA,SAAA,EAAY,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,CAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,aAAA,GAAwB;AAI1B,IAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAA,EAKY,KAAK,MAAA,CAAO,MAAM,CAAA,mBAAA,EAAsB,IAAA,CAAK,OAAO,cAAc,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAA,EAKlE,KAAK,MAAA,CAAO,MAAM,CAAA,mBAAA,EAAsB,IAAA,CAAK,OAAO,eAAe,CAAA;AAAA;AAAA;AAAA,qBAAA,CAAA;AAAA,EAIxF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,SAAA,GAAoB;AACtB,IAAA,OAAO,iFAAA;AAAA,EACT;AACF,CAAA;;;ACJO,IAAM,qBAAN,MAAyB;AAAA,EACrB,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EAET,YAAY,KAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,eAAA,CAAgB,KAAK,CAAA;AACtC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,gBAAA,CAAiB,KAAK,CAAA;AACxC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,cAAA,CAAe,KAAK,CAAA;AACrC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,eAAA,CAAgB,KAAK,CAAA;AACtC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,oBAAA,CAAqB,KAAK,CAAA;AAChD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,KAAK,CAAA;AACxC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,eAAA,CAAgB,KAAK,CAAA;AAAA,EACxC;AACF,CAAA;;;ACmBO,IAAM,qBAAN,MAAwF;AAAA,EACpF,MAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA,GAAS,IAAI,gBAAA,EAAiB;AAAA,EAEvC,YAAY,OAAA,EAAkD;AAC5D,IAAA,MAAM,EAAE,cAAA,EAAgB,MAAA,EAAQ,YAAA,EAAa,GAAI,qBAAqB,OAAO,CAAA;AAC7E,IAAA,MAAM,KAAA,GAAQ,qBAAqB,OAAO,CAAA;AAC1C,IAAA,MAAM,UAAA,GAAa,IAAI,kBAAA,CAAmB,KAAK,CAAA;AAC/C,IAAA,MAAM,gBAAA,GAAmB,+BAA+B,OAAO,CAAA;AAC/D,IAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,OAAA;AACjC,IAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,SAAA,EAAU,GAAI,OAAA,CAAQ,OAAA,EAAS,EAAE,MAAA,EAAQ,KAAA,EAAO,IAAA,CAAK,MAAA,EAAQ,CAAA;AACrF,IAAA,MAAM,KAAA,GAA0C;AAAA,MAC9C,QAAA;AAAA,MACA,UAAA;AAAA,MACA,gBAAA;AAAA,MACA,YAAA,EAAc,WAAW,KAAA,CAAM,YAAA;AAAA,MAC/B,YAAA,EAAc,uBAAuB,OAAO,CAAA;AAAA,MAC5C,cAAA;AAAA,MACA,mBAAmB,KAAA,CAAM,iBAAA;AAAA,MACzB,MAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAU,MAAA,KAAW,QAAA;AAAA,MACrB,KAAA,EAAO,CAAC,EAAE,GAAA,EAAK,UAAA,EAAY,WAAA,EAAY,KACrC,QAAA,CAAS,KAAA,CAAM,GAAA,EAAK,UAAA,EAAY,WAAA,EAAa,YAAY,CAAA;AAAA,MAC3D,SAAA,EAAW,IAAIc,wBAAA,EAAgB;AAAA,MAC/B,YAAA,sBAAkB,GAAA,EAAI;AAAA,MACtB,WAAA,sBAAiB,GAAA,EAAI;AAAA,MACrB,cAAA,sBAAoB,GAAA,EAAI;AAAA,MACxB,SAAA;AAAA,MACA,IAAA;AAAA,MACA,qBAAqB,KAAA,CAAM,mBAAA;AAAA,MAC3B,oBAAoB,MAAA,CAAO,iBAAA;AAAA,MAC3B,oBAAA,EAAsB,MAAA;AAAA,MACtB,MAAA,EAAQ,KAAA;AAAA,MACR,eAAA,sBAAqB,GAAA;AAAI,KAC3B;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,cAAA,CAAe,KAAK,CAAA;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,cAAA,CAAe,KAAK,CAAA;AACvC,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,kBAAA,CAAmB,KAAK,CAAA;AAC/C,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,mBAAA,CAAoB,KAAK,CAAA;AACjD,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,aAAA,CAAc,KAAA,EAAO,OAAO,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,IAAA,CAAK,OAAO,GAAA,EAAI;AAAA,EACxB;AAAA;AAAA,EAGS,eAAA,GAAwDC,iCAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjE,uBAAuB,KAAA,EAAyB;AAC9C,IAAA,OACE,8BAAA,CAA+B,KAAK,CAAA,IACpC,IAAA,CAAK,OAAO,QAAA,CAAS,sBAAA,GAAyB,KAAK,CAAA,KAAM,IAAA;AAAA,EAE7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,WAAA,CACJ,IAAA,EACA,OAAA,EACY;AACZ,IAAA,MAAM,GAAA,GAAM,EAAE,IAAA,EAAM,KAAA,EAAM;AAC1B,IAAA,MAAM,OAAA,GAAU,OAAO,WAAA,KAA0C;AAC/D,MAAA,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,GAAA,CAAI,WAAA,EAAa,GAAG,CAAA;AAChD,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,KAAK,WAAW,CAAA;AAAA,MAC/B,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,MAAA,CAAO,WAAW,CAAA;AAAA,MAChD;AAAA,IACF,CAAA;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA,CAAM,SAAS,OAAO,CAAA;AAChD,IAAA,IAAI,IAAI,IAAA,EAAM;AACZ,MAAA,IAAA,CAAK,UAAU,eAAA,EAAgB;AAAA,IACjC;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,KAAA,CACE,MACA,OAAA,EACY;AACZ,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,WAAA,CAAY,IAAI,CAAA;AAAA,IAC9C;AACA,IAAA,MAAM,EAAE,SAAA,EAAW,cAAA,EAAe,GAAI,OAAA;AACtC,IAAA,OAAO,mBAAmB,MAAA,GACtB,qBAAA,CAAsB,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,CAAA,GACtD,sBAAsB,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,gBAAgB,CAAA;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAA,CACE,WAAA,EACA,OAAA,EACA,GAAA,EACuB;AACvB,IAAA,OAAO,KAAK,SAAA,CAAU,MAAA,CAAO,aAAa,EAAE,OAAA,EAAS,KAAK,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OAAA,EAAmD;AACvD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA;AAAA,EACnC;AAAA,EAEA,WAAA,CAAY,OAAuB,cAAA,EAAwC;AAEzE,IAAA,OAAO,OAAA,CAAQ,QAAQ,IAAA,CAAK,WAAA,CAAY,YAAY,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAC,CAAA;AAAA,EAChF;AAAA;AAAA,EAGA,QAAA,CAAS,KAAA,EAAuB,GAAA,EAAW,WAAA,EAA8C;AACvF,IAAA,OAAO,KAAK,WAAA,CAAY,QAAA,CAAS,OAAO,EAAE,GAAA,EAAK,aAAa,CAAA;AAAA,EAC9D;AAAA,EAEA,YAAA,CAAa,QAAmC,GAAA,EAA+B;AAC7E,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,YAAA,CAAa,MAAA,EAAQ,GAAG,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,UAAA,CACE,KAAA,EACA,WAAA,EACA,KAAA,EACA,GAAA,EACkB;AAClB,IAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,MACb,IAAA,CAAK,YAAY,WAAA,CAAY;AAAA,QAC3B,KAAA;AAAA,QACA,QAAQ,EAAE,IAAA,EAAM,YAAA,EAAc,WAAA,EAAa,OAAO,GAAA;AAAI,OACvD;AAAA,KACH;AAAA,EACF;AAAA;AAAA,EAGA,IAAA,CAAK,KAAA,EAAuB,KAAA,EAAkB,GAAA,EAA6B;AACzE,IAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,MACb,IAAA,CAAK,WAAA,CAAY,WAAA,CAAY,EAAE,KAAA,EAAO,MAAA,EAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,GAAA,EAAI,EAAG;AAAA,KAC9E;AAAA,EACF;AAAA;AAAA,EAGA,OAAA,CAAQ,OAAuB,GAAA,EAA6B;AAC1D,IAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,MACb,IAAA,CAAK,WAAA,CAAY,WAAA,CAAY,EAAE,KAAA,EAAO,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,GAAA,EAAI,EAAG;AAAA,KAC1E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,mBAAmB,QAAA,EAAkE;AACzF,IAAA,IAAI,KAAK,MAAA,CAAO,IAAA,KAAS,UAAa,CAAC,IAAA,CAAK,OAAO,QAAA,EAAU;AAC3D,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA;AACjC,IAAA,MAAM,UAAU,IAAI,oBAAA;AAAA,MAClB,YAAY;AAEV,QAAA,MAAM,MAAA,GAAS,IAAIH,SAAAA,CAAO,OAAO,CAAA;AACjC,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,MAAM,CAAA;AACxB,QAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,QAAA,OAAO,MAAA;AAAA,MACT,CAAA;AAAA,MACA,KAAK,MAAA,CAAO,mBAAA;AAAA,MACZ,QAAA;AAAA,MACA,KAAK,MAAA,CAAO;AAAA,KACd;AACA,IAAA,MAAM,QAAQ,KAAA,EAAM;AACpB,IAAA,OAAO,MAAM,QAAQ,KAAA,EAAM;AAAA,EAC7B;AAAA;AAAA,EAGA,WAAW,UAAA,EAAmC;AAC5C,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,UAAU,CAAA;AAAA,EAChD;AAAA,EAEA,eAAe,KAAA,EAAiD;AAC9D,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,cAAA,CAAe,KAAK,CAAA;AAAA,EAC/C;AAAA,EAEA,OAAA,CAAQ,aAAgC,GAAA,EAA4B;AAClE,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,OAAA,CAAQ,WAAA,EAAa,GAAG,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAA,EAA6C;AACjD,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AAAA,EACxC;AAAA,EAEA,WAAW,GAAA,EAA0C;AACnD,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,GAAG,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAA,CAAM,OAAA,GAAwB,EAAC,EAAkB;AACrD,IAAA,IAAA,CAAK,OAAO,MAAA,GAAS,IAAA;AACrB,IAAA,IAAA,CAAK,OAAO,oBAAA,IAAuB;AACnC,IAAA,IAAA,CAAK,OAAO,oBAAA,GAAuB,MAAA;AACnC,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,SAAA;AACzB,IAAA,IAAA,CAAK,OAAO,SAAA,GAAY,MAAA;AACxB,IAAA,MAAM,EAAE,QAAO,GAAI,OAAA;AACnB,IAAA,MAAM,KAAA,GAAQ,MAAY,IAAA,CAAK,MAAA,CAAO,UAAA,EAAW;AACjD,IAAA,IAAI,MAAA,EAAQ,YAAY,IAAA,EAAM;AAC5B,MAAA,KAAA,EAAM;AAAA,IACR;AACA,IAAA,MAAA,EAAQ,iBAAiB,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AACvD,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,GAAA,EAAI;AAAA,IAClB,CAAA,SAAE;AACA,MAAA,MAAA,EAAQ,mBAAA,CAAoB,SAAS,KAAK,CAAA;AAAA,IAC5C;AAAA,EACF;AACF;AAMA,SAAS,OAAA,CACP,OAAA,EACA,EAAE,MAAA,EAAQ,OAAM,EAKhB;AACA,EAAA,IAAI,OAAA,CAAQ,aAAa,MAAA,EAAW;AAClC,IAAA,MAAM,EAAE,QAAA,EAAAI,SAAAA,EAAU,IAAA,EAAAC,OAAK,GAAI,OAAA;AAC3B,IAAA,OAAO;AAAA,MACL,QAAA,EACEA,KAAAA,KAAS,MAAA,GAAYD,SAAAA,GAAW,YAAA,CAAaA,SAAAA,EAAU,IAAI,UAAA,CAAWC,KAAAA,EAAM,EAAE,MAAA,EAAQ,CAAC,CAAA;AAAA,MACzF,IAAA,EAAAA,KAAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,MAAM,IAAA,GACJ,OAAA,CAAQ,IAAA,IACR,IAAIC,OAAA,CAAK;AAAA,IACP,GAAG,OAAA,CAAQ,UAAA;AAAA,IACX,kBAAkB,OAAA,CAAQ,gBAAA;AAAA,IAC1B,MAAA,EAAQ,MAAM,WAAA;AAAY,GAC3B,CAAA;AACH,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAW;AAC9B,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,IAAU,OAAA;AACrC,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAU;AAC1B,MAAA,UAAA,CAAW,KAAA;AAAA,QACT,CAAA,mFAAA,EAAsF,MAAM,OAAO,CAAA;AAAA,OACrG;AAAA,IACF,CAAC,CAAA;AACD,IAAA,SAAA,GAAY,IAAA;AAAA,EACd;AAGA,EAAA,MAAM,QAAA,GAAW,IAAI,UAAA,CAAW,IAAA,EAAM;AAAA,IACpC,MAAA;AAAA,IACA,aAAA,EAAe,SAAA,KAAc,MAAA,IAAa,OAAA,CAAQ,kBAAA,KAAuB;AAAA,GAC1E,CAAA;AACD,EAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,SAAA,EAAU;AACrC","file":"index.cjs","sourcesContent":["import type { PostgresStoreState } from './postgres-store-state.js';\n\n/** What {@link budgetSettingsSql} sets and how long the settings last. */\nexport type BudgetSettings = {\n /** The value as SQL: a parameter (`$1`) or a quoted literal (`'5000ms'`). */\n readonly value: string;\n /**\n * Also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+, `transaction_timeout`: the\n * server then ends the session of an overrun, so only executors that survive that get them\n * ({@link PostgresExecutor.sessionTimeouts}).\n */\n readonly sessionTimeouts: boolean;\n /** `transaction`: `SET LOCAL` semantics, gone with the transaction. `session`: kept by the connection. */\n readonly scope: 'transaction' | 'session';\n};\n\n/** The statement that holds a transaction to a time budget: `statement_timeout` and, see {@link BudgetSettings}, more. */\nexport function budgetSettingsSql({ value, sessionTimeouts, scope }: BudgetSettings): string {\n const local = scope === 'transaction';\n const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;\n if (!sessionTimeouts) {\n return statementTimeout;\n }\n return (\n `${statementTimeout}, set_config('idle_in_transaction_session_timeout', ${value}, ${local}), ` +\n \"CASE WHEN current_setting('server_version_num')::int >= 170000 \" +\n `THEN set_config('transaction_timeout', ${value}, ${local}) END`\n );\n}\n\n/** Puts the settings {@link budgetSettingsSql} keeps at session level back to the defaults of the session. */\nexport const SESSION_DEFAULTS_SQL =\n 'SELECT set_config(name, reset_val, false) FROM pg_settings ' +\n \"WHERE name IN ('statement_timeout', 'idle_in_transaction_session_timeout', 'transaction_timeout')\";\n\n/** The budget as a setting value: whole milliseconds, so nothing but digits reaches SQL text. */\nexport function budgetValue(timeoutMs: number): string {\n return `${Math.ceil(timeoutMs)}ms`;\n}\n\n/**\n * Runs `work` in a transaction of `state`'s executor that the server holds to `timeoutMs`. An executor\n * with `transactionWithBudget` (`PgExecutor`) sets the budget in the round trip of its `BEGIN`; any\n * other executor runs it with `SET LOCAL` semantics as the first statement of the transaction.\n */\nexport function inBudgetedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithBudget !== undefined) {\n return executor.transactionWithBudget(work, timeoutMs);\n }\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await state.query({ sql, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import { ConfigurationError, type TransactionIsolationLevel } from '@relaybus/core';\nimport type { PostgresStoreState } from './postgres-store-state.js';\nimport { budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/** The SQL keywords of each level. Only these literals ever reach SQL text. */\nconst ISOLATION_KEYWORDS: Readonly<Record<TransactionIsolationLevel, string>> = {\n 'read committed': 'READ COMMITTED',\n 'repeatable read': 'REPEATABLE READ',\n serializable: 'SERIALIZABLE',\n};\n\n/** The keywords of `isolationLevel` as SQL; an unknown level (a store called around the bus) is refused. */\nexport function isolationKeywords(isolationLevel: TransactionIsolationLevel): string {\n const keywords = Object.hasOwn(ISOLATION_KEYWORDS, isolationLevel)\n ? ISOLATION_KEYWORDS[isolationLevel]\n : undefined;\n if (keywords === undefined) {\n throw new ConfigurationError(`Unknown isolation level ${JSON.stringify(isolationLevel)}`);\n }\n return keywords;\n}\n\n/**\n * Runs `work` in a transaction at `isolationLevel` that the server holds to `timeoutMs`. An executor\n * with `transactionWithIsolation` (`PgExecutor`) sends both with its `BEGIN`; any other executor gets\n * `SET TRANSACTION ISOLATION LEVEL` as the first statement of the transaction and the budget as the\n * second: PostgreSQL refuses the level once a query ran, and the budget's `set_config` is a query.\n */\nexport function inIsolatedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n isolationLevel,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n readonly isolationLevel: TransactionIsolationLevel;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithIsolation !== undefined) {\n return executor.transactionWithIsolation(work, { isolationLevel, timeoutMs });\n }\n const keywords = isolationKeywords(isolationLevel);\n const budget = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await executor.query(`SET TRANSACTION ISOLATION LEVEL ${keywords}`, [], transaction);\n await state.query({ sql: budget, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import { createHash } from 'node:crypto';\nimport type { RelayBusLogger } from '@relaybus/core';\nimport type { Pool, PoolClient } from 'pg';\nimport type {\n PostgresExecutor,\n PostgresIsolatedTransactionOptions,\n PostgresParameter,\n PostgresQueryOptions,\n PostgresRow,\n} from './executor.js';\nimport { isolationKeywords } from './transaction-isolation.js';\nimport { SESSION_DEFAULTS_SQL, budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/**\n * SQLSTATEs of a named statement the server does not know (26000) or already has under that name\n * (42P05). Both mean the connection the statement ran on is not the session that prepared it, which is\n * what a pooler in transaction mode without prepared statement support (PgBouncer before 1.21) does.\n */\nconst FOREIGN_SESSION_ERRORS = new Set(['26000', '42P05']);\n\nexport interface PgExecutorOptions {\n /** Receives the warning sent when prepared statements are switched off. Default `console`. */\n readonly logger?: RelayBusLogger;\n /**\n * The pool is this executor's alone (the store sets it for the pool it creates from\n * `connectionString`). A transaction budget then becomes a session setting of the connection, sent\n * with `BEGIN` only when the connection does not have it yet, and a transaction without a budget on\n * such a connection puts the session defaults back in its `BEGIN`. Statements outside a\n * transaction run under the budget the connection last got. Never set it for a pool other code\n * uses, or behind a pooler in transaction mode (session settings would reach other clients); the\n * executor stops it by itself when it notices a pooler (see prepared statements). Default `false`.\n */\n readonly sessionBudget?: boolean;\n}\n\n/** How a transaction starts on one connection, and what its commit tells about the session. */\ntype TransactionStart = {\n readonly begin: string;\n /** The budget the session keeps once the transaction committed; `null` for the defaults. */\n readonly sessionValue?: string | null;\n};\n\n/** Hex digits of the statement hash in a prepared statement name. */\nconst STATEMENT_NAME_DIGITS = 24;\n\n/**\n * Executor for a `pg` {@link Pool}. A transaction is a dedicated pool client\n * between `BEGIN` and `COMMIT`; it is handed to callers as the transaction\n * handle, so they can run their own queries on it.\n *\n * A statement sent with `prepare: true` is a named prepared statement: each\n * connection parses and plans its text once and from then on only binds the\n * parameters. Its name is derived from the text, so stores with different\n * tables never share one. When the server reports that a prepared statement\n * does not exist on the connection, or already does (a pooler such as\n * PgBouncer before 1.21 in transaction mode hands every transaction another\n * server session), the executor stops preparing for good, logs a warning, and\n * runs the statement again unprepared unless it belonged to a transaction,\n * which has failed by then and is the caller's to retry.\n */\nexport class PgExecutor implements PostgresExecutor<PoolClient> {\n readonly #pool: Pool;\n readonly #logger: RelayBusLogger;\n readonly #names = new Map<string, string>();\n #preparing = true;\n readonly #sessionBudget: boolean;\n /** The budget each connection keeps at session level (`sessionBudget`); absent for the defaults. */\n readonly #sessionValues = new WeakMap<PoolClient, string>();\n\n constructor(pool: Pool, options: PgExecutorOptions = {}) {\n this.#pool = pool;\n this.#logger = options.logger ?? console;\n this.#sessionBudget = options.sessionBudget === true;\n }\n\n /** The connection listens for `error` during the transaction, so a server-ended session fails the transaction instead of the process. */\n readonly sessionTimeouts = true;\n\n transaction<T>(work: (transaction: PoolClient) => Promise<T>): Promise<T> {\n // Once a pooler was noticed, which session a connection reaches is unknown: every transaction resets.\n return this.#transaction(work, (client) =>\n this.#sessionBudget && (!this.#preparing || this.#sessionValues.has(client))\n ? { begin: `BEGIN; ${SESSION_DEFAULTS_SQL}`, sessionValue: null }\n : { begin: 'BEGIN' },\n );\n }\n\n /**\n * Sends `BEGIN` and the budget settings as one simple query (the value as a literal: the simple\n * query protocol has no parameters), so the budget costs no round trip. With `sessionBudget` a\n * connection that already keeps this budget only gets `BEGIN`.\n */\n transactionWithBudget<T>(\n work: (transaction: PoolClient) => Promise<T>,\n timeoutMs: number,\n ): Promise<T> {\n return this.#transaction(work, this.#budgetStart(timeoutMs, 'BEGIN'));\n }\n\n /**\n * Like {@link PgExecutor.transactionWithBudget} with `BEGIN ISOLATION LEVEL ...`: the level is set\n * with the `BEGIN` of the same simple query, before the budget's first statement.\n */\n transactionWithIsolation<T>(\n work: (transaction: PoolClient) => Promise<T>,\n { isolationLevel, timeoutMs }: PostgresIsolatedTransactionOptions,\n ): Promise<T> {\n return this.#transaction(\n work,\n this.#budgetStart(timeoutMs, `BEGIN ISOLATION LEVEL ${isolationKeywords(isolationLevel)}`),\n );\n }\n\n /** How a transaction starts on a connection when it is held to `timeoutMs`; `begin` is the `BEGIN` statement. */\n #budgetStart(timeoutMs: number, begin: string): (client: PoolClient) => TransactionStart {\n const value = budgetValue(timeoutMs);\n const settings = (scope: 'transaction' | 'session'): string =>\n budgetSettingsSql({ value: `'${value}'`, sessionTimeouts: true, scope });\n return (client) => {\n if (!this.#keepsSessionBudget()) {\n return { begin: `${begin}; ${settings('transaction')}` };\n }\n return this.#sessionValues.get(client) === value\n ? { begin }\n : { begin: `${begin}; ${settings('session')}`, sessionValue: value };\n };\n }\n\n #recordSession(client: PoolClient, sessionValue: string | null | undefined): void {\n if (sessionValue === null) {\n this.#sessionValues.delete(client);\n } else if (sessionValue !== undefined) {\n this.#sessionValues.set(client, sessionValue);\n }\n }\n\n /** A pooler that hands out other server sessions (noticed by prepared statements) shares session settings. */\n #keepsSessionBudget(): boolean {\n return this.#sessionBudget && this.#preparing;\n }\n\n async #transaction<T>(\n work: (transaction: PoolClient) => Promise<T>,\n start: (client: PoolClient) => TransactionStart,\n ): Promise<T> {\n const client = await this.#pool.connect();\n let released = false;\n const release = (destroy: boolean): void => {\n if (released) {\n return;\n }\n released = true;\n client.removeListener('error', onSessionEnded);\n if (destroy) {\n client.release(true);\n } else {\n client.release();\n }\n };\n // The pool only listens while a client is idle: an error event of a checked-out client (the\n // server ending the session, for example at idle_in_transaction_session_timeout) would be\n // unhandled. The connection is dead, so it goes back to the pool at once, destroyed; the\n // transaction fails at its next statement or its commit.\n const onSessionEnded = (error: Error): void => {\n this.#logger.warn(\n `[PgExecutor](transaction) The server ended the session of an open transaction, the transaction fails | error=${error.message}`,\n );\n release(true);\n };\n client.on('error', onSessionEnded);\n const { begin, sessionValue } = start(client);\n try {\n await client.query(begin);\n const result = await work(client);\n const { command } = await client.query('COMMIT');\n // Settings changed in a transaction that rolls back (a failed one answers COMMIT with ROLLBACK)\n // return to what the session had before.\n if (command === 'COMMIT') {\n this.#recordSession(client, sessionValue);\n }\n release(false);\n return result;\n } catch (error) {\n await this.#rollbackAndRelease(client, release);\n throw error;\n }\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n async query(\n sql: string,\n parameters: readonly PostgresParameter[],\n transaction?: PoolClient,\n options?: PostgresQueryOptions,\n ): Promise<readonly PostgresRow[]> {\n const queryable = transaction ?? this.#pool;\n const values = [...parameters];\n if (options?.prepare !== true || !this.#preparing) {\n return (await queryable.query<PostgresRow>(sql, values)).rows;\n }\n try {\n return (await queryable.query<PostgresRow>({ name: this.#nameOf(sql), text: sql, values }))\n .rows;\n } catch (error) {\n if (!FOREIGN_SESSION_ERRORS.has((error as { code?: unknown }).code as string)) {\n throw error;\n }\n if (this.#preparing) {\n this.#preparing = false;\n this.#logger.warn(\n `[PgExecutor](query) The server does not keep prepared statements per connection, statements are sent unprepared from now on; set preparedStatements: false to skip this check | code=${String((error as { code?: unknown }).code)}`,\n );\n }\n if (transaction !== undefined) {\n throw error;\n }\n return (await queryable.query<PostgresRow>(sql, values)).rows;\n }\n }\n\n /** `relaybus_` and 24 hex digits of the SHA-256 of the text: well under the 63 bytes of an identifier. */\n #nameOf(sql: string): string {\n let name = this.#names.get(sql);\n if (name === undefined) {\n name = `relaybus_${createHash('sha256').update(sql).digest('hex').slice(0, STATEMENT_NAME_DIGITS)}`;\n this.#names.set(sql, name);\n }\n return name;\n }\n\n /** A client whose rollback fails is in an unknown state, so it is destroyed instead of reused. */\n async #rollbackAndRelease(\n client: PoolClient,\n release: (destroy: boolean) => void,\n ): Promise<void> {\n try {\n await client.query('ROLLBACK');\n release(false);\n } catch {\n release(true);\n }\n }\n}\n","import { ConfigurationError } from '@relaybus/core';\n\nconst IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_]*$/;\nconst MAXIMUM_IDENTIFIER_LENGTH = 63;\n\n/**\n * Throws {@link ConfigurationError} unless `value` is a plain lower-case\n * PostgreSQL identifier. Identifiers are interpolated into SQL text (they\n * cannot be bound as parameters), so this is the injection boundary: only\n * letters, digits and underscores survive, and nothing needs escaping.\n */\nexport function assertIdentifier(label: string, value: string): void {\n if (!IDENTIFIER_PATTERN.test(value) || value.length > MAXIMUM_IDENTIFIER_LENGTH) {\n throw new ConfigurationError(\n `${label} '${value}' must match ${String(IDENTIFIER_PATTERN)} and be at most ${MAXIMUM_IDENTIFIER_LENGTH} characters`,\n );\n }\n}\n\n/** Double-quotes an identifier that already passed {@link assertIdentifier}. */\nexport function quoteIdentifier(value: string): string {\n return `\"${value}\"`;\n}\n","import { ConfigurationError } from '@relaybus/core';\nimport { createHash } from 'node:crypto';\nimport { assertIdentifier, quoteIdentifier } from './identifiers.js';\n\n/** Where relaybus keeps its tables. */\nexport interface PostgresSchemaOptions {\n /** Schema that holds the tables. Created by `setup()` when it is not `public`. Default `'public'`. */\n readonly schema?: string;\n /**\n * Prepended to every table and index name, which makes the names\n * `<prefix>events`, `<prefix>deliveries` and `<prefix>key_sequences`.\n * Lower-case letters, digits and underscores. Default `'relaybus_'`.\n */\n readonly tablePrefix?: string;\n /**\n * Keep an append-only record of completed deliveries in\n * `<prefix>completed_deliveries`, so `listDeliveries({ status: 'completed' })`,\n * `statistics().completed` and `retention.completed` keep working. Default\n * `false`: a completed delivery is deleted, which avoids the dead tuples and\n * index churn of updating it. Use the same value in every process.\n */\n readonly completionHistory?: boolean;\n}\n\n/** Validated, quoted names used to build SQL. */\nexport interface PostgresNames {\n readonly schema: string;\n readonly quotedSchema: string;\n readonly events: string;\n /** Unquoted, unqualified name of {@link events}, for catalog lookups. */\n readonly eventsTableName: string;\n readonly deliveries: string;\n readonly keySequences: string;\n /** Lane lease rows: one per lane, see {@link LANE_COUNT}. */\n readonly lanes: string;\n /** Unquoted, unqualified name of {@link lanes}, for catalog lookups. */\n readonly lanesTableName: string;\n /** One row per event that had a delivery complete: when the last one did. Retention of completed work is measured from it. */\n readonly eventCompletions: string;\n /** Completion history, present only with `completionHistory`. */\n readonly completions: string;\n readonly completionHistory: boolean;\n /**\n * Channel of the notifications that wake dispatchers when deliveries were published:\n * `<schema>.<prefix>deliveries`, or a hash of it when that is longer than a channel name may be.\n */\n readonly notificationChannel: string;\n /** Index names, quoted but not schema-qualified (an index lives in its table's schema). */\n readonly indexes: {\n readonly deliveryEventHandler: string;\n readonly deliveryLaneDue: string;\n readonly deliveryKeyPending: string;\n readonly eventCreated: string;\n readonly deliveryCompleted: string;\n readonly deliveryDead: string;\n readonly completionCompleted: string;\n readonly eventCompletionsCompleted: string;\n /** Indexes of the 0.1.0 schema that the current schema drops. */\n readonly obsolete: readonly string[];\n };\n}\n\n/**\n * Number of lanes. Every delivery belongs to the lane of its ordering key (or of\n * its event id when the event has no key); workers lease whole lanes. The count\n * is fixed because the lane of a delivery is stored, and all processes must\n * agree on it.\n */\nexport const LANE_COUNT = 256;\n\nconst DEFAULT_SCHEMA = 'public';\nconst MAXIMUM_CHANNEL_LENGTH = 63;\nconst DEFAULT_TABLE_PREFIX = 'relaybus_';\nconst TABLE_PREFIX_PATTERN = /^[a-z0-9_]*$/;\n\n/** Derives the names of every index, current and obsolete, from the index-name builder. */\nfunction indexNames(index: (suffix: string) => string): PostgresNames['indexes'] {\n return {\n deliveryEventHandler: index('deliveries_event_handler_unique'),\n deliveryLaneDue: index('deliveries_lane_due_idx'),\n deliveryKeyPending: index('deliveries_key_pending_idx'),\n eventCreated: index('events_created_idx'),\n deliveryCompleted: index('deliveries_completed_idx'),\n deliveryDead: index('deliveries_dead_idx'),\n completionCompleted: index('completed_deliveries_completed_idx'),\n eventCompletionsCompleted: index('event_completions_completed_idx'),\n obsolete: [\n index('deliveries_due_idx'),\n index('deliveries_due_unkeyed_idx'),\n index('deliveries_handler_created_idx'),\n index('deliveries_key_unfinished_idx'),\n index('deliveries_key_processing_idx'),\n index('deliveries_status_created_idx'),\n ],\n };\n}\n\n/**\n * Validates the options and derives every name the store uses. Every name,\n * including the longest index name, is checked against the PostgreSQL 63\n * character limit so that a too-long prefix fails here and not as a\n * silently truncated, colliding name in the database.\n */\nexport function resolvePostgresNames(options: PostgresSchemaOptions = {}): PostgresNames {\n const schema = options.schema ?? DEFAULT_SCHEMA;\n const tablePrefix = options.tablePrefix ?? DEFAULT_TABLE_PREFIX;\n assertIdentifier('schema', schema);\n if (!TABLE_PREFIX_PATTERN.test(tablePrefix)) {\n throw new ConfigurationError(\n `tablePrefix '${tablePrefix}' must match ${String(TABLE_PREFIX_PATTERN)}`,\n );\n }\n const name = (suffix: string): string => {\n const identifier = `${tablePrefix}${suffix}`;\n assertIdentifier(`tablePrefix '${tablePrefix}' produces the name`, identifier);\n return identifier;\n };\n const quotedSchema = quoteIdentifier(schema);\n const table = (suffix: string): string => `${quotedSchema}.${quoteIdentifier(name(suffix))}`;\n const index = (suffix: string): string => quoteIdentifier(name(suffix));\n return {\n schema,\n quotedSchema,\n events: table('events'),\n eventsTableName: name('events'),\n deliveries: table('deliveries'),\n keySequences: table('key_sequences'),\n lanes: table('lanes'),\n lanesTableName: name('lanes'),\n eventCompletions: table('event_completions'),\n completions: table('completed_deliveries'),\n completionHistory: options.completionHistory ?? false,\n notificationChannel: channelName(`${schema}.${tablePrefix}deliveries`),\n indexes: indexNames(index),\n };\n}\n\n/** Hex digits of the hash that names a channel whose readable name is too long. */\nconst CHANNEL_HASH_DIGITS = 32;\n\n/** PostgreSQL truncates names longer than 63 bytes, which could merge channels: those are hashed instead. */\nfunction channelName(readable: string): string {\n return readable.length <= MAXIMUM_CHANNEL_LENGTH\n ? readable\n : `relaybus_${createHash('sha256').update(readable).digest('hex').slice(0, CHANNEL_HASH_DIGITS)}`;\n}\n","import { LANE_COUNT } from './names.js';\n\n/**\n * Renders a timestamptz as ISO-8601 text in UTC. Reading timestamps as text\n * makes results independent of the driver's type parsers (Drizzle, for\n * instance, replaces them) and of the session time zone.\n */\nexport function isoText(expression: string): string {\n return `to_char(${expression} AT TIME ZONE 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`;\n}\n\n/**\n * The lane of a delivery: a hash of the ordering key, or of the event id when\n * the event has no key. All deliveries of one key therefore share a lane and\n * are owned by one worker at a time, which is what keeps their order.\n * `hashtextextended` is stable across PostgreSQL versions and platforms.\n */\nexport function laneExpression(keyExpression: string, eventIdExpression: string): string {\n return `(hashtextextended(COALESCE(${keyExpression}, ${eventIdExpression}), 0) & ${LANE_COUNT - 1})::smallint`;\n}\n","import { createHash } from 'node:crypto';\nimport {\n LANE_COUNT,\n resolvePostgresNames,\n type PostgresNames,\n type PostgresSchemaOptions,\n} from './names.js';\nimport { laneExpression } from './sql-fragments.js';\n\n/** Hex digits of the statement hash in the schema marker. */\nconst SCHEMA_MARKER_DIGITS = 32;\n\n/** The payload and headers columns of the event table, and as 0.4.0 and earlier created them. */\nconst PAYLOAD_COLUMNS = ` payload json NOT NULL,\n headers json NOT NULL DEFAULT '{}'::json,`;\nconst JSONB_PAYLOAD_COLUMNS = ` payload jsonb NOT NULL,\n headers jsonb NOT NULL DEFAULT '{}'::jsonb,`;\n\n/**\n * Statements that create the schema, tables and indexes, in dependency order,\n * and upgrade a 0.1.0 schema and the `jsonb` payload columns of schemas before 0.4.1 in place.\n * Every statement is idempotent (`IF NOT EXISTS`, or guarded by a check for the old columns). Run them in\n * one transaction and serialize concurrent runs (see\n * {@link PostgresEventStore.setup}), or paste {@link createPostgresSchemaSql}\n * into your own migration tool.\n *\n * `events.id` and `deliveries.id` are `text` so that any caller-supplied id\n * (UUID, ULID, deterministic business id) is accepted. `deliveries.id` uses the\n * `C` collation so that ordering by id matches a byte-wise comparison on every\n * database, whatever its locale.\n *\n * A delivery row is written once (insert) and removed once (delete) on the\n * normal path. The lease lives in the lane row a delivery belongs to, so\n * claiming, renewing and completing never update an indexed column of the\n * delivery. The lane table is tiny, has no index besides its primary key and\n * leaves free space in its pages, so its updates are heap-only (HOT).\n */\nexport function createPostgresSchemaStatements(options: PostgresSchemaOptions = {}): string[] {\n const names = resolvePostgresNames(options);\n const statements = schemaBodyStatements(names);\n statements.push(`COMMENT ON TABLE ${names.lanes} IS '${version040Marker(names, statements)}'`);\n return statements;\n}\n\n/** The schema statements without the marker comment. */\nfunction schemaBodyStatements(names: PostgresNames): string[] {\n const statements = [...eventAndDeliveryStatements(names), ...laneAndCompletionStatements(names)];\n if (names.completionHistory) {\n statements.push(...completionHistoryStatements(names));\n }\n if (names.schema !== 'public') {\n statements.unshift(`CREATE SCHEMA IF NOT EXISTS ${names.quotedSchema}`);\n }\n return statements;\n}\n\n/** The event, key sequence and delivery tables, their upgrades and indexes. */\nfunction eventAndDeliveryStatements(names: PostgresNames): string[] {\n return [...eventAndKeySequenceStatements(names), ...deliveryStatements(names)];\n}\n\n/** The event table with its index, and the key sequence table. */\nfunction eventAndKeySequenceStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.events} (\n id text PRIMARY KEY,\n type text NOT NULL,\n source text NOT NULL,\n key text,\n sequence bigint,\n${PAYLOAD_COLUMNS}\n correlation_id text,\n causation_id text,\n occurred_at timestamptz NOT NULL,\n created_at timestamptz NOT NULL,\n handlers text[] NOT NULL DEFAULT '{}'\n)`,\n upgradePayloadToJson(names),\n `CREATE INDEX IF NOT EXISTS ${names.indexes.eventCreated} ON ${names.events} (created_at, id)`,\n `CREATE TABLE IF NOT EXISTS ${names.keySequences} (\n key text PRIMARY KEY,\n sequence bigint NOT NULL\n)`,\n ];\n}\n\n/** The delivery table, the 0.1.0 upgrade, the obsolete index drops and the current indexes. */\nfunction deliveryStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.deliveries} (\n id text COLLATE \"C\" PRIMARY KEY,\n event_id text NOT NULL REFERENCES ${names.events} (id) ON DELETE CASCADE,\n handler text NOT NULL,\n lane smallint NOT NULL,\n claims integer NOT NULL DEFAULT 0,\n status text NOT NULL CHECK (status IN ('pending', 'processing', 'completed', 'dead')),\n attempts integer NOT NULL DEFAULT 0,\n available_at timestamptz NOT NULL,\n last_error jsonb,\n key text,\n sequence bigint,\n created_at timestamptz NOT NULL,\n updated_at timestamptz NOT NULL,\n completed_at timestamptz,\n CONSTRAINT ${names.indexes.deliveryEventHandler} UNIQUE (event_id, handler)\n) WITH (autovacuum_vacuum_scale_factor = 0.02, autovacuum_analyze_scale_factor = 0.05)`,\n upgradeFromVersion010(names),\n `ALTER TABLE ${names.deliveries} ADD COLUMN IF NOT EXISTS claims integer NOT NULL DEFAULT 0`,\n `ALTER TABLE ${names.deliveries} SET (autovacuum_vacuum_scale_factor = 0.02, autovacuum_analyze_scale_factor = 0.05)`,\n ...names.indexes.obsolete.map((index) => `DROP INDEX IF EXISTS ${names.quotedSchema}.${index}`),\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryLaneDue} ON ${names.deliveries} (lane, available_at, id) WHERE status = 'pending'`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryKeyPending} ON ${names.deliveries} (lane, handler, key, sequence) WHERE key IS NOT NULL AND status = 'pending'`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryCompleted} ON ${names.deliveries} (completed_at, id) WHERE status = 'completed'`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.deliveryDead} ON ${names.deliveries} (updated_at, id) WHERE status = 'dead'`,\n ];\n}\n\n/** The lane and event completion tables, and the lane rows. */\nfunction laneAndCompletionStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.lanes} (\n lane smallint PRIMARY KEY CHECK (lane >= 0 AND lane < ${LANE_COUNT}),\n epoch bigint NOT NULL DEFAULT 0,\n lease_owner text,\n lease_expires_at timestamptz,\n in_flight text[] NOT NULL DEFAULT '{}',\n claim_floor bigint NOT NULL DEFAULT 0\n) WITH (fillfactor = 50)`,\n `ALTER TABLE ${names.lanes} ADD COLUMN IF NOT EXISTS claim_floor bigint NOT NULL DEFAULT 0`,\n `CREATE TABLE IF NOT EXISTS ${names.eventCompletions} (\n event_id text PRIMARY KEY REFERENCES ${names.events} (id) ON DELETE CASCADE,\n completed_at timestamptz NOT NULL\n)`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.eventCompletionsCompleted} ON ${names.eventCompletions} (completed_at, event_id)`,\n `INSERT INTO ${names.lanes} (lane) SELECT generate_series(0, ${LANE_COUNT - 1})::smallint ON CONFLICT (lane) DO NOTHING`,\n ];\n}\n\n/** The completion history table, kept with `completionHistory: true`. */\nfunction completionHistoryStatements(names: PostgresNames): string[] {\n return [\n `CREATE TABLE IF NOT EXISTS ${names.completions} (\n id text COLLATE \"C\" PRIMARY KEY,\n event_id text NOT NULL REFERENCES ${names.events} (id) ON DELETE CASCADE,\n handler text NOT NULL,\n attempts integer NOT NULL,\n available_at timestamptz NOT NULL,\n created_at timestamptz NOT NULL,\n completed_at timestamptz NOT NULL\n)`,\n `CREATE INDEX IF NOT EXISTS ${names.indexes.completionCompleted} ON ${names.completions} (completed_at, id)`,\n ];\n}\n\n/**\n * A schema marker: the hash of `statements`. The last schema statement leaves one on the lane table\n * ({@link version040SchemaMarker}), and {@link PostgresEventStore.setup} reads it to skip the\n * statements when the schema is already current, because their table locks queue behind running\n * claims and completions and deadlock with them.\n */\nfunction postgresSchemaMarker(statements: readonly string[]): string {\n return `relaybus schema ${createHash('sha256').update(statements.join(';')).digest('hex').slice(0, SCHEMA_MARKER_DIGITS)}`;\n}\n\n/**\n * Upgrades a 0.1.0 deliveries table, recognized by its `lease_token` column.\n * Rows keep their ids, attempts and payload references. Deliveries that were\n * `processing` become `pending` (their attempt stays counted, as a lost lease\n * would count it), every row gets its lane, every event learns which handlers\n * it already has deliveries for, and the per-delivery lease columns go. Deliveries completed under 0.1.0 stay as `completed` rows until\n * `retention.completed` purges them. Stop all 0.1.0 workers before the first\n * run: they cannot use the upgraded tables.\n */\nfunction upgradeFromVersion010(names: ReturnType<typeof resolvePostgresNames>): string {\n return `DO $relaybus_upgrade$\nBEGIN\n IF EXISTS (\n SELECT 1 FROM pg_attribute\n WHERE attrelid = '${names.deliveries}'::regclass AND attname = 'lease_token' AND NOT attisdropped\n ) THEN\n ALTER TABLE ${names.events} ADD COLUMN IF NOT EXISTS handlers text[] NOT NULL DEFAULT '{}';\n UPDATE ${names.events} AS event SET handlers = known.handlers\n FROM (\n SELECT event_id, array_agg(handler) AS handlers FROM ${names.deliveries} GROUP BY event_id\n ) AS known\n WHERE event.id = known.event_id;\n ALTER TABLE ${names.deliveries} ADD COLUMN IF NOT EXISTS lane smallint;\n UPDATE ${names.deliveries} SET lane = ${laneExpression('key', 'event_id')} WHERE lane IS NULL;\n ALTER TABLE ${names.deliveries} ALTER COLUMN lane SET NOT NULL;\n UPDATE ${names.deliveries} SET status = 'pending' WHERE status = 'processing';\n ALTER TABLE ${names.deliveries}\n DROP COLUMN lease_owner, DROP COLUMN lease_token, DROP COLUMN lease_expires_at;\n END IF;\nEND\n$relaybus_upgrade$`;\n}\n\n/**\n * Turns the `jsonb` payload and headers columns of a schema created before 0.4.1 into `json`, which\n * keeps the text the producer serialized: `jsonb` re-orders object keys, so an event read back\n * serialized differently from what was published. One table rewrite under an exclusive lock; rows\n * stored before the upgrade keep the key order `jsonb` gave them. A no-op once both columns are\n * `json`, and when the table does not exist yet. {@link PostgresEventStore.setup} runs it in a\n * transaction of its own before the other statements, so it holds no other table lock while it\n * waits for the event table (a completion locks deliveries before the event rows it references).\n */\nexport function upgradePayloadToJson(names: PostgresNames): string {\n return `DO $relaybus_payload_json$\nBEGIN\n IF EXISTS (\n SELECT 1 FROM pg_attribute\n WHERE attrelid = to_regclass('${names.events}') AND attname IN ('payload', 'headers')\n AND atttypid = 'jsonb'::regtype AND NOT attisdropped\n ) THEN\n ALTER TABLE ${names.events}\n ALTER COLUMN headers DROP DEFAULT,\n ALTER COLUMN payload TYPE json USING payload::json,\n ALTER COLUMN headers TYPE json USING headers::json,\n ALTER COLUMN headers SET DEFAULT '{}'::json;\n END IF;\nEND\n$relaybus_payload_json$`;\n}\n\n/**\n * The schema marker 0.4.0 writes, which 0.4.1 keeps writing: the hash of the schema statements without\n * the payload conversion and with the `jsonb` columns of 0.4.0. A 0.4.0 instance started next to 0.4.1,\n * or after a rollback, then still finds its marker and runs no schema statement, whose table locks could\n * deadlock with running claims. Whether the payload columns are converted is read from the column types\n * instead (see {@link SetupStatements.schemaCurrent}).\n */\nexport function version040SchemaMarker(options: PostgresSchemaOptions = {}): string {\n const names = resolvePostgresNames(options);\n return version040Marker(names, schemaBodyStatements(names));\n}\n\n/** {@link version040SchemaMarker} of the body statements of {@link schemaBodyStatements}. */\nfunction version040Marker(names: PostgresNames, statements: readonly string[]): string {\n const conversion = upgradePayloadToJson(names);\n return postgresSchemaMarker(\n statements\n .filter((statement) => statement !== conversion)\n .map((statement) => statement.replace(PAYLOAD_COLUMNS, JSONB_PAYLOAD_COLUMNS)),\n );\n}\n\n/**\n * The statements of {@link createPostgresSchemaStatements} as one SQL script,\n * for migration tools. Pair it with `new RelayBus({ setupStore: false })`.\n */\nexport function createPostgresSchemaSql(options: PostgresSchemaOptions = {}): string {\n return `${createPostgresSchemaStatements(options).join(';\\n\\n')};\\n`;\n}\n","import type { RelayBusLogger } from '@relaybus/core';\nimport { systemClock } from '@relaybus/core';\nimport { schedule, type CancelTimer } from '@relaybus/core/internal';\n\n/** Wait before a lost listening connection is opened again. */\nconst RECONNECT_DELAY_MS = 1_000;\n\n/** What the listener needs of a connection: a `pg` `Client` has it. */\nexport interface ListeningConnection {\n on(event: 'notification', listener: () => void): unknown;\n on(event: 'error', listener: (error: Error) => void): unknown;\n on(event: 'end', listener: () => void): unknown;\n query(sql: string): Promise<unknown>;\n end(): Promise<void>;\n}\n\n/**\n * Returns a function that ends the connection once, however often it is called. `ended` is set\n * first because ending can report the end synchronously, which calls back into the loss handler.\n */\nfunction endOnce(connection: ListeningConnection, ended: { value: boolean }): () => Promise<void> {\n let ending: Promise<void> = Promise.resolve();\n return () => {\n if (!ended.value) {\n ended.value = true;\n ending = connection.end().catch(() => undefined);\n }\n return ending;\n };\n}\n\n/**\n * Holds one connection of its own (outside any pool, so it never takes a connection the store needs)\n * that `LISTEN`s on a channel, and calls a listener for every notification. The notifications are hints\n * for the dispatcher, never needed for correctness: when the connection is lost it is replaced after a\n * pause, and the listener is called once for whatever was sent meanwhile.\n */\nexport class NotificationListener {\n readonly #connect: () => Promise<ListeningConnection>;\n readonly #channel: string;\n readonly #listener: () => void;\n readonly #logger: RelayBusLogger;\n /** Ends the current connection, listening or still starting; undefined while there is none. */\n #drop: (() => Promise<void>) | undefined;\n #reconnectTimer: CancelTimer | undefined;\n #closed = false;\n\n constructor(\n connect: () => Promise<ListeningConnection>,\n channel: string,\n listener: () => void,\n logger: RelayBusLogger,\n ) {\n this.#connect = connect;\n this.#channel = channel;\n this.#listener = listener;\n this.#logger = logger;\n }\n\n /** Connects and listens. Rejects when that fails; a connection lost later is replaced. */\n async start(): Promise<void> {\n const connection = await this.#connect();\n const ended = { value: false };\n const end = endOnce(connection, ended);\n if (this.#closed) {\n await end();\n return;\n }\n // Registered before LISTEN, so closing ends a connection whose LISTEN has not answered yet.\n this.#drop = end;\n let listening = false;\n const onLost = (error?: Error): void => {\n if (!listening || ended.value) {\n // While starting, a failure surfaces as the rejection of LISTEN, which ends the connection.\n return;\n }\n void end();\n // Only a listening connection gets here, and it is always the current one.\n this.#drop = undefined;\n this.#logger.warn(\n `[NotificationListener](start) Listening connection lost, opening another | channel=${this.#channel} | error=${error?.message ?? 'connection ended'}`,\n );\n this.#scheduleReconnect();\n };\n connection.on('error', onLost);\n connection.on('end', () => onLost());\n connection.on('notification', () => this.#listener());\n try {\n await connection.query(`LISTEN \"${this.#channel}\"`);\n } catch (error) {\n await this.#abandonFailedListen(end, error);\n return;\n }\n if (this.#closed) {\n await end();\n return;\n }\n listening = true;\n }\n\n /** Forgets and ends a connection whose LISTEN failed; rethrows the failure unless closing caused it. */\n async #abandonFailedListen(end: () => Promise<void>, error: unknown): Promise<void> {\n if (this.#drop === end) {\n this.#drop = undefined;\n }\n await end();\n if (this.#closed) {\n // Closing ended the connection while LISTEN was pending: not a failure to report.\n return;\n }\n throw error;\n }\n\n #scheduleReconnect(): void {\n this.#reconnectTimer = schedule(systemClock, {\n run: () => {\n this.#reconnectTimer = undefined;\n this.start().then(\n () => {\n if (!this.#closed) {\n this.#listener();\n }\n },\n (error: unknown) => {\n this.#logger.warn(\n `[NotificationListener](scheduleReconnect) Listening again failed, retrying | channel=${this.#channel} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n if (!this.#closed) {\n this.#scheduleReconnect();\n }\n },\n );\n },\n delayMs: RECONNECT_DELAY_MS,\n unref: true,\n });\n }\n\n /** Stops listening for good and ends the connection. */\n async close(): Promise<void> {\n this.#closed = true;\n this.#reconnectTimer?.();\n const drop = this.#drop;\n this.#drop = undefined;\n await drop?.();\n }\n}\n","import type { PoolClient } from 'pg';\nimport type { PostgresExecutor } from './executor.js';\n\n/**\n * An executor whose transactions (and the statements in them) belong to `executor`, the application's\n * library, while statements outside a transaction run on `root`, a `PgExecutor` on a `pg` pool of the\n * same database that keeps them as prepared statements.\n */\nexport function withRootPool<TTransaction>(\n executor: PostgresExecutor<TTransaction>,\n root: PostgresExecutor<PoolClient>,\n): PostgresExecutor<TTransaction> {\n return {\n ...(executor.sessionTimeouts === undefined\n ? {}\n : { sessionTimeouts: executor.sessionTimeouts }),\n transaction: (work) => executor.transaction(work),\n ...(executor.transactionWithBudget === undefined\n ? {}\n : {\n transactionWithBudget: (work, timeoutMs) =>\n executor.transactionWithBudget!(work, timeoutMs),\n }),\n ...(executor.transactionWithIsolation === undefined\n ? {}\n : {\n transactionWithIsolation: (work, options) =>\n executor.transactionWithIsolation!(work, options),\n }),\n ...(executor.isSerializationFailure === undefined\n ? {}\n : { isSerializationFailure: (error) => executor.isSerializationFailure!(error) }),\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction, options) =>\n transaction === undefined\n ? root.query(sql, parameters, undefined, options)\n : executor.query(sql, parameters, transaction, options),\n };\n}\n","/** PostgreSQL SQLSTATE `serialization_failure`: a concurrent transaction conflicts, running this one again can succeed. */\nconst SERIALIZATION_FAILURE = '40001';\n\n/**\n * Prisma's code for \"write conflict or deadlock\" of an interactive transaction (`P2034`): raised for\n * `40001` and, since running it again is just as safe, for a deadlock (`40P01`).\n */\nconst PRISMA_WRITE_CONFLICT = 'P2034';\n\nconst CONFLICT_CODES: ReadonlySet<unknown> = new Set([\n SERIALIZATION_FAILURE,\n PRISMA_WRITE_CONFLICT,\n]);\n\n/** Wrappers nested deeper than this are not searched; real ones are two or three levels deep. */\nconst MAXIMUM_DEPTH = 6;\n\n/** The properties that hold the error a library wrapped: standard `cause`, TypeORM `driverError`. */\nconst WRAPPED_ERROR_KEYS = ['cause', 'driverError', 'originalError'] as const;\n\ntype ErrorShape = {\n readonly code?: unknown;\n readonly originalCode?: unknown;\n readonly driverAdapterError?: unknown;\n readonly meta?: unknown;\n readonly [key: string]: unknown;\n};\n\n/**\n * True when `error` is, or wraps, a PostgreSQL serialization failure (SQLSTATE `40001`), whichever\n * library raised it: `pg` (Kysely, Knex and the `pg` executor pass its error through), TypeORM's\n * `QueryFailedError` (`driverError`), Drizzle's wrapper (`cause`), Prisma (`P2034`, or a raw-query\n * error whose `meta.code` is the SQLSTATE, and driver-adapter errors that nest the original error).\n */\nexport function isPostgresSerializationFailure(error: unknown, depth = 0): boolean {\n if (typeof error !== 'object' || error === null || depth > MAXIMUM_DEPTH) {\n return false;\n }\n const shape = error as ErrorShape;\n if (CONFLICT_CODES.has(shape.code) || shape.originalCode === SERIALIZATION_FAILURE) {\n return true;\n }\n const meta = shape.meta as ErrorShape | undefined;\n if (\n isPostgresSerializationFailure(meta, depth + 1) ||\n isPostgresSerializationFailure(meta?.driverAdapterError, depth + 1)\n ) {\n return true;\n }\n return WRAPPED_ERROR_KEYS.some((key) => isPostgresSerializationFailure(shape[key], depth + 1));\n}\n","import type {\n ClaimedDelivery,\n DeliveryRecord,\n DeliveryStatus,\n ErrorInfo,\n EventEnvelope,\n EventHeaders,\n} from '@relaybus/core';\nimport { LaneLeaseTokenFormat, type LaneLeaseTokenParts } from '@relaybus/core/internal';\nimport type { PostgresRow } from './executor.js';\nimport { LANE_COUNT } from './names.js';\n\n// Rows come from statements written in this package, so their shape is known.\n// Casting here is the single place where driver output is trusted.\n\nfunction text(row: PostgresRow, column: string): string {\n return row[column] as string;\n}\n\nfunction nullableText(row: PostgresRow, column: string): string | null {\n return row[column] as string | null;\n}\n\nfunction nullableDate(row: PostgresRow, column: string): Date | null {\n const value = nullableText(row, column);\n return value === null ? null : new Date(value);\n}\n\n/** Count columns arrive as number, string or bigint depending on the driver. */\nexport function readCount(row: PostgresRow, column: string): number {\n return Number(row[column]);\n}\n\nexport function mapEventEnvelope(row: PostgresRow): EventEnvelope {\n return {\n id: text(row, 'event_id'),\n type: text(row, 'event_type'),\n source: text(row, 'event_source'),\n key: nullableText(row, 'event_key'),\n payload: JSON.parse(text(row, 'event_payload')) as unknown,\n headers: JSON.parse(text(row, 'event_headers')) as EventHeaders,\n correlationId: nullableText(row, 'event_correlation_id'),\n causationId: nullableText(row, 'event_causation_id'),\n occurredAt: new Date(text(row, 'event_occurred_at')),\n };\n}\n\n/** Lease tokens of this store: epochs are bigint text of up to 18 digits. */\nconst LEASE_TOKENS = new LaneLeaseTokenFormat({\n laneCount: LANE_COUNT,\n epochDigits: 18,\n claimsDigits: 9,\n});\n\n/**\n * The fencing token of a claimed delivery names its lane and the lane's epoch,\n * so every state change can check the lane without reading the delivery first.\n */\nexport function formatLeaseToken(\n lane: number,\n { epoch, claims }: { readonly epoch: string; readonly claims: number },\n): string {\n return LEASE_TOKENS.format(lane, { epoch, claims });\n}\n\n/**\n * A lane lease: lane, epoch and claim generation. `claims` counts the claims of this delivery\n * that ended before this one; every end of a claim bumps it, so an old lease can never match a\n * newer claim.\n */\nexport type LaneLease = LaneLeaseTokenParts;\n\n/** Splits a lease token; undefined when it was not issued by this store. */\nexport function parseLeaseToken(token: string): LaneLease | undefined {\n return LEASE_TOKENS.parse(token);\n}\n\nexport function mapClaimedDelivery(row: PostgresRow, leaseExpiresAt: Date): ClaimedDelivery {\n return {\n deliveryId: text(row, 'delivery_id'),\n leaseToken: formatLeaseToken(readCount(row, 'lane'), {\n epoch: text(row, 'epoch'),\n claims: readCount(row, 'claims'),\n }),\n handler: text(row, 'handler'),\n attempt: readCount(row, 'attempt'),\n leaseExpiresAt,\n event: mapEventEnvelope(row),\n };\n}\n\nexport function mapDeliveryRecord(row: PostgresRow): DeliveryRecord {\n const lastError = nullableText(row, 'last_error');\n return {\n id: text(row, 'delivery_id'),\n handler: text(row, 'handler'),\n status: text(row, 'status') as DeliveryStatus,\n attempts: readCount(row, 'attempts'),\n availableAt: new Date(text(row, 'available_at')),\n leaseOwner: nullableText(row, 'lease_owner'),\n leaseExpiresAt: nullableDate(row, 'lease_expires_at'),\n lastError: lastError === null ? null : (JSON.parse(lastError) as ErrorInfo),\n createdAt: new Date(text(row, 'created_at')),\n updatedAt: new Date(text(row, 'updated_at')),\n completedAt: nullableDate(row, 'completed_at'),\n event: mapEventEnvelope(row),\n };\n}\n\nexport function mapOldestDueAt(rows: readonly PostgresRow[]): Date | null {\n return nullableDate(rows[0]!, 'oldest_due_at');\n}\n","import {\n systemClock,\n type AppendEntry,\n type AppendResult,\n type EventEnvelope,\n} from '@relaybus/core';\nimport { CompositeKey, schedule } from '@relaybus/core/internal';\nimport type { PostgresRow } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { readCount } from './row-mapping.js';\n\n/**\n * Least time between two wake-up notifications of one store. A transaction that sends `NOTIFY` holds a\n * database-wide lock from its commit until the commit is flushed, so a notification per publishing\n * transaction made concurrent publishers commit one at a time.\n */\nconst NOTIFICATION_INTERVAL_MS = 10;\n\ninterface EventRow {\n readonly id: string;\n readonly type: string;\n readonly source: string;\n readonly key: string | null;\n readonly sequence: string | null;\n readonly payload: unknown;\n readonly headers: EventEnvelope['headers'];\n readonly correlation_id: string | null;\n readonly causation_id: string | null;\n readonly occurred_at: string;\n readonly handlers: readonly string[];\n}\n\ninterface DeliveryRow {\n readonly id: string;\n readonly event_id: string;\n readonly handler: string;\n readonly available_at: string;\n}\n\n/** What `#appendToExistingEvents` needs from the append that found existing events. */\ntype AppendToExistingEventsInput = {\n readonly plan: AppendPlan;\n readonly fresh: readonly PostgresRow[];\n readonly deliveries: readonly DeliveryRow[];\n readonly handlersByEvent: ReadonlyMap<string, string[]>;\n /** Grows by every event that turns out to be gone and is inserted again. */\n readonly insertedEventIds: Set<string>;\n readonly createdAt: string;\n readonly wakeAt: string | null;\n};\n\n/** appender */\nexport class PostgresAppend<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n this.#state = state;\n }\n\n /** Implements {@link PostgresEventStore.append}. */\n async append(\n transaction: TTransaction,\n { entries, now }: { readonly entries: readonly AppendEntry[]; readonly now: Date },\n ): Promise<AppendResult> {\n const plan = planAppend(entries);\n if (plan.events.length === 0) {\n return { appendedEventIds: [], duplicateEventIds: [], appendedDeliveryCount: 0 };\n }\n const createdAt = now.toISOString();\n const wakeAt = this.#wakeAt(plan.deliveries, { now, transaction });\n const handlersByEvent = handlersByEventOf(plan.deliveries);\n const fresh = await this.#insertFreshEvents(transaction, {\n plan,\n handlersByEvent,\n createdAt,\n wakeAt,\n });\n const insertedEventIds = new Set(\n fresh.filter((row) => row['inserted'] === true).map((row) => row['id'] as string),\n );\n let appendedDeliveryCount = readCount(fresh[0]!, 'deliveries');\n const remaining = plan.deliveries.filter(\n (delivery) => !insertedEventIds.has(delivery.event_id),\n );\n if (remaining.length > 0) {\n appendedDeliveryCount += await this.#appendToExistingEvents(transaction, {\n plan,\n fresh,\n deliveries: remaining,\n handlersByEvent,\n insertedEventIds,\n createdAt,\n wakeAt,\n });\n }\n return { ...splitOutcomes(plan, insertedEventIds), appendedDeliveryCount };\n }\n\n /** Runs the publishing statement that inserts the events not stored yet, with their deliveries. */\n async #insertFreshEvents(\n transaction: TTransaction,\n {\n plan,\n handlersByEvent,\n createdAt,\n wakeAt,\n }: {\n readonly plan: AppendPlan;\n readonly handlersByEvent: ReadonlyMap<string, string[]>;\n readonly createdAt: string;\n readonly wakeAt: string | null;\n },\n ): Promise<readonly PostgresRow[]> {\n const keyCounts = keyCountsOf(plan.events);\n return this.#state.query({\n sql: this.#state.statements.append.insertFreshEvents,\n parameters: [\n JSON.stringify(\n plan.events.map((event, ordinal) => ({\n ordinal,\n ...toEventRow(event, { sequence: null, handlers: handlersByEvent.get(event.id) ?? [] }),\n })),\n ),\n createdAt,\n JSON.stringify(plan.deliveries),\n JSON.stringify([...keyCounts].map(([key, count]) => ({ key, count }))),\n wakeAt,\n ],\n transaction,\n });\n }\n\n /** Locks the given events and returns the ids of those that still exist. */\n async #lockExistingEvents(\n transaction: TTransaction,\n existing: readonly EventRow[],\n ): Promise<Set<string>> {\n const locked = await this.#state.query({\n sql: this.#state.statements.append.lockExistingEvents,\n parameters: [JSON.stringify(existing.map((row) => row.id).sort())],\n transaction,\n });\n return new Set(locked.map((row) => row['id'] as string));\n }\n\n /**\n * The time the publishing statements notify the dispatchers for (deliveries due by then wake them),\n * or `null` for no notification. An append in a transaction of the caller's always notifies, at its\n * commit. In a transaction of this store, only the first append within {@link NOTIFICATION_INTERVAL_MS}\n * does; the others leave the wake-up to {@link #wakeAfterCommit}, which runs once their transaction\n * committed, so no committed delivery waits for the poll.\n */\n #wakeAt(\n deliveries: readonly DeliveryRow[],\n { now, transaction }: { readonly now: Date; readonly transaction: TTransaction },\n ): string | null {\n if (\n !this.#state.notifies ||\n !deliveries.some((delivery) => Date.parse(delivery.available_at) <= now.getTime())\n ) {\n return null;\n }\n const own = this.#state.ownTransactions.get(transaction);\n if (\n own !== undefined &&\n Date.now() - this.#state.lastNotificationAt < NOTIFICATION_INTERVAL_MS\n ) {\n own.wake = true;\n return null;\n }\n this.#state.lastNotificationAt = Date.now();\n return now.toISOString();\n }\n\n /**\n * Wakes the dispatchers for a committed transaction whose appends sent no notification: at once when\n * none was sent within {@link NOTIFICATION_INTERVAL_MS}, otherwise once when the interval ends. A\n * wake-up already scheduled covers this transaction too, since it is sent after this commit. Nothing is\n * sent once the store is closed or the `pg` pool behind it is ending: no dispatcher can be woken through\n * it then, and the deliveries are found by polling.\n */\n wakeAfterCommit(): void {\n if (this.#state.trailingNotification !== undefined || this.#state.closed) {\n return;\n }\n this.#state.trailingNotification = schedule(systemClock, {\n run: () => {\n this.#state.trailingNotification = undefined;\n if (this.#state.pool?.ending === true) {\n return;\n }\n this.#state.lastNotificationAt = Date.now();\n this.#state\n .query({ sql: this.#state.statements.append.notify, parameters: [] })\n .catch((error: unknown) => {\n this.#state.logger.error(\n `[PostgresAppend](wakeAfterCommit) Waking the dispatchers failed, they find the deliveries when they poll | error=${error instanceof Error ? error.message : String(error)}`,\n );\n });\n },\n delayMs: Math.max(0, this.#state.lastNotificationAt + NOTIFICATION_INTERVAL_MS - Date.now()),\n });\n }\n\n /**\n * Adds the deliveries of events the publishing statement found already stored. An event that already\n * exists may be getting the same new handler from another transaction at this very moment. Whoever\n * holds the event decides, so the freshness check of the insert sees what the other transaction\n * committed, even if its delivery has completed since. An existing event that a purge removed\n * meanwhile is inserted again (with the sequence reserved for it) instead of being skipped; its id is\n * added to `insertedEventIds`. Returns how many deliveries were inserted.\n */\n async #appendToExistingEvents(\n transaction: TTransaction,\n input: AppendToExistingEventsInput,\n ): Promise<number> {\n const { plan, fresh, deliveries, handlersByEvent, insertedEventIds, createdAt, wakeAt } = input;\n const sequences = new Map(\n fresh.map((row) => [row['id'] as string, row['sequence'] as string | null]),\n );\n const reinserted: string[] = [];\n let existing = plan.events\n .filter((event) => !insertedEventIds.has(event.id))\n .map((event) =>\n toEventRow(event, {\n sequence: sequences.get(event.id)!,\n handlers: handlersByEvent.get(event.id) ?? [],\n }),\n );\n while (existing.length > 0) {\n const locked = await this.#lockExistingEvents(transaction, existing);\n const gone = existing.filter((row) => !locked.has(row.id));\n if (gone.length > 0) {\n const inserted = await this.#state.query({\n sql: this.#state.statements.append.insertEvents,\n parameters: [JSON.stringify(gone), createdAt],\n transaction,\n });\n for (const row of inserted) {\n insertedEventIds.add(row['id'] as string);\n reinserted.push(row['id'] as string);\n }\n }\n existing = gone.filter((row) => !insertedEventIds.has(row.id));\n }\n const inserted = await this.#state.query({\n sql: this.#state.statements.append.insertDeliveries,\n parameters: [JSON.stringify(deliveries), createdAt, JSON.stringify(reinserted), wakeAt],\n transaction,\n });\n return inserted.length;\n }\n}\n\ninterface AppendPlan {\n /** First occurrence of every event id in the call, in entry order. */\n readonly events: readonly EventEnvelope[];\n readonly deliveries: readonly DeliveryRow[];\n /** One per entry: its event id, and whether an earlier entry of the call carried the same id. */\n readonly outcomes: ReadonlyArray<{ readonly eventId: string; readonly repeated: boolean }>;\n}\n\nfunction planAppend(entries: readonly AppendEntry[]): AppendPlan {\n const events: EventEnvelope[] = [];\n const deliveries: DeliveryRow[] = [];\n const outcomes: Array<{ eventId: string; repeated: boolean }> = [];\n const seenEventIds = new Set<string>();\n const seenDeliveries = new Set<string>();\n for (const { event, deliveries: newDeliveries } of entries) {\n const repeated = seenEventIds.has(event.id);\n seenEventIds.add(event.id);\n outcomes.push({ eventId: event.id, repeated });\n if (!repeated) {\n events.push(event);\n }\n for (const delivery of newDeliveries) {\n const identity = CompositeKey.of(event.id, delivery.handler);\n if (!seenDeliveries.has(identity)) {\n seenDeliveries.add(identity);\n deliveries.push({\n id: delivery.id,\n event_id: event.id,\n handler: delivery.handler,\n available_at: delivery.availableAt.toISOString(),\n });\n }\n }\n }\n return { events, deliveries, outcomes };\n}\n\nfunction toEventRow(\n event: EventEnvelope,\n {\n sequence,\n handlers,\n }: { readonly sequence: string | null; readonly handlers: readonly string[] },\n): EventRow {\n return {\n id: event.id,\n type: event.type,\n source: event.source,\n key: event.key,\n sequence,\n payload: event.payload,\n headers: event.headers,\n correlation_id: event.correlationId,\n causation_id: event.causationId,\n occurred_at: event.occurredAt.toISOString(),\n handlers,\n };\n}\n\n/** The handlers each event gets a delivery for, in delivery order. */\nfunction handlersByEventOf(deliveries: readonly DeliveryRow[]): Map<string, string[]> {\n const handlersByEvent = new Map<string, string[]>();\n for (const delivery of deliveries) {\n handlersByEvent.set(delivery.event_id, [\n ...(handlersByEvent.get(delivery.event_id) ?? []),\n delivery.handler,\n ]);\n }\n return handlersByEvent;\n}\n\n/** How many of the events carry each key: the sequences each key reserves. */\nfunction keyCountsOf(events: AppendPlan['events']): Map<string, number> {\n const keyCounts = new Map<string, number>();\n for (const event of events) {\n if (event.key !== null) {\n keyCounts.set(event.key, (keyCounts.get(event.key) ?? 0) + 1);\n }\n }\n return keyCounts;\n}\n\n/** Each entry's event id as appended (new and inserted by this call) or duplicate, in entry order. */\nfunction splitOutcomes(\n plan: AppendPlan,\n insertedEventIds: ReadonlySet<string>,\n): { appendedEventIds: string[]; duplicateEventIds: string[] } {\n const appendedEventIds: string[] = [];\n const duplicateEventIds: string[] = [];\n for (const { eventId, repeated } of plan.outcomes) {\n (!repeated && insertedEventIds.has(eventId) ? appendedEventIds : duplicateEventIds).push(\n eventId,\n );\n }\n return { appendedEventIds, duplicateEventIds };\n}\n","import { RelayBusError } from '@relaybus/core';\n\n/**\n * A claim was refused because giving back the deliveries of an earlier, failed\n * claim still fails. Claiming before that would take the owner's live lanes for\n * foreign ones; the next claim tries the reconciliation again.\n */\nexport class ReconcileFailedError extends RelayBusError {\n override name = 'ReconcileFailedError';\n override readonly code: string = 'RELAYBUS_POSTGRES_RECONCILE_FAILED';\n}\n","import { CompositeKey } from '@relaybus/core/internal';\nimport type { PostgresRow } from './executor.js';\n\n// Reading the rows of the claim statements: what they left behind, and their order.\n\n/** Whether the claim statement saw work it could not take: a takeover in progress, unexamined free lanes, or a stale snapshot. */\nexport function leftWorkBehind(row: PostgresRow): boolean {\n return (\n row['takeover_waiting'] === true ||\n row['unexamined_free_lanes'] === true ||\n row['stale'] === true\n );\n}\n\n/**\n * The first `limit` picks in due order, keeping only the lowest sequence of each (handler, key):\n * two statements that read at different moments may each have picked a head of the same key.\n */\nexport function keepKeyHeads(picked: readonly PostgresRow[], limit: number): PostgresRow[] {\n const seenKeys = new Set<string>();\n const kept = [...picked]\n .sort((left, right) => compareSequence(left, right))\n .filter((row) => {\n if (row['delivery_key'] === null) {\n return true;\n }\n const group = CompositeKey.of(row['handler'] as string, row['delivery_key'] as string);\n return !seenKeys.has(group) && Boolean(seenKeys.add(group));\n });\n kept.sort(compareDue);\n return kept.slice(0, limit);\n}\n\nfunction compareSequence(left: PostgresRow, right: PostgresRow): number {\n const first = sequenceOf(left);\n const second = sequenceOf(right);\n return Number(first > second) - Number(first < second);\n}\n\n/** The key sequence of a picked row; 0 for an unkeyed delivery, which has none. */\nfunction sequenceOf(row: PostgresRow): bigint {\n return BigInt((row['sequence'] as string | null) ?? 0);\n}\n\nexport function compareDue(left: PostgresRow, right: PostgresRow): number {\n return (\n compareText(left['due_at'] as string, right['due_at'] as string) ||\n compareText(left['delivery_id'] as string, right['delivery_id'] as string)\n );\n}\n\nfunction compareText(left: string, right: string): number {\n return Number(left > right) - Number(left < right);\n}\n","import { type ClaimRequest, type ClaimedDelivery } from '@relaybus/core';\nimport { OwnerSerializedClaims } from '@relaybus/core/internal';\nimport { ReconcileFailedError } from './errors.js';\nimport type { PostgresParameter, PostgresRow } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { compareDue, keepKeyHeads, leftWorkBehind } from './claim-rows.js';\nimport { mapClaimedDelivery, parseLeaseToken, readCount } from './row-mapping.js';\n\n/** Lanes a claim takes in its first round; every further round takes twice as many. */\nconst INITIAL_LANES_PER_ROUND = 4;\n\n/** Attempts of the held-lane claim before a stale statement is given up for this call (a later claim finds the work). */\nconst MAXIMUM_STALE_CLAIM_ATTEMPTS = 3;\n\n/**\n * Claims for {@link PostgresEventStore.claim}, one claim per owner at a time: held lanes first\n * when the owner is draining a backlog there, then free lanes round by round. A claim that fails\n * after the database may have recorded it reconciles the owner's lanes.\n */\nexport class PostgresClaims<TTransaction> extends OwnerSerializedClaims {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n super();\n this.#state = state;\n }\n\n protected async claimInTurn(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n await this.#assertReconciled(request.leaseOwner);\n // An owner whose last claim was filled from the lanes it held is draining a backlog there: those\n // lanes are asked first.\n const heldFirst = this.#state.drainingOwners.has(request.leaseOwner);\n let rows = await this.#claimFirst(request, heldFirst);\n const heldLanes = new Set(JSON.parse(rows[0]!['examined_lanes'] as string) as number[]);\n const claimed = this.#takeClaimed(rows, request.leaseOwner);\n if (heldFirst && claimed.length < request.limit && rows[0]!['stale'] !== true) {\n const freeRows = await this.#claimFreeLanesAfterHeld(request, claimed);\n if (freeRows === undefined) {\n return this.#handOutInDueOrder(claimed, { request, heldLanes });\n }\n rows = freeRows;\n }\n if (claimed.length < request.limit && leftWorkBehind(rows[0]!)) {\n await this.#claimMoreLanes(request, claimed);\n }\n return this.#handOutInDueOrder(claimed, { request, heldLanes });\n }\n\n /** Reconciles first when an earlier reconciliation of `owner` failed; refuses to claim while it still fails. */\n async #assertReconciled(owner: string): Promise<void> {\n if (this.#state.unreconciled.has(owner) && !(await this.#reconcile(owner))) {\n // The generation moved on and the lanes were not told: claiming now would take the owner's live lanes for foreign ones.\n throw new ReconcileFailedError(\n `[PostgresEventStore](claim) Giving back unreturned deliveries still fails, so no claim is made | owner=${owner}`,\n );\n }\n }\n\n /** The first claim statement: from the held lanes only when `heldFirst`, else from held and free lanes. */\n async #claimFirst(request: ClaimRequest, heldFirst: boolean): Promise<readonly PostgresRow[]> {\n try {\n return await this.#claimInOneStatement(\n request,\n heldFirst\n ? this.#state.statements.lanes.claimHeldLanes\n : this.#state.statements.lanes.claimLanes,\n );\n } catch (error) {\n await this.#reconcile(request.leaseOwner);\n throw error;\n }\n }\n\n /**\n * After a held-lanes claim came up short: claims the rest from held and free lanes and adds it to\n * `claimed`. Returns the statement's rows, or undefined when it failed after something was claimed\n * already, which is then handed out as it is.\n */\n async #claimFreeLanesAfterHeld(\n request: ClaimRequest,\n claimed: PostgresRow[],\n ): Promise<readonly PostgresRow[] | undefined> {\n let rows: readonly PostgresRow[];\n try {\n rows = await this.#claimInOneStatement(\n { ...request, limit: request.limit - claimed.length },\n this.#state.statements.lanes.claimLanes,\n );\n } catch (error) {\n await this.#reconcile(request.leaseOwner);\n if (claimed.length === 0) {\n this.#state.drainingOwners.delete(request.leaseOwner);\n throw error;\n }\n this.#state.logger.error(\n `[PostgresClaims](claimFreeLanesAfterHeld) Claiming from free lanes failed, returning the deliveries already claimed | claimed=${claimed.length} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n return undefined;\n }\n claimed.push(...this.#takeClaimed(rows, request.leaseOwner));\n return rows;\n }\n\n /** Takes more lanes round by round and adds what they give to `claimed`; keeps what was claimed when that fails. */\n async #claimMoreLanes(request: ClaimRequest, claimed: PostgresRow[]): Promise<void> {\n try {\n const more = await this.#claimMore(request, claimed.length);\n this.#handOut(more, request.leaseOwner);\n claimed.push(...more);\n } catch (error) {\n await this.#reconcile(request.leaseOwner);\n if (claimed.length === 0) {\n throw error;\n }\n this.#state.logger.error(\n `[PostgresClaims](claimMoreLanes) Taking more lanes failed, returning the deliveries already claimed | claimed=${claimed.length} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /** The deliveries a claim statement picked, registered as handed out to `leaseOwner`. */\n #takeClaimed(rows: readonly PostgresRow[], leaseOwner: string): PostgresRow[] {\n const claimed = rows.filter((row) => row['delivery_id'] !== null);\n this.#forgetFinished(rows[0]!, { leaseOwner, claimed });\n this.#handOut(claimed, leaseOwner);\n return claimed;\n }\n\n #handOutInDueOrder(\n claimed: PostgresRow[],\n {\n request,\n heldLanes,\n }: { readonly request: ClaimRequest; readonly heldLanes: ReadonlySet<number> },\n ): ClaimedDelivery[] {\n if (\n claimed.length >= request.limit &&\n claimed.every((row) => heldLanes.has(readCount(row, 'lane')))\n ) {\n this.#state.drainingOwners.add(request.leaseOwner);\n } else {\n this.#state.drainingOwners.delete(request.leaseOwner);\n }\n // The steps pick from different lanes; hand the batch out in due order, like a single query would.\n claimed.sort(compareDue);\n return claimed.map((row) => mapClaimedDelivery(row, request.leaseExpiresAt));\n }\n\n /**\n * Runs `statement` (`LaneStatements.claimLanes` or its held-lane form), again when it reports that it waited for a lane lock and\n * read deliveries with an older snapshot than the lane it got. A held lane is only locked by an\n * operation of its own owner (another claim, a reschedule), so a few attempts are enough.\n */\n async #claimInOneStatement(\n request: ClaimRequest,\n statement: string,\n ): Promise<readonly PostgresRow[]> {\n const parameters = [\n request.now.toISOString(),\n JSON.stringify(request.handlers),\n request.limit,\n request.leaseOwner,\n request.leaseExpiresAt.toISOString(),\n this.#generation(request.leaseOwner).toString(),\n ];\n let rows = await this.#state.query({ sql: statement, parameters });\n for (\n let attempt = 1;\n attempt < MAXIMUM_STALE_CLAIM_ATTEMPTS && rows[0]!['stale'] === true;\n attempt += 1\n ) {\n rows = await this.#state.query({ sql: statement, parameters });\n }\n return rows;\n }\n\n /**\n * Second step of {@link PostgresEventStore.claim}, in one transaction: takes free lanes a few at a\n * time, lanes to take over included (their lost attempts are charged first), and records the batch.\n * `alreadyClaimed` deliveries of the first step are in flight, so they are not picked again.\n */\n async #claimMore(request: ClaimRequest, alreadyClaimed: number): Promise<PostgresRow[]> {\n const now = request.now.toISOString();\n const leaseExpiresAt = request.leaseExpiresAt.toISOString();\n const handlers = JSON.stringify(request.handlers);\n // Taken before the transaction starts: a transaction that reaches the server late keeps its generation.\n const generation = this.#generation(request.leaseOwner).toString();\n return this.#state.executor.transaction(async (transaction) => {\n const claimed: PostgresRow[] = [];\n const remaining = (): number => request.limit - alreadyClaimed - claimed.length;\n const takenLanes = new Set<number>();\n for (let laneCount = INITIAL_LANES_PER_ROUND; remaining() > 0;) {\n const taken = await this.#state.query({\n sql: this.#state.statements.lanes.takeFreeLanes,\n parameters: [now, handlers, laneCount, request.leaseOwner, leaseExpiresAt, generation],\n transaction,\n });\n if (taken.length === 0) {\n break;\n }\n const lanes = taken.map((row) => readCount(row, 'lane'));\n for (const lane of lanes) {\n takenLanes.add(lane);\n }\n claimed.push(\n ...(await this.#pickDeliveries(\n [now, handlers, remaining(), JSON.stringify(lanes)],\n transaction,\n )),\n );\n laneCount *= 2;\n }\n await this.#recordClaim(claimed, { lanes: takenLanes, request, transaction });\n return claimed;\n });\n }\n\n /**\n * The generation of the owner's claim statements. It only grows, also across restarts (it starts at the\n * clock), and a reconciliation moves it up, which fences off every earlier statement still in flight.\n */\n #generation(owner: string, advance = false): bigint {\n const current = this.#state.generations.get(owner) ?? BigInt(Date.now());\n const next = advance\n ? current + GENERATION_STEP > BigInt(Date.now())\n ? current + GENERATION_STEP\n : BigInt(Date.now())\n : current;\n this.#state.generations.set(owner, next);\n return next;\n }\n\n /** Remembers the claims handed to the caller of `claim` until they are settled. */\n #handOut(rows: readonly PostgresRow[], leaseOwner: string): void {\n for (const row of rows) {\n const claim = mapClaimedDelivery(row, new Date(0));\n this.#state.handedOut.register(claim, {\n owner: leaseOwner,\n deliveryId: claim.deliveryId,\n ...parseLeaseToken(claim.leaseToken)!,\n });\n }\n }\n\n /**\n * Drops the registrations of the owner's held lanes whose delivery no longer runs there\n * (completed inside the caller's transaction, deleted, or listed no more). Registrations of\n * lanes this claim did not see stay: their tokens may still be valid.\n */\n #forgetFinished(\n row: PostgresRow,\n {\n leaseOwner,\n claimed,\n }: { readonly leaseOwner: string; readonly claimed: readonly PostgresRow[] },\n ): void {\n // Lanes the statement freed are examined too: nothing runs there any more.\n const heldLanes = new Set(JSON.parse(row['examined_lanes'] as string) as number[]);\n const running = new Set([\n ...(JSON.parse(row['running_ids'] as string) as string[]),\n ...claimed.map((picked) => picked['delivery_id'] as string),\n ]);\n this.#state.handedOut.forgetWhere(\n (entry) =>\n entry.owner === leaseOwner && heldLanes.has(entry.lane) && !running.has(entry.deliveryId),\n );\n }\n\n /**\n * After a claim failed, possibly after the database recorded its batch: gives back the recorded\n * deliveries that were never handed out, keeping exactly the claims handed out and not settled.\n * A failure is remembered and retried before the owner's next claim: other deliveries keep\n * renewing the lane, so an unreturned one would otherwise never be recovered.\n */\n async #reconcile(leaseOwner: string): Promise<boolean> {\n // Claim statements of the generation before are fenced off by the new one.\n const generation = this.#generation(leaseOwner, true);\n const handedOut = this.#state.handedOut\n .entriesOf(leaseOwner)\n .map(({ deliveryId, lane, epoch, claims }) => ({ id: deliveryId, lane, epoch, claims }));\n try {\n await this.#state.query({\n sql: this.#state.statements.claim.reconcileClaims,\n parameters: [leaseOwner, JSON.stringify(handedOut), generation.toString()],\n });\n this.#state.unreconciled.delete(leaseOwner);\n return true;\n } catch (error) {\n this.#state.unreconciled.add(leaseOwner);\n this.#state.logger.error(\n `[PostgresClaims](reconcile) Giving back unreturned deliveries failed, it is retried before the next claim | owner=${leaseOwner} | error=${error instanceof Error ? error.message : String(error)}`,\n );\n return false;\n }\n }\n\n /** Fast claim, then the slow one when the fast window was full of blocked followers. */\n async #pickDeliveries(\n parameters: readonly PostgresParameter[],\n transaction: TTransaction,\n ): Promise<PostgresRow[]> {\n const limit = parameters[2] as number;\n const fastRows = await this.#state.query({\n sql: this.#state.statements.claim.claim,\n parameters,\n transaction,\n });\n const picked = fastRows.filter((row) => row['delivery_id'] !== null);\n if (picked.length < limit && fastRows[0]!['window_saturated'] === true) {\n const slowRows = await this.#state.query({\n sql: this.#state.statements.claim.claimBehindBlockedKeys,\n parameters,\n transaction,\n });\n // Nothing was written, so the slow statement sees the fast statement's picks again.\n // Both pick at most the head of a key, so the union is still one delivery per key.\n const pickedIds = new Set(picked.map((row) => row['delivery_id']));\n picked.push(\n ...slowRows.filter(\n (row) => row['delivery_id'] !== null && !pickedIds.has(row['delivery_id']),\n ),\n );\n // The two statements read at different moments: a dead letter requeued in between can put a key's\n // predecessor in one result and its successor in the other. Only the lowest of a key may run.\n return keepKeyHeads(picked, limit);\n }\n return picked;\n }\n\n /** Writes the picked ids into their lane rows and frees the lanes that picked nothing. */\n async #recordClaim(\n claimed: readonly PostgresRow[],\n {\n lanes,\n request,\n transaction,\n }: {\n readonly lanes: ReadonlySet<number>;\n readonly request: ClaimRequest;\n readonly transaction: TTransaction;\n },\n ): Promise<void> {\n const idsByLane = new Map<number, string[]>();\n for (const row of claimed) {\n const lane = readCount(row, 'lane');\n idsByLane.set(lane, [...(idsByLane.get(lane) ?? []), row['delivery_id'] as string]);\n }\n const idleLanes = [...lanes].filter((lane) => !idsByLane.has(lane));\n if (idsByLane.size === 0 && idleLanes.length === 0) {\n return;\n }\n await this.#state.query({\n sql: this.#state.statements.claim.recordClaim,\n parameters: [\n JSON.stringify([...idsByLane].map(([lane, ids]) => ({ lane, ids }))),\n JSON.stringify(idleLanes),\n request.leaseOwner,\n request.leaseExpiresAt.toISOString(),\n ],\n transaction,\n });\n }\n}\n\n/** How far a reconciliation moves the generation at least. */\nconst GENERATION_STEP = 1n;\n","import { type LeaseReference } from '@relaybus/core';\nimport {\n DeliveryLeaseIdentity,\n LeaseSettlement,\n type LeaseChange,\n type LeaseExtension,\n} from '@relaybus/core/internal';\nimport type { PostgresParameter } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { parseLeaseToken, readCount, type LaneLease } from './row-mapping.js';\n\n/**\n * Ends and renews claims for {@link PostgresEventStore}: every statement is fenced by the lane\n * lease the token names (lane, epoch and claim generation).\n */\nexport class PostgresCompletion<TTransaction> extends LeaseSettlement<LaneLease> {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n super();\n this.#state = state;\n }\n\n /** Implements {@link PostgresEventStore.complete}. */\n async complete(\n lease: LeaseReference,\n { now, transaction }: { readonly now: Date; readonly transaction?: TTransaction | undefined },\n ): Promise<boolean> {\n return (await this.#completeLeases([lease], { now, transaction }))[0]!;\n }\n\n /** Implements {@link PostgresEventStore.completeMany}. */\n completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]> {\n return this.#completeLeases(leases, { now, transaction: undefined });\n }\n\n /** A lease this store issued; any other token cannot be held. */\n protected findHeld(lease: LeaseReference): LaneLease | undefined {\n return parseLeaseToken(lease.leaseToken);\n }\n\n protected writeExtension(\n held: LaneLease,\n { lease, leaseExpiresAt }: LeaseExtension,\n ): Promise<boolean> {\n return this.#changed(this.#state.statements.completion.extendLease, [\n ...fenceOf(lease, held),\n leaseExpiresAt.toISOString(),\n ]);\n }\n\n protected writeChange(held: LaneLease, { lease, change }: LeaseChange): Promise<boolean> {\n const { completion } = this.#state.statements;\n const fence = fenceOf(lease, held);\n if (change.kind === 'reschedule') {\n return this.#changed(completion.reschedule, [\n ...fence,\n change.availableAt.toISOString(),\n JSON.stringify(change.error),\n change.now.toISOString(),\n ]);\n }\n if (change.kind === 'bury') {\n return this.#changed(completion.bury, [\n ...fence,\n JSON.stringify(change.error),\n change.now.toISOString(),\n ]);\n }\n return this.#changed(completion.release, [...fence, change.now.toISOString()]);\n }\n\n /** Forgets a handed-out lease once the store answered about it (any answer: the claim is over or fenced out). */\n protected forgetHandedOut(lease: LeaseReference): void {\n this.#state.handedOut.forget(lease);\n }\n\n async #changed(sql: string, parameters: readonly PostgresParameter[]): Promise<boolean> {\n const rows = await this.#state.query({ sql, parameters });\n return readCount(rows[0]!, 'count') > 0;\n }\n\n /**\n * Deletes the delivery of every lease that is still the current claim of its\n * delivery. Returns one flag per lease, in order. Results are matched to leases\n * by position, so two leases of one delivery (a stale and a current one) get\n * their own answers; a lease listed twice completes once, at its first position.\n */\n async #completeLeases(\n leases: readonly LeaseReference[],\n { now, transaction }: { readonly now: Date; readonly transaction: TTransaction | undefined },\n ): Promise<boolean[]> {\n const issued = issuedLeases(leases);\n const completed = new Set<number>();\n if (issued.length > 0) {\n const rows = await this.#state.query({\n sql: this.#state.statements.completion.complete,\n parameters: [JSON.stringify(issued), now.toISOString()],\n transaction,\n });\n for (const row of rows) {\n completed.add(readCount(row, 'ord'));\n }\n }\n if (transaction === undefined) {\n // Inside the caller's transaction the completion is only provisional: it may roll back and retry.\n for (const lease of leases) {\n this.#state.handedOut.forget(lease);\n }\n }\n return leases.map((_, ord) => completed.has(ord));\n }\n}\n\n/** The first parameters of every fenced statement: the delivery and the lane lease of its claim. */\nfunction fenceOf(lease: LeaseReference, held: LaneLease): PostgresParameter[] {\n return [lease.deliveryId, held.lane, held.epoch, held.claims];\n}\n\n/** The leases this store can have issued, each once, with their position in `leases`. */\nfunction issuedLeases(\n leases: readonly LeaseReference[],\n): Array<{ ord: number; id: string } & LaneLease> {\n const issued: Array<{ ord: number; id: string } & LaneLease> = [];\n const seen = new Set<string>();\n leases.forEach((lease, ord) => {\n const held = parseLeaseToken(lease.leaseToken);\n const identity = DeliveryLeaseIdentity.of(lease.deliveryId, lease.leaseToken);\n if (held !== undefined && !seen.has(identity)) {\n seen.add(identity);\n issued.push({ ord, id: lease.deliveryId, ...held });\n }\n });\n return issued;\n}\n","import { Client, type ClientConfig } from 'pg';\n\n/**\n * The connections the store opened itself: every connection of the pool it created from\n * `connectionString`, and the connections it listens for notifications on. A shutdown that runs past\n * its deadline destroys them, so a query that hangs (a lock wait, an unreachable server) fails at\n * once instead of holding `stop` and the process. Pools the application passed in are never tracked.\n */\nexport class OwnedConnections {\n readonly #clients = new Set<Client>();\n\n /**\n * The `Client` class for a pool the store creates: every connection is tracked from the moment it\n * is created, so one still connecting or authenticating is destroyed too.\n */\n clientClass(): typeof Client {\n // eslint-disable-next-line @typescript-eslint/no-this-alias -- the class below needs the tracker\n const owned = this;\n return class OwnedClient extends Client {\n constructor(config?: string | ClientConfig) {\n super(config);\n owned.track(this);\n }\n };\n }\n\n /** Tracks one connection until it ends. */\n track(client: Client): void {\n this.#clients.add(client);\n client.once('end', () => this.#clients.delete(client));\n }\n\n /**\n * Destroys the socket of every tracked connection. Its queries fail with \"Connection terminated\"\n * and the pool drops it. The server ends the session when it next talks to the client.\n */\n destroyAll(): void {\n for (const client of this.#clients) {\n // A destroyed connection reports an error; nobody may be listening on a checked-out one.\n client.on('error', () => undefined);\n client.connection.stream.destroy();\n }\n this.#clients.clear();\n }\n}\n","import {\n type DeliveryQuery,\n type DeliveryRecord,\n type EventStoreStatistics,\n type PurgeRequest,\n type PurgeResult,\n} from '@relaybus/core';\nimport type { PostgresRow } from './executor.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { mapDeliveryRecord, mapOldestDueAt, readCount } from './row-mapping.js';\n\n/** maintenance */\nexport class PostgresMaintenance<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n\n constructor(state: PostgresStoreState<TTransaction>) {\n this.#state = state;\n }\n\n /** Implements {@link PostgresEventStore.relinquish}. */\n async relinquish(leaseOwner: string): Promise<void> {\n await this.#state.query({\n sql: this.#state.statements.claim.relinquish,\n parameters: [leaseOwner],\n });\n }\n\n /** Implements {@link PostgresEventStore.listDeliveries}. */\n async listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n const statement = this.#state.statements.queries.listDeliveries(query);\n const rows = await this.#state.executor.query(statement.sql, statement.parameters);\n return rows.map(mapDeliveryRecord);\n }\n\n /** Implements {@link PostgresEventStore.requeue}. */\n async requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n const rows = await this.#state.query({\n sql: this.#state.statements.queries.requeue,\n parameters: [JSON.stringify(deliveryIds), now.toISOString()],\n });\n return readCount(rows[0]!, 'count');\n }\n\n /** Implements {@link PostgresEventStore.statistics}. */\n async statistics(now: Date): Promise<EventStoreStatistics> {\n const stored: Record<string, number> = { pending: 0, dead: 0, completed: 0 };\n for (const row of await this.#state.query({\n sql: this.#state.statements.queries.countByStatus,\n parameters: [],\n })) {\n stored[row['status'] as string] = readCount(row, 'count');\n }\n const [running] = await this.#state.query({\n sql: this.#state.statements.queries.countRunning,\n parameters: [],\n });\n const processing = readCount(running!, 'count');\n let completed = stored['completed']!;\n if (this.#state.completionHistory) {\n const [history] = await this.#state.query({\n sql: this.#state.statements.queries.countCompletionHistory,\n parameters: [],\n });\n completed += readCount(history!, 'count');\n }\n const oldestDue = await this.#state.query({\n sql: this.#state.statements.queries.oldestDue,\n parameters: [now.toISOString()],\n });\n return {\n // The counts come from separate statements; a delivery that finishes in between must not make this negative.\n pending: Math.max(0, stored['pending']! - processing),\n processing,\n completed,\n dead: stored['dead']!,\n oldestDueAt: mapOldestDueAt(oldestDue),\n };\n }\n\n /** Implements {@link PostgresEventStore.purge}. */\n async purge(request: PurgeRequest): Promise<PurgeResult> {\n const total = { deletedDeliveries: 0, deletedEvents: 0 };\n const batches = this.#purgeBatchPlan(request);\n for (const [sql, cutoff, deleteOrphans] of batches) {\n if (cutoff === undefined) {\n continue;\n }\n let deletedInBatch = this.#state.purgeBatchSize;\n while (deletedInBatch === this.#state.purgeBatchSize) {\n const batch = await this.#purgeBatch(sql, { cutoff, deleteOrphans });\n deletedInBatch = batch.deletedDeliveries;\n total.deletedDeliveries += batch.deletedDeliveries;\n total.deletedEvents += batch.deletedEvents;\n }\n }\n total.deletedEvents += await this.#purgeAllOrphanEvents(request);\n return total;\n }\n\n /** The purge statements to run in order: SQL, cutoff (undefined skips it) and the orphan-event delete. */\n #purgeBatchPlan(request: PurgeRequest): Array<[string, Date | undefined, string]> {\n const batches: Array<[string, Date | undefined, string]> = [\n [\n this.#state.statements.purge.purgeCompletedBatch(),\n request.completedBefore,\n this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n ],\n [\n this.#state.statements.purge.purgeDeadBatch(),\n request.deadBefore,\n this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n ],\n ];\n if (this.#state.completionHistory) {\n batches.push([\n this.#state.statements.purge.purgeCompletionHistoryBatch(),\n request.completedBefore,\n this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n ]);\n }\n return batches;\n }\n\n /** Removes the events left without deliveries, in two passes; returns how many events were deleted. */\n async #purgeAllOrphanEvents(request: PurgeRequest): Promise<number> {\n let deletedEvents = 0;\n const orphanCutoff = [request.completedBefore, request.deadBefore]\n .filter((cutoff) => cutoff !== undefined)\n .sort((first, second) => first.getTime() - second.getTime())[0];\n if (orphanCutoff !== undefined) {\n deletedEvents += await this.#purgeOrphanEvents(\n this.#state.statements.purge.lockOrphanEventsBatch,\n {\n deleteStatement: this.#state.statements.purge.deleteOrphanEventsWithoutCompletion,\n cutoff: orphanCutoff,\n recheckCutoff: false,\n },\n );\n }\n if (request.completedBefore !== undefined) {\n deletedEvents += await this.#purgeOrphanEvents(\n this.#state.statements.purge.lockCompletedOrphanEventsBatch,\n {\n deleteStatement: this.#state.statements.purge.deleteExpiredCompletedOrphanEvents,\n cutoff: request.completedBefore,\n recheckCutoff: true,\n },\n );\n }\n return deletedEvents;\n }\n\n async #purgeOrphanEvents(\n lockStatement: string,\n {\n deleteStatement,\n cutoff,\n recheckCutoff,\n }: { readonly deleteStatement: string; readonly cutoff: Date; readonly recheckCutoff: boolean },\n ): Promise<number> {\n let deletedEvents = 0;\n let removedInBatch = this.#state.purgeBatchSize;\n while (removedInBatch === this.#state.purgeBatchSize) {\n removedInBatch = await this.#state.executor.transaction(async (transaction) => {\n const locked = await this.#state.query({\n sql: lockStatement,\n parameters: [cutoff.toISOString(), this.#state.purgeBatchSize],\n transaction,\n });\n const ids = JSON.stringify(locked.map((row: PostgresRow) => row['id'] as string));\n const removed = await this.#state.query({\n sql: deleteStatement,\n parameters: recheckCutoff ? [ids, cutoff.toISOString()] : [ids],\n transaction,\n });\n return readCount(removed[0]!, 'count');\n });\n deletedEvents += removedInBatch;\n }\n return deletedEvents;\n }\n\n async #purgeBatch(\n sql: string,\n { cutoff, deleteOrphans }: { readonly cutoff: Date; readonly deleteOrphans: string },\n ): Promise<{ deletedDeliveries: number; deletedEvents: number }> {\n return this.#state.executor.transaction(async (transaction) => {\n const deleted = await this.#state.query({\n sql,\n parameters: [cutoff.toISOString(), this.#state.purgeBatchSize],\n transaction,\n });\n if (deleted.length === 0) {\n return { deletedDeliveries: 0, deletedEvents: 0 };\n }\n const eventIds = JSON.stringify([\n ...new Set(deleted.map((row) => row['event_id'] as string)),\n ]);\n const locked = await this.#state.query({\n sql: this.#state.statements.purge.lockEvents,\n parameters: [eventIds],\n transaction,\n });\n const removed = await this.#state.query({\n sql: deleteOrphans,\n parameters: [JSON.stringify(locked.map((row: PostgresRow) => row['id'] as string))],\n transaction,\n });\n return { deletedDeliveries: deleted.length, deletedEvents: readCount(removed[0]!, 'count') };\n });\n }\n}\n","import { resolvePostgresNames, type PostgresSchemaOptions } from './names.js';\nimport { type PostgresStoreState } from './postgres-store-state.js';\nimport { upgradePayloadToJson } from './schema.js';\n\n/** What the catalog says about the schema (see {@link SetupStatements.schemaCurrent}). */\ntype SchemaState = {\n /** The lane table carries the schema marker, which 0.4.0 writes too. */\n readonly marked: boolean;\n /** The payload and headers columns are `json`. */\n readonly payloadJson: boolean;\n};\n\n/**\n * Brings the schema to the current statements under the setup lock (see\n * {@link PostgresEventStore.setup}): first the payload conversion in a transaction of its own, then\n * the other statements, unless the schema carries the marker, which 0.4.0 writes too and which then\n * needs only the conversion.\n */\nexport class PostgresSetup<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n /** The conversion of `jsonb` payload columns. */\n readonly #payloadUpgrade: string;\n\n constructor(state: PostgresStoreState<TTransaction>, options: PostgresSchemaOptions) {\n this.#state = state;\n this.#payloadUpgrade = upgradePayloadToJson(resolvePostgresNames(options));\n }\n\n /** Implements {@link PostgresEventStore.setup}. */\n async run(): Promise<void> {\n // DDL on a current schema would still lock the tables, and those locks deadlock with running claims.\n if (isCurrent(await this.#schemaState())) {\n return;\n }\n await this.#underSetupLock(async (transaction) => {\n await this.#run(this.#payloadUpgrade, transaction);\n });\n await this.#underSetupLock(async (transaction, schema) => {\n // A 0.4.0 setup may have created the schema since the first step released the lock.\n if (schema.marked) {\n await this.#run(this.#payloadUpgrade, transaction);\n return;\n }\n for (const statement of this.#state.schemaStatements) {\n await this.#run(statement, transaction);\n }\n });\n }\n\n /**\n * Runs `work` in a transaction under the setup lock, unless the schema became current. The\n * payload conversion goes first in a transaction of its own, so it holds no other table lock\n * while it waits for the event table (a completion locks deliveries before the event rows).\n */\n async #underSetupLock(\n work: (transaction: TTransaction, schema: SchemaState) => Promise<void>,\n ): Promise<void> {\n await this.#state.executor.transaction(async (transaction) => {\n await this.#state.executor.query(\n this.#state.statements.setup.setupLock,\n [this.#state.setupLockKey],\n transaction,\n );\n const schema = await this.#schemaState(transaction);\n if (!isCurrent(schema)) {\n await work(transaction, schema);\n }\n });\n }\n\n async #run(statement: string, transaction: TTransaction): Promise<void> {\n await this.#state.executor.query(statement, [], transaction);\n }\n\n async #schemaState(transaction?: TTransaction): Promise<SchemaState> {\n const rows = await this.#state.executor.query(\n this.#state.statements.setup.schemaCurrent,\n [this.#state.schemaMarker],\n transaction,\n );\n return { marked: rows[0]!['marked'] === true, payloadJson: rows[0]!['payload_json'] === true };\n }\n}\n\n/** Current: the marker is there and the payload columns are converted. */\nfunction isCurrent(schema: SchemaState): boolean {\n return schema.marked && schema.payloadJson;\n}\n","import { ConfigurationError, type RelayBusLogger } from '@relaybus/core';\nimport { PositiveInteger } from '@relaybus/core/internal';\nimport type { Pool, PoolClient, PoolConfig } from 'pg';\nimport type { PostgresExecutor, PostgresQueryOptions } from './executor.js';\nimport type { PostgresSchemaOptions } from './names.js';\n\n/** Options shared by every way of connecting. */\nexport interface PostgresEventStoreSettings extends PostgresSchemaOptions {\n /**\n * Maximum deliveries deleted per transaction by `purge`. Smaller batches\n * hold row locks for less time; `purge` keeps going until nothing is left.\n * Default 1000.\n */\n readonly purgeBatchSize?: number;\n /**\n * Receives errors of idle connections in a pool the store creates itself\n * (database failover, `pg_terminate_backend`, network resets). Default\n * `console`. A pool you pass in is yours: attach `pool.on('error', ...)` to\n * it, otherwise `pg` raises an unhandled `error` event and the process exits.\n */\n readonly logger?: RelayBusLogger;\n /**\n * Send the statements the store repeats (publish, claim, complete, renew) as named prepared\n * statements, so each connection parses and plans their text once instead of on every call. Default\n * `true`. Set `false` behind a pooler in transaction mode that does not keep prepared statements per\n * client (PgBouncer before 1.21, or 1.21+ with `max_prepared_statements = 0`). Left on there, the\n * first statement that lands on another server session fails once, then the store stops preparing\n * and logs a warning. Only executors that support it prepare (`PgExecutor`, the default); the\n * other adapters send every statement unprepared.\n */\n readonly preparedStatements?: boolean;\n /**\n * How dispatchers in other processes learn about new deliveries.\n * - `'notify'` (default): a publishing transaction sends `NOTIFY` (at most one per 10 ms per store,\n * the rest merged into one trailing notification after the commit) and each dispatcher listens\n * with `LISTEN` on a connection of its own, so a delivery is picked up within milliseconds.\n * - `'poll'`: no `NOTIFY`, no listening connection. Other processes find new deliveries when they\n * poll (`dispatcher.pollInterval`, default 1 s); a dispatcher in the publishing process is still\n * woken at once. Use it behind a pooler in transaction mode, where `LISTEN` does not work.\n */\n readonly wakeUp?: PostgresWakeUp;\n}\n\n/** See {@link PostgresEventStoreSettings.wakeUp}. */\nexport type PostgresWakeUp = 'notify' | 'poll';\n\nconst WAKE_UPS: readonly PostgresWakeUp[] = ['notify', 'poll'];\n\n/** Use an existing `pg` pool. The store never closes it. */\nexport interface PostgresPoolOptions extends PostgresEventStoreSettings {\n readonly pool: Pool;\n readonly connectionString?: never;\n readonly poolConfig?: never;\n readonly executor?: never;\n}\n\n/** Let the store create (and on `close()` end) its own `pg` pool. */\nexport interface PostgresConnectionOptions extends PostgresEventStoreSettings {\n readonly connectionString: string;\n /** Extra `pg` pool settings, for example `max`. */\n readonly poolConfig?: Omit<PoolConfig, 'connectionString'>;\n readonly pool?: never;\n readonly executor?: never;\n}\n\n/** Use another database library through an adapter. The store never closes it. */\nexport interface PostgresExecutorOptions<TTransaction> extends PostgresEventStoreSettings {\n readonly executor: PostgresExecutor<TTransaction>;\n /**\n * Optional `pg` pool on the same database, for example the one an ORM's `pg` driver adapter uses\n * (`new PrismaPg(pool)`, Kysely's `PostgresDialect`, Drizzle's `node-postgres`). The store never\n * closes it. With it:\n * - the statements the store sends outside a transaction (the dispatcher's claims, completions and\n * lease renewals, maintenance) run on it as prepared statements (`preparedStatements`), which ORM\n * raw queries cannot do; statements in a transaction still go through `executor`;\n * - with `wakeUp: 'notify'` the store listens for wake-ups with its connection settings, so a\n * delivery published in an ORM transaction is dispatched right after that transaction commits,\n * instead of after a fixed delay or the next poll.\n */\n readonly pool?: Pool;\n readonly connectionString?: never;\n readonly poolConfig?: never;\n}\n\nexport type PostgresEventStoreOptions<TTransaction = PoolClient> =\n PostgresPoolOptions | PostgresConnectionOptions | PostgresExecutorOptions<TTransaction>;\n\nconst DEFAULT_PURGE_BATCH_SIZE = 1_000;\n\n/** Validates the options that are not names, in declaration order. */\nexport function resolveStoreSettings<TTransaction>(\n options: PostgresEventStoreOptions<TTransaction>,\n): {\n purgeBatchSize: number;\n wakeUp: PostgresWakeUp;\n queryOptions: PostgresQueryOptions | undefined;\n} {\n // A pool next to an executor only serves the store's own statements (PostgresExecutorOptions.pool).\n const sources = [options.executor ?? options.pool, options.connectionString].filter(\n (source) => source !== undefined,\n );\n if (sources.length !== 1) {\n throw new ConfigurationError(\n 'PostgresEventStore needs exactly one of pool, connectionString or executor',\n );\n }\n const purgeBatchSize = PositiveInteger.of(\n options.purgeBatchSize ?? DEFAULT_PURGE_BATCH_SIZE,\n 'purgeBatchSize',\n );\n const wakeUp = options.wakeUp ?? 'notify';\n if (!WAKE_UPS.includes(wakeUp)) {\n throw new ConfigurationError(`wakeUp must be 'notify' or 'poll', received ${String(wakeUp)}`);\n }\n const preparedStatements = options.preparedStatements ?? true;\n if (typeof preparedStatements !== 'boolean') {\n throw new ConfigurationError(\n `preparedStatements must be a boolean, received ${String(preparedStatements)}`,\n );\n }\n return {\n purgeBatchSize,\n wakeUp,\n queryOptions: preparedStatements ? { prepare: true } : undefined,\n };\n}\n","import type { PostgresNames } from './names.js';\nimport { laneExpression } from './sql-fragments.js';\n\n/** Statements that publish: events, deliveries and the wake-up notification. */\nexport class AppendStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Publishes in one statement: reserves the sequences of the keys (`[{ key, count }]` in `$4`, locked in\n * key order: each row lock is held until the publishing transaction ends, which makes sequence order equal commit order for a key), numbers the keyed events in entry order (`ordinal`), inserts\n * the events of `$1` that do not exist yet and the deliveries of `$3` that belong to them, and sends one\n * wake-up notification when a delivery it inserted is due at `$5`. Parameters:\n * `[eventsJson, createdAt, deliveriesJson, keyCountsJson, now]`. Returns one row per event of `$1`: its\n * id, its sequence, whether this statement inserted it, and (on every row) how many deliveries it\n * inserted. Deliveries of events that already existed are left to {@link insertDeliveries}.\n */\n get insertFreshEvents(): string {\n return `WITH ${this.#reservedSequences()}, ${this.#incomingEvents()}, ${this.#insertedEvents()}, ${this.#insertedDeliveries()}, ${this.#wakeUp('inserted_deliveries', '$5')}\nSELECT incoming.id, incoming.sequence::text AS sequence,\n incoming.id IN (SELECT inserted_events.id FROM inserted_events) AS inserted,\n (SELECT count(*) FROM inserted_deliveries)::int AS deliveries\nFROM incoming\nWHERE (SELECT count(*) FROM woken) >= 0`;\n }\n\n /** The CTE `reserved` of {@link insertFreshEvents}: the sequences the keys of `$4` reserve. */\n #reservedSequences(): string {\n return `reserved AS (\n INSERT INTO ${this.#names.keySequences} AS reserved (key, sequence)\n SELECT requested.key, requested.count\n FROM jsonb_to_recordset($4::jsonb) AS requested (key text, count bigint)\n ORDER BY requested.key\n ON CONFLICT (key) DO UPDATE SET sequence = reserved.sequence + EXCLUDED.sequence\n RETURNING reserved.key AS key, reserved.sequence AS sequence\n)`;\n }\n\n /** The CTE `incoming` of {@link insertFreshEvents}: the events of `$1` with their key sequences. */\n #incomingEvents(): string {\n return `incoming AS (\n SELECT incoming.*,\n CASE WHEN incoming.key IS NULL THEN NULL ELSE\n reserved.sequence - count(*) OVER (PARTITION BY incoming.key)\n + row_number() OVER (PARTITION BY incoming.key ORDER BY incoming.ordinal)\n END AS sequence\n FROM json_to_recordset($1::json) AS incoming (\n ordinal int, id text, type text, source text, key text, payload json, headers json,\n correlation_id text, causation_id text, occurred_at timestamptz, handlers text[])\n LEFT JOIN reserved ON reserved.key = incoming.key\n)`;\n }\n\n /** The CTE `inserted_events` of {@link insertFreshEvents}: the events of `$1` that do not exist yet. */\n #insertedEvents(): string {\n return `inserted_events AS (\n INSERT INTO ${this.#names.events}\n (id, type, source, key, sequence, payload, headers, correlation_id, causation_id, occurred_at, created_at, handlers)\n SELECT incoming.id, incoming.type, incoming.source, incoming.key, incoming.sequence,\n COALESCE(incoming.payload, 'null'::json), COALESCE(incoming.headers, '{}'::json),\n incoming.correlation_id, incoming.causation_id, incoming.occurred_at, $2::timestamptz,\n COALESCE(incoming.handlers, '{}')\n FROM incoming\n ORDER BY incoming.id\n ON CONFLICT (id) DO NOTHING\n RETURNING id, key, sequence\n)`;\n }\n\n /** The CTE `inserted_deliveries` of {@link insertFreshEvents}: the deliveries of `$3` of the inserted events. */\n #insertedDeliveries(): string {\n return `inserted_deliveries AS (\n INSERT INTO ${this.#names.deliveries}\n (id, event_id, handler, lane, status, attempts, available_at, key, sequence, created_at, updated_at)\n SELECT delivery.id, delivery.event_id, delivery.handler, ${laneExpression('event.key', 'event.id')}, 'pending', 0,\n delivery.available_at, event.key, event.sequence, $2::timestamptz, $2::timestamptz\n FROM jsonb_to_recordset($3::jsonb) AS delivery (id text, event_id text, handler text, available_at timestamptz)\n JOIN inserted_events AS event ON event.id = delivery.event_id\n ORDER BY delivery.event_id, delivery.handler\n ON CONFLICT (event_id, handler) DO NOTHING\n RETURNING available_at\n)`;\n }\n\n /**\n * One wake-up notification on {@link PostgresNames.notificationChannel}, outside any publishing\n * transaction. Returns a boolean column rather than the `void` of `pg_notify`, which some libraries\n * cannot read (Prisma's raw queries reject a `void` column).\n */\n get notify(): string {\n return `SELECT true AS notified FROM pg_notify('${this.#names.notificationChannel}', '')`;\n }\n\n /**\n * A CTE `woken` that sends one notification on {@link PostgresNames.notificationChannel} when a row of\n * `inserted` is due at `now`. PostgreSQL delivers it when the transaction commits, merges the same\n * notification sent twice in one transaction, and drops it on rollback. The statement must reference\n * `woken` for it to run.\n */\n #wakeUp(inserted: string, now: string): string {\n return `woken AS (\n SELECT pg_notify('${this.#names.notificationChannel}', '') FROM (\n SELECT 1 FROM ${inserted} WHERE ${inserted}.available_at <= ${now}::timestamptz LIMIT 1\n ) AS due\n)`;\n }\n\n /**\n * Parameters: `[eventsJson, createdAt]`. Returns the ids that were inserted.\n * `handlers` is the list of handlers the event gets deliveries for: it\n * outlives the deliveries, which are deleted when they complete.\n */\n get insertEvents(): string {\n return `INSERT INTO ${this.#names.events}\n (id, type, source, key, sequence, payload, headers, correlation_id, causation_id, occurred_at, created_at, handlers)\nSELECT incoming.id, incoming.type, incoming.source, incoming.key, incoming.sequence,\n COALESCE(incoming.payload, 'null'::json), COALESCE(incoming.headers, '{}'::json),\n incoming.correlation_id, incoming.causation_id, incoming.occurred_at, $2::timestamptz,\n COALESCE(incoming.handlers, '{}')\nFROM json_to_recordset($1::json) AS incoming (\n id text, type text, source text, key text, sequence bigint, payload json, headers json,\n correlation_id text, causation_id text, occurred_at timestamptz, handlers text[])\nORDER BY incoming.id\nON CONFLICT (id) DO NOTHING\nRETURNING id`;\n }\n\n /**\n * Locks events that were not inserted by the current append, in id order, so\n * that appends adding handlers to the same event run one after the other.\n * Parameters: `[eventIdsJson]`. `FOR NO KEY UPDATE` conflicts with itself and\n * not with the foreign key checks of other inserts.\n */\n get lockExistingEvents(): string {\n return `SELECT id FROM ${this.#names.events}\nWHERE id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\nORDER BY id\nFOR NO KEY UPDATE`;\n }\n\n /**\n * Parameters: `[deliveriesJson, createdAt, insertedEventIdsJson, now]`. Key and\n * sequence are copied from the stored event, so a delivery added later to an\n * existing event keeps the event's position in its key and lands in the same\n * lane. Returns the ids that were inserted.\n *\n * The deliveries of events this call just inserted are all new. For an event\n * that already existed, a handler gets a delivery only if the event does not\n * list it yet: a completed delivery is deleted, but its handler stays listed,\n * so a redelivered or republished event never runs a handler twice. The\n * handlers added to an existing event are appended to its list.\n */\n get insertDeliveries(): string {\n const events = this.#names.events;\n const insertedEvents = `ARRAY(SELECT jsonb_array_elements_text($3::jsonb))`;\n return `WITH incoming AS (\n SELECT incoming.id, incoming.event_id, incoming.handler, incoming.available_at\n FROM jsonb_to_recordset($1::jsonb) AS incoming (id text, event_id text, handler text, available_at timestamptz)\n), fresh AS (\n SELECT incoming.*, event.key, event.sequence, ${laneExpression('event.key', 'event.id')} AS lane\n FROM incoming\n JOIN ${events} AS event ON event.id = incoming.event_id\n WHERE event.id = ANY (${insertedEvents}) OR NOT incoming.handler = ANY (event.handlers)\n), inserted AS (\n INSERT INTO ${this.#names.deliveries}\n (id, event_id, handler, lane, status, attempts, available_at, key, sequence, created_at, updated_at)\n SELECT fresh.id, fresh.event_id, fresh.handler, fresh.lane, 'pending', 0, fresh.available_at,\n fresh.key, fresh.sequence, $2::timestamptz, $2::timestamptz\n FROM fresh\n ORDER BY fresh.event_id, fresh.handler\n ON CONFLICT (event_id, handler) DO NOTHING\n RETURNING id, event_id, handler, available_at\n), extended AS (\n UPDATE ${events} AS event SET handlers = event.handlers || added.handlers\n FROM (\n SELECT inserted.event_id, array_agg(inserted.handler) AS handlers FROM inserted\n WHERE inserted.event_id <> ALL (${insertedEvents}) GROUP BY inserted.event_id\n ) AS added\n WHERE event.id = added.event_id\n RETURNING event.id\n), ${this.#wakeUp('inserted', '$4')}\nSELECT id FROM inserted WHERE (SELECT count(*) FROM woken) >= 0`;\n }\n}\n","import type { PostgresParameter } from './executor.js';\nimport type { PostgresNames } from './names.js';\nimport { isoText } from './sql-fragments.js';\n\nexport interface PostgresStatement {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n}\n\n/**\n * Due deliveries the fast claim examines before it gives up and lets the slow\n * claim look at the heads of all keys.\n */\nexport const CLAIM_SCAN_WINDOW = 256;\n\n/** Due deliveries the fast claim reads from one lane. A lane that fills it may hide claimable deliveries behind blocked followers. */\nexport const LANE_SCAN_WINDOW = 64;\n\n/**\n * Due deliveries of a free lane a claim looks at when it decides how many lanes to take: their unkeyed\n * deliveries and distinct keys estimate what the lane can give, so a deep backlog is taken a few lanes\n * at a time and a lane of few hot keys counts for no more than its keys.\n */\nexport const LANE_DEPTH_CAP = 16;\n\n/** Free lanes a claim that needs more takes at least (those with the oldest due deliveries), as in its first round. */\nexport const INITIAL_FREE_LANES = 4;\n\nexport const HANDLER_PREDICATE = `delivery.handler = ANY (ARRAY(SELECT jsonb_array_elements_text($2::jsonb)))`;\n\nexport function eventColumns(alias: string): string {\n return `${alias}.id AS event_id,\n ${alias}.type AS event_type,\n ${alias}.source AS event_source,\n ${alias}.key AS event_key,\n ${alias}.payload::text AS event_payload,\n ${alias}.headers::text AS event_headers,\n ${alias}.correlation_id AS event_correlation_id,\n ${alias}.causation_id AS event_causation_id,\n ${isoText(`${alias}.occurred_at`)} AS event_occurred_at`;\n}\n\n/** `WITH changed AS (<dml> RETURNING 1) SELECT count(*)`: a top-level SELECT works the same on every driver. */\nexport function countChanged(dml: string): string {\n return `WITH changed AS (${dml} RETURNING 1) SELECT count(*)::int AS count FROM changed`;\n}\n\n/**\n * The head (lowest pending sequence) of every key of every wanted handler in the lane `scope.lane`,\n * as a subquery returning `(id, lane, available_at, handler, key)`. A loose index scan on the\n * pending-key index hops from key to key of a handler, and after its last key on to the first key of\n * the next wanted handler, so the cost follows the number of keys, not the number of followers. The\n * handlers are walked inside the recursion instead of joined to it: a join multiplied the planner's\n * cost estimate by the handler count, which pushed the claim statements over `jit_above_cost`, and\n * compiling them took longer than running them.\n */\nexport function keyHeads(names: PostgresNames, scope: string): string {\n const deliveries = names.deliveries;\n // `key IS NOT NULL` is spelled out only where nothing else implies it: next to `key > ...` or\n // `key = ...` the planner proves the partial index from those, and with the column all null in the\n // statistics the extra clause made it expect one row behind many index entries and cost every hop as a\n // full range scan.\n const pending = `candidate.lane = ${scope}.lane AND candidate.status = 'pending'`;\n const nextHandler = (after: string): string =>\n `(SELECT min(wanted.handler) FROM jsonb_array_elements_text($2::jsonb) AS wanted (handler)${after === '' ? '' : ` WHERE wanted.handler > ${after}`})`;\n return `\n WITH RECURSIVE hops (handler, key) AS (\n SELECT ${nextHandler('')}, NULL::text\n UNION ALL\n SELECT CASE WHEN next.key IS NULL THEN ${nextHandler('hops.handler')} ELSE hops.handler END, next.key\n FROM hops\n CROSS JOIN LATERAL (\n SELECT CASE WHEN hops.key IS NULL\n THEN (SELECT candidate.key FROM ${deliveries} AS candidate\n WHERE ${pending} AND candidate.handler = hops.handler AND candidate.key IS NOT NULL\n ORDER BY candidate.key LIMIT 1)\n ELSE (SELECT candidate.key FROM ${deliveries} AS candidate\n WHERE ${pending} AND candidate.handler = hops.handler AND candidate.key > hops.key\n ORDER BY candidate.key LIMIT 1)\n END AS key\n OFFSET 0\n ) AS next\n WHERE hops.handler IS NOT NULL\n )\n SELECT lowest.id, lowest.lane, lowest.available_at, lowest.handler, lowest.key\n FROM hops\n CROSS JOIN LATERAL (\n SELECT candidate.id, candidate.lane, candidate.available_at, candidate.handler, candidate.key\n FROM ${deliveries} AS candidate\n WHERE ${pending} AND candidate.handler = hops.handler AND candidate.key = hops.key\n ORDER BY candidate.sequence LIMIT 1\n ) AS lowest\n WHERE hops.key IS NOT NULL\n `;\n}\n\n/** True when none of the lane's listed deliveries exists as a pending row. */\nexport function noRunningDelivery(names: PostgresNames, laneAlias: string): string {\n return `NOT EXISTS (\n SELECT 1 FROM unnest(${laneAlias}.in_flight) AS flying (id)\n JOIN ${names.deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n )`;\n}\n","import type { PostgresNames } from './names.js';\nimport {\n CLAIM_SCAN_WINDOW,\n HANDLER_PREDICATE,\n LANE_SCAN_WINDOW,\n eventColumns,\n keyHeads,\n noRunningDelivery,\n} from './statement-fragments.js';\n\nconst LANE_LIST = `ARRAY(SELECT jsonb_array_elements_text($4::jsonb)::smallint)`;\n\n/** Statements of the claim continued round by round, its record, reconciliation and lane handback. */\nexport class ClaimStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Fast claim: picks from the first {@link CLAIM_SCAN_WINDOW} due deliveries of\n * the given lanes in due order, which is everything the claim needs while the\n * front of the queue is not clogged with blocked followers of busy keys.\n * Parameters: `[now, handlersJson, limit, lanesJson]`. The lanes must be held\n * and locked by the caller.\n *\n * Always returns one row per picked delivery, or a single row whose\n * `delivery_id` is null when nothing was picked. `window_saturated` says\n * whether the window was full: when it is and fewer than `limit` deliveries\n * were picked, deliveries beyond the window may still be claimable and the\n * caller runs {@link claimBehindBlockedKeys}. When the window is not\n * saturated every due delivery was examined, so the result is complete.\n *\n * A delivery is a candidate when it is pending, due, and not in flight. A\n * keyed delivery is a candidate only when it is the head of its (handler,\n * key), that is (a) no earlier delivery of that handler and key is pending\n * (an earlier one in flight is still a pending row, which is the ordering\n * guarantee), and (b) no other delivery of that handler and key is in\n * flight, which covers a delivery that re-enters the key behind a running one\n * (requeue, or a handler added to an old event).\n *\n * No row is locked or written here: the lanes' exclusive leases are the\n * mutual exclusion, so two claimers never see the same lane.\n */\n get claim(): string {\n return `WITH ${this.#scopeAndRunning(`SELECT lane.lane, lane.epoch, lane.in_flight FROM ${this.#names.lanes} AS lane WHERE lane.lane = ANY (${LANE_LIST})`)},\n${this.#fastWindow()}\n)\n${this.#pickedRows(`((SELECT count(*) FROM due_window) >= ${CLAIM_SCAN_WINDOW} OR EXISTS (SELECT 1 FROM due_window GROUP BY lane HAVING count(*) >= ${LANE_SCAN_WINDOW}))`)}`;\n }\n\n /** The `due_window` and `candidates` CTEs of the fast claim, up to (not including) the closing parenthesis of `candidates`. */\n #fastWindow(): string {\n const deliveries = this.#names.deliveries;\n return `due_window AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at\n FROM scope\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = scope.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (scope.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${LANE_SCAN_WINDOW}\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT ${CLAIM_SCAN_WINDOW}\n), candidates AS MATERIALIZED (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM due_window\n JOIN ${deliveries} AS delivery ON delivery.id = due_window.id\n WHERE delivery.key IS NULL OR NOT (${this.#blockedKey('delivery')})\n ORDER BY delivery.available_at, delivery.id\n LIMIT $3::int`;\n }\n\n /**\n * Slow claim, run when {@link claim} picked too few deliveries from a full\n * window: the front of the due queue is mostly followers of blocked keys.\n * Same parameters and rules as {@link claim}, but heads are found with\n * a loose index scan over the pending-key index of each lane (it hops from key\n * to key), so the cost follows the number of pending keys in the lanes\n * instead of one probe per due follower.\n */\n get claimBehindBlockedKeys(): string {\n const deliveries = this.#names.deliveries;\n return `WITH ${this.#scopeAndRunning(`SELECT lane.lane, lane.epoch, lane.in_flight FROM ${this.#names.lanes} AS lane WHERE lane.lane = ANY (${LANE_LIST})`)},\nheads AS MATERIALIZED (\n SELECT head.id, head.lane, head.available_at, head.handler, head.key\n FROM scope\n CROSS JOIN LATERAL (${keyHeads(this.#names, 'scope')}) AS head\n), keyed AS MATERIALIZED (\n SELECT heads.id, heads.lane, heads.available_at\n FROM heads\n JOIN scope ON scope.lane = heads.lane\n WHERE heads.available_at <= $1::timestamptz AND heads.id <> ALL (scope.in_flight)\n AND NOT EXISTS (SELECT 1 FROM running WHERE running.handler = heads.handler AND running.key = heads.key)\n ORDER BY heads.available_at, heads.id\n LIMIT $3::int\n), unkeyed AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at\n FROM scope\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = scope.lane AND delivery.key IS NULL AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (scope.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT $3::int\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT $3::int\n), candidates AS MATERIALIZED (\n SELECT id, lane, available_at FROM (\n SELECT id, lane, available_at FROM keyed\n UNION ALL\n SELECT id, lane, available_at FROM unkeyed\n ) AS both_sets\n ORDER BY available_at, id\n LIMIT $3::int\n)\n${this.#pickedRows('false')}`;\n }\n\n /** The held lanes with their epochs and in-flight ids, and the keyed deliveries running in them. */\n #scopeAndRunning(scopeQuery: string): string {\n const deliveries = this.#names.deliveries;\n return `scope AS MATERIALIZED (\n ${scopeQuery}\n), running AS MATERIALIZED (\n SELECT delivery.handler, delivery.key\n FROM scope\n CROSS JOIN LATERAL unnest(scope.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id\n WHERE delivery.status = 'pending' AND delivery.key IS NOT NULL\n)`;\n }\n\n /** True when an earlier delivery of the candidate's handler and key is pending, or another one is running. */\n #blockedKey(alias: string): string {\n return `EXISTS (\n SELECT 1 FROM ${this.#names.deliveries} AS earlier\n WHERE earlier.lane = ${alias}.lane AND earlier.handler = ${alias}.handler AND earlier.key = ${alias}.key\n AND earlier.status = 'pending' AND earlier.key IS NOT NULL\n AND earlier.sequence < ${alias}.sequence\n ) OR ${this.#runningElsewhere(alias)}`;\n }\n\n /** True when a delivery of the candidate's handler and key is in flight. The candidate itself never is. */\n #runningElsewhere(alias: string): string {\n return `EXISTS (\n SELECT 1 FROM running\n WHERE running.handler = ${alias}.handler AND running.key = ${alias}.key\n )`;\n }\n\n /** Final SELECT shared by both claims: the picked deliveries with their lane epoch and event. */\n #pickedRows(saturated: string): string {\n return `SELECT ${saturated} AS window_saturated, picked.*\nFROM (SELECT 1) AS anchor\nLEFT JOIN (\n ${this.#pickedRowsSelect()}\n) AS picked ON true\nORDER BY picked.due_at, picked.delivery_id`;\n }\n\n /** The picked deliveries joined with the lane epoch and their event, as the claim result columns. */\n #pickedRowsSelect(): string {\n return `SELECT candidates.available_at AS due_at, delivery.id AS delivery_id, delivery.lane::int AS lane,\n scope.epoch::text AS epoch, delivery.claims AS claims, delivery.handler, delivery.key AS delivery_key, delivery.sequence::text AS sequence, (delivery.attempts + 1)::int AS attempt,\n ${eventColumns('event')}\n FROM candidates\n JOIN scope ON scope.lane = candidates.lane\n JOIN ${this.#names.deliveries} AS delivery ON delivery.id = candidates.id\n JOIN ${this.#names.events} AS event ON event.id = delivery.event_id`;\n }\n\n /**\n * Records the deliveries a claim picked in their lanes and frees the lanes it\n * took or held for nothing. Parameters:\n * `[pickedJson, idleLanesJson, leaseOwner, leaseExpiresAt]` with\n * `pickedJson = [{ lane, ids }]`.\n *\n * A picked lane lists the ids that are still in flight (listed ids whose row\n * still exists) plus the new ones, and its lease reaches `leaseExpiresAt`.\n * An idle lane is freed when no delivery of it is in flight, so other workers\n * need not wait for the lease to expire.\n */\n get recordClaim(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `WITH picked AS (\n SELECT recorded.lane, recorded.ids\n FROM jsonb_to_recordset($1::jsonb) AS recorded (lane smallint, ids text[])\n), still_running AS (\n SELECT lane.lane, array_agg(delivery.id) AS ids\n FROM picked\n JOIN ${lanes} AS lane ON lane.lane = picked.lane\n CROSS JOIN LATERAL unnest(lane.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n GROUP BY lane.lane\n), extended AS (\n UPDATE ${lanes} AS lane\n SET in_flight = COALESCE(still_running.ids, '{}') || picked.ids,\n lease_expires_at = GREATEST(lane.lease_expires_at, $4::timestamptz)\n FROM picked\n LEFT JOIN still_running ON still_running.lane = picked.lane\n WHERE lane.lane = picked.lane\n RETURNING lane.lane\n), freed AS (\n UPDATE ${lanes} AS lane\n SET lease_owner = NULL, lease_expires_at = NULL, in_flight = '{}'\n WHERE lane.lane = ANY (ARRAY(SELECT jsonb_array_elements_text($2::jsonb)::smallint))\n AND lane.lease_owner = $3::text\n AND ${noRunningDelivery(this.#names, 'lane')}\n RETURNING lane.lane\n)\nSELECT (SELECT count(*) FROM extended)::int AS extended, (SELECT count(*) FROM freed)::int AS freed`;\n }\n\n /**\n * Keeps in the in-flight lists of the lanes `$1` holds only the claims in `$2`\n * (`[{ id, lane, epoch, claims }]`, the ones this store handed out and nobody\n * settled yet) and takes every other delivery out. That is a batch a claim\n * recorded but whose answer never arrived: nothing runs it and the lane lease,\n * renewed by the owner's other deliveries, would keep it away from everybody for\n * ever. A claim matches only with the lane epoch and the delivery generation it was\n * handed out with. Parameters: `[leaseOwner, handedOutJson, generation]`; a lane whose `claim_floor` is above\n * the generation was reconciled by a newer call, so an older (late) reconciliation leaves it alone.\n * The lanes are locked in lane order first (see the lock order on {@link PostgresStatements}).\n */\n get reconcileClaims(): string {\n const deliveries = this.#names.deliveries;\n const handedOut = `jsonb_to_recordset($2::jsonb) AS handed (id text, lane smallint, epoch bigint, claims int)`;\n const kept = `SELECT 1 FROM ${handedOut} JOIN ${deliveries} AS delivery ON delivery.id = handed.id\n WHERE handed.id = flying.id AND handed.lane = lane.lane AND handed.epoch = lane.epoch AND delivery.claims = handed.claims`;\n return `WITH owned AS MATERIALIZED (\n SELECT lane.lane FROM ${this.#names.lanes} AS lane\n WHERE lane.lease_owner = $1::text AND lane.claim_floor <= $3::bigint\n ORDER BY lane.lane\n FOR NO KEY UPDATE\n)\nUPDATE ${this.#names.lanes} AS lane\nSET in_flight = ARRAY(SELECT flying.id FROM unnest(lane.in_flight) AS flying (id) WHERE EXISTS (${kept})),\n claim_floor = $3::bigint\nFROM owned\nWHERE lane.lane = owned.lane AND lane.lease_owner = $1::text AND lane.claim_floor <= $3::bigint`;\n }\n\n /**\n * Frees every lane `$1` holds that has no running delivery, locking them in lane order first.\n * Parameters: `[leaseOwner]`.\n */\n get relinquish(): string {\n return `WITH owned AS MATERIALIZED (\n SELECT lane.lane FROM ${this.#names.lanes} AS lane\n WHERE lane.lease_owner = $1::text\n ORDER BY lane.lane\n FOR NO KEY UPDATE\n)\nUPDATE ${this.#names.lanes} AS lane\nSET lease_owner = NULL, lease_expires_at = NULL, in_flight = '{}'\nFROM owned\nWHERE lane.lane = owned.lane AND lane.lease_owner = $1::text AND ${noRunningDelivery(this.#names, 'lane')}`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { countChanged } from './statement-fragments.js';\n\n/** Fenced statements that end or extend a claim. */\nexport class CompletionStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Extends the lease of the lane a running delivery belongs to; the lane lease\n * never shrinks. Parameters: `[deliveryId, lane, epoch, claims, leaseExpiresAt]`.\n */\n get extendLease(): string {\n return countChanged(`UPDATE ${this.#names.lanes} AS lane\nSET lease_expires_at = GREATEST(lane.lease_expires_at, $5::timestamptz)\nWHERE lane.lane = $2::smallint AND lane.epoch = $3::bigint AND $1::text = ANY (lane.in_flight)\n AND EXISTS (\n SELECT 1 FROM ${this.#names.deliveries} AS delivery\n WHERE delivery.id = $1::text AND delivery.status = 'pending' AND delivery.claims = $4::int\n )`);\n }\n\n /**\n * Deletes the running deliveries whose lane lease is still the one they were\n * claimed under. Parameters: `[leasesJson, now]` with\n * `leasesJson = [{ ord, id, lane, epoch, claims }]`. Returns the `ord` of every lease that was completed, so\n * results are matched to leases and not to delivery ids. A delivery is only deleted by the claim that\n * is still its current one (`claims`), which makes a stale lease harmless even when the same owner re-claimed\n * the delivery in the same lane epoch. The event gets a completion time for retention.\n *\n * The lane rows are locked `FOR KEY SHARE` first, in lane order, and the lock\n * is held until the surrounding transaction ends. A claimer that takes the\n * lane over locks it `FOR UPDATE`, which conflicts with that lock, so it\n * skips the lane until this completion commits or rolls back: a completion\n * and a takeover cannot both succeed for one delivery, which is what makes a\n * transactional handler's writes effectively-once. The weakest lock that\n * conflicts with a takeover is used on purpose: it does not conflict with the\n * owner's own claim and heartbeats (plain updates of the lane row), which\n * would otherwise wait for every completion in progress. With a completion history the deleted rows are copied to\n * it in the same statement.\n */\n get complete(): string {\n const deliveries = this.#names.deliveries;\n const history = this.#names.completionHistory;\n return `WITH leases AS (\n SELECT lease.ord, lease.id, lease.lane, lease.epoch, lease.claims\n FROM jsonb_to_recordset($1::jsonb) AS lease (ord int, id text, lane smallint, epoch bigint, claims int)\n), fence AS MATERIALIZED (\n SELECT lane.lane, lane.epoch, lane.in_flight\n FROM ${this.#names.lanes} AS lane\n WHERE lane.lane IN (SELECT lane FROM leases)\n ORDER BY lane.lane\n FOR KEY SHARE\n), completed AS (\n DELETE FROM ${deliveries} AS delivery\n USING leases JOIN fence ON fence.lane = leases.lane AND fence.epoch = leases.epoch\n WHERE delivery.id = leases.id AND delivery.lane = leases.lane AND delivery.status = 'pending'\n AND delivery.claims = leases.claims AND leases.id = ANY (fence.in_flight)\n RETURNING leases.ord, delivery.id, delivery.event_id, delivery.handler, delivery.attempts, delivery.available_at, delivery.created_at\n), stamped AS (\n INSERT INTO ${this.#names.eventCompletions} (event_id, completed_at)\n SELECT DISTINCT completed.event_id, $2::timestamptz FROM completed\n -- Event id order: completions of other handlers of the same events lock these rows too.\n ORDER BY completed.event_id\n ON CONFLICT (event_id) DO UPDATE SET completed_at = GREATEST(${this.#names.eventCompletions}.completed_at, EXCLUDED.completed_at)\n RETURNING event_id\n)${\n history\n ? `, archived AS (\n INSERT INTO ${this.#names.completions} (id, event_id, handler, attempts, available_at, created_at, completed_at)\n SELECT id, event_id, handler, attempts + 1, available_at, created_at, $2::timestamptz FROM completed\n RETURNING id\n)`\n : ''\n }\nSELECT ord FROM completed`;\n }\n\n /**\n * Returns a running delivery to pending, due at `availableAt`, and takes it\n * out of the lane's in-flight list. Parameters:\n * `[deliveryId, lane, epoch, claims, availableAt, errorJson, now]`. The attempt that\n * just ended is counted.\n */\n get reschedule(): string {\n return this.#leaveFlight(\n `SET available_at = $5::timestamptz, last_error = $6::jsonb, attempts = delivery.attempts + 1, claims = delivery.claims + 1, updated_at = $7::timestamptz`,\n );\n }\n\n /** Parameters: `[deliveryId, lane, epoch, claims, errorJson, now]`. The attempt that just ended is counted. */\n get bury(): string {\n return this.#leaveFlight(\n `SET status = 'dead', last_error = $5::jsonb, attempts = delivery.attempts + 1, claims = delivery.claims + 1, updated_at = $6::timestamptz`,\n );\n }\n\n /**\n * Gives a running delivery back without spending its attempt (an attempt is\n * only recorded when it ends in failure or a lost lease): pending, due `now`.\n * Parameters: `[deliveryId, lane, epoch, claims, now]`.\n */\n get release(): string {\n return this.#leaveFlight(\n `SET available_at = $5::timestamptz, claims = delivery.claims + 1, updated_at = $5::timestamptz`,\n );\n }\n\n /**\n * Applies `assignments` to a running delivery and removes it from its lane's\n * in-flight list, if the lane still has the caller's epoch. The lane row is\n * locked first (`FOR NO KEY UPDATE`, which conflicts with a takeover's `FOR UPDATE`), so a takeover cannot interleave. Parameters\n * `$1`..`$4` are always `[deliveryId, lane, epoch, claims]`; ending a claim bumps `claims`.\n */\n #leaveFlight(assignments: string): string {\n const lanes = this.#names.lanes;\n return `WITH fence AS MATERIALIZED (\n SELECT lane.lane FROM ${lanes} AS lane\n WHERE lane.lane = $2::smallint AND lane.epoch = $3::bigint AND $1::text = ANY (lane.in_flight)\n FOR NO KEY UPDATE\n), changed AS (\n UPDATE ${this.#names.deliveries} AS delivery ${assignments}\n FROM fence\n WHERE delivery.id = $1::text AND delivery.lane = fence.lane AND delivery.status = 'pending'\n AND delivery.claims = $4::int\n RETURNING delivery.id\n), trimmed AS (\n UPDATE ${lanes} AS lane SET in_flight = array_remove(lane.in_flight, $1::text)\n FROM changed WHERE lane.lane = $2::smallint\n RETURNING lane.lane\n)\nSELECT count(*)::int AS count FROM changed`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport {\n CLAIM_SCAN_WINDOW,\n HANDLER_PREDICATE,\n LANE_SCAN_WINDOW,\n keyHeads,\n} from './statement-fragments.js';\n\n/** Which lanes `#candidates` picks from, under which CTE names, and how many. */\ntype CandidateSpec = {\n readonly prefix: string;\n readonly scope: string;\n readonly running: string | null;\n readonly limit: string;\n};\n\n/** True for a delivery whose (handler, key) runs nowhere in the CTE `running`; always true without one. */\nfunction notRunning(running: string | null, alias: string): string {\n return running === null\n ? 'true'\n : `NOT EXISTS (SELECT 1 FROM ${running} AS running WHERE running.handler = ${alias}.handler AND running.key = ${alias}.key)`;\n}\n\n/** Statements that pick the claimable deliveries of a set of lanes, as CTEs a claim embeds. */\nexport class CandidateStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * CTEs that pick up to `limit` claimable deliveries from the lanes of the CTE `scope` (columns `lane`,\n * `epoch`, `in_flight`), named after `prefix`; the result is `<prefix>_candidates (id, lane, available_at)`.\n * The rules are those of `ClaimStatements.claim`. The fast window reads the first {@link LANE_SCAN_WINDOW} due\n * deliveries of each lane (at most {@link CLAIM_SCAN_WINDOW} together); of a key, only the lowest sequence\n * in the window can be its head, so only that one is checked for an earlier pending delivery. Only when\n * that yields fewer than `limit` are the lanes whose window filled up looked at again with a loose index\n * scan over the heads of all their keys. `running` names the CTE of the keyed deliveries running in the\n * lanes, or is null when nothing runs there.\n */\n candidates(\n prefix: string,\n {\n scope,\n running,\n limit,\n }: { readonly scope: string; readonly running: string | null; readonly limit: string },\n ): string {\n const spec: CandidateSpec = { prefix, scope, running, limit };\n return this.#fastCandidates(spec) + this.#slowCandidates(spec);\n }\n\n /** The fast window of each lane and the claimable deliveries in it (`<prefix>_window`, `<prefix>_fast`). */\n #fastCandidates({ prefix, scope, running, limit }: CandidateSpec): string {\n const deliveries = this.#names.deliveries;\n return `${prefix}_window AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at, recent.handler, recent.key, recent.sequence\n FROM ${scope}\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at, delivery.handler, delivery.key, delivery.sequence\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = ${scope}.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (${scope}.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${LANE_SCAN_WINDOW}\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT ${CLAIM_SCAN_WINDOW}\n), ${prefix}_fast AS MATERIALIZED (\n SELECT picked.id, picked.lane, picked.available_at FROM (\n SELECT unkeyed.id, unkeyed.lane, unkeyed.available_at FROM ${prefix}_window AS unkeyed WHERE unkeyed.key IS NULL\n UNION ALL\n SELECT head.id, head.lane, head.available_at\n FROM (\n SELECT DISTINCT ON (keyed.handler, keyed.key) keyed.id, keyed.lane, keyed.available_at, keyed.handler, keyed.key, keyed.sequence\n FROM ${prefix}_window AS keyed\n WHERE keyed.key IS NOT NULL\n ORDER BY keyed.handler, keyed.key, keyed.sequence\n ) AS head\n WHERE NOT EXISTS (\n SELECT 1 FROM ${deliveries} AS earlier\n WHERE earlier.lane = head.lane AND earlier.handler = head.handler AND earlier.key = head.key\n AND earlier.status = 'pending' AND earlier.key IS NOT NULL AND earlier.sequence < head.sequence\n ) AND ${notRunning(running, 'head')}\n ) AS picked\n ORDER BY picked.available_at, picked.id\n LIMIT ${limit}\n`;\n }\n\n /**\n * For lanes whose window filled up while the fast pick came up short: the heads of all their keys and\n * their unkeyed deliveries, then the union with the fast pick (`<prefix>_candidates`).\n */\n #slowCandidates(spec: CandidateSpec): string {\n return (\n this.#saturatedLanes(spec) +\n this.#keyHeads(spec) +\n this.#keyedHeads(spec) +\n this.#unkeyedRecent(spec) +\n this.#unionCandidates(spec)\n );\n }\n\n /** `<prefix>_saturated`: the lanes whose window filled up while the fast pick came up short. */\n #saturatedLanes({ prefix, scope, limit }: CandidateSpec): string {\n return `), ${prefix}_saturated AS MATERIALIZED (\n SELECT ${scope}.lane, ${scope}.in_flight FROM ${scope}\n WHERE (SELECT count(*) FROM ${prefix}_fast) < ${limit}\n AND ((SELECT count(*) FROM ${prefix}_window) >= ${CLAIM_SCAN_WINDOW}\n OR ${scope}.lane IN (\n SELECT full_lane.lane FROM ${prefix}_window AS full_lane\n GROUP BY full_lane.lane HAVING count(*) >= ${LANE_SCAN_WINDOW}\n ))\n`;\n }\n\n /** `<prefix>_heads`: the head of every key of the saturated lanes. */\n #keyHeads({ prefix }: CandidateSpec): string {\n return `), ${prefix}_heads AS MATERIALIZED (\n SELECT head.id, head.lane, head.available_at, head.handler, head.key\n FROM ${prefix}_saturated AS scope\n CROSS JOIN LATERAL (${keyHeads(this.#names, 'scope')}) AS head\n`;\n }\n\n /** `<prefix>_keyed`: the due heads that are not in flight and whose key runs nowhere. */\n #keyedHeads({ prefix, running, limit }: CandidateSpec): string {\n return `), ${prefix}_keyed AS MATERIALIZED (\n SELECT heads.id, heads.lane, heads.available_at\n FROM ${prefix}_heads AS heads\n JOIN ${prefix}_saturated AS scope ON scope.lane = heads.lane\n WHERE heads.available_at <= $1::timestamptz AND heads.id <> ALL (scope.in_flight) AND ${notRunning(running, 'heads')}\n ORDER BY heads.available_at, heads.id\n LIMIT ${limit}\n`;\n }\n\n /** `<prefix>_unkeyed`: the due unkeyed deliveries of the saturated lanes that are not in flight. */\n #unkeyedRecent({ prefix, limit }: CandidateSpec): string {\n const deliveries = this.#names.deliveries;\n return `), ${prefix}_unkeyed AS MATERIALIZED (\n SELECT recent.id, recent.lane, recent.available_at\n FROM ${prefix}_saturated AS scope\n CROSS JOIN LATERAL (\n SELECT delivery.id, delivery.lane, delivery.available_at\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = scope.lane AND delivery.key IS NULL AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n AND delivery.id <> ALL (scope.in_flight)\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${limit}\n ) AS recent\n ORDER BY recent.available_at, recent.id\n LIMIT ${limit}\n`;\n }\n\n /** `<prefix>_candidates`: the union of the fast pick and the slow picks, oldest first, at most `limit`. */\n #unionCandidates({ prefix, limit }: CandidateSpec): string {\n return `), ${prefix}_candidates AS MATERIALIZED (\n SELECT chosen.id, chosen.lane, chosen.available_at FROM (\n SELECT fast.id, fast.lane, fast.available_at FROM ${prefix}_fast AS fast\n UNION\n SELECT keyed.id, keyed.lane, keyed.available_at FROM ${prefix}_keyed AS keyed\n UNION\n SELECT unkeyed.id, unkeyed.lane, unkeyed.available_at FROM ${prefix}_unkeyed AS unkeyed\n ) AS chosen\n ORDER BY chosen.available_at, chosen.id\n LIMIT ${limit}\n)`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { CandidateStatements } from './statements-candidates.js';\nimport {\n CLAIM_SCAN_WINDOW,\n HANDLER_PREDICATE,\n INITIAL_FREE_LANES,\n LANE_DEPTH_CAP,\n LANE_SCAN_WINDOW,\n eventColumns,\n noRunningDelivery,\n} from './statement-fragments.js';\n\n/**\n * Free lanes a claim looks at beyond the number of deliveries it still wants, so lanes whose due\n * deliveries all wait behind a key's later head do not hide the others. When even these are not enough\n * the claim continues in the transaction that takes lanes round by round.\n */\nconst FREE_LANE_SURPLUS = 16;\n\n/** A free lane: its lease expired, or this owner left it behind under an older claim floor. */\nconst freeLane = (alias: string): string =>\n `(${alias}.lease_expires_at IS NULL OR ${alias}.lease_expires_at <= $1::timestamptz\n OR (${alias}.lease_owner = $4::text AND ${alias}.claim_floor < $6::bigint))`;\n\n/** The free-lane CTEs of a claim that only looks at the lanes it holds: all empty. */\nconst NO_FREE_LANES = `), free_lanes AS (\n SELECT NULL::smallint AS lane, NULL::bigint AS epoch, NULL::text[] AS in_flight, false AS running WHERE false\n), free_scope AS (\n SELECT NULL::smallint AS lane, NULL::bigint AS epoch WHERE false\n), free_candidates AS (\n SELECT NULL::text AS id, NULL::smallint AS lane, NULL::timestamptz AS available_at WHERE false\n)`;\n\n/** Statements that claim with the lanes they hold or take: the one-statement claim and the lane takeover. */\nexport class LaneStatements {\n readonly #names: PostgresNames;\n readonly #candidateStatements: CandidateStatements;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n this.#candidateStatements = new CandidateStatements(names);\n }\n\n /**\n * A claim in one statement, the only one in the common case. Parameters:\n * `[now, handlersJson, limit, leaseOwner, leaseExpiresAt, generation]`.\n *\n * 1. **Held lanes.** The lanes this owner holds under a live lease whose `claim_floor` is exactly the\n * generation are locked `FOR NO KEY UPDATE` in lane order. A lane above it was raised by a\n * reconciliation, so a statement of a claim whose caller gave up (a client timeout does not cancel\n * the statement on the server) and that reaches the server late records nothing; a lane below it was\n * taken by such a late statement after the reconciliation, and its listed deliveries were never\n * handed out. A lane that another transaction of this owner is changing makes the statement wait;\n * the statement then reports `stale` and does nothing (see the `stale` CTE).\n * 2. **Free lanes**, only when the held lanes yield fewer than `limit`: the free lanes with a due\n * delivery (one index probe per free lane) are ranked by their oldest due delivery; the first\n * {@link INITIAL_FREE_LANES} that can give something now, and further ones until what they can give\n * (estimated from their first {@link LANE_DEPTH_CAP} due deliveries) covers what is still wanted, are locked\n * `FOR UPDATE SKIP LOCKED`, so a lane another claimer has is skipped, never waited\n * for. A lane that still runs deliveries of an expired lease is left to the transaction of\n * {@link takeFreeLanes}, which charges their lost attempts (`takeover_waiting`); so is any lane whose\n * locked row differs from what the statement's snapshot saw. A lane that runs nothing and did not\n * change cannot have had a delivery written since the snapshot, so its deliveries can be read here.\n * 3. **Picks** follow the rules of `ClaimStatements.claim`: the fast window of each lane, and for lanes whose\n * window filled up while the batch is not full, the heads of all keys (a loose index scan per lane).\n * 4. **Writes**: one update per lane. A held lane records its picks; a taken lane gets a new epoch, the\n * owner, the lease and its picks; a taken lane that yielded nothing is not written. Held lanes that\n * picked nothing, run nothing and have no full scan window are freed.\n *\n * Always returns one row per picked delivery, or one row whose `delivery_id` is null. `running_ids`\n * (JSON text) lists the deliveries the held lanes still run, `examined_lanes` the held lanes.\n */\n get claimLanes(): string {\n return this.#claimLanes(true);\n }\n\n /**\n * {@link claimLanes} limited to the lanes the owner holds: the same parameters, rows and writes, without\n * looking at free lanes (`takeover_waiting` and `unexamined_free_lanes` are false). A worker draining a\n * backlog finds its batch in the lanes it holds; this statement is about half as costly to plan, and\n * the caller runs {@link claimLanes} after it only when it came up short.\n */\n get claimHeldLanes(): string {\n return this.#claimLanes(false);\n }\n\n #claimLanes(includeFreeLanes: boolean): string {\n const free = includeFreeLanes\n ? this.#freeLaneChoice() + this.#freeLaneDepth() + this.#freeLaneTake()\n : NO_FREE_LANES;\n return (\n this.#heldLanes() + free + this.#claimPicks() + this.#claimRecord() + this.#claimRelease()\n );\n }\n\n /** Locks the held lanes, detects a stale snapshot and picks from the held lanes; ends with `wanted`. */\n #heldLanes(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `WITH held AS MATERIALIZED (\n SELECT lane.lane, lane.epoch, lane.in_flight\n FROM ${lanes} AS lane\n WHERE lane.lease_owner = $4::text AND lane.lease_expires_at > $1::timestamptz\n AND lane.claim_floor = $6::bigint\n ORDER BY lane.lane\n FOR NO KEY UPDATE\n), stale AS (\n -- A claim that waited for a lane lock sees the new lane row but reads deliveries with the snapshot it took\n -- before the wait: whatever changed the lane meanwhile (a reschedule, a release) may also have changed\n -- deliveries it cannot see. The statement then does nothing and reports it, and the caller runs it again.\n SELECT EXISTS (\n SELECT 1 FROM held\n JOIN ${lanes} AS before ON before.lane = held.lane\n WHERE before.epoch <> held.epoch OR before.in_flight IS DISTINCT FROM held.in_flight\n ) AS value\n), held_scope AS MATERIALIZED (\n SELECT held.lane, held.epoch, held.in_flight FROM held WHERE NOT (SELECT value FROM stale)\n), held_running AS MATERIALIZED (\n SELECT delivery.handler, delivery.key\n FROM held_scope\n CROSS JOIN LATERAL unnest(held_scope.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id\n WHERE delivery.status = 'pending' AND delivery.key IS NOT NULL\n), ${this.#candidateStatements.candidates('held', { scope: 'held_scope', running: 'held_running', limit: '$3::int' })}, wanted AS MATERIALIZED (\n SELECT CASE WHEN (SELECT value FROM stale) THEN 0\n ELSE $3::int - (SELECT count(*) FROM held_candidates)::int END AS count\n`;\n }\n\n /** The oldest due delivery of each free lane, at most the number still wanted plus a surplus. */\n #freeLaneChoice(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `), free_lanes AS MATERIALIZED (\n -- The oldest due delivery of each free lane: one index probe per free lane, bounded by the due time,\n -- so deliveries scheduled for later are never read.\n SELECT lane.lane, lane.epoch, lane.in_flight, lane.lease_owner, lane.lease_expires_at,\n oldest.available_at, oldest.id, NOT ${noRunningDelivery(this.#names, 'lane')} AS running\n FROM ${lanes} AS lane\n CROSS JOIN LATERAL (\n SELECT delivery.available_at, delivery.id\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = lane.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n ORDER BY delivery.available_at, delivery.id\n LIMIT 1\n ) AS oldest\n WHERE (SELECT count FROM wanted) > 0 AND ${freeLane('lane')}\n ORDER BY oldest.available_at, oldest.id\n LIMIT (SELECT count FROM wanted) + ${FREE_LANE_SURPLUS}\n`;\n }\n\n /** What each free candidate lane can give now, and their order. */\n #freeLaneDepth(): string {\n const deliveries = this.#names.deliveries;\n return `), free_depth AS MATERIALIZED (\n -- What each candidate lane can give now, from its first due deliveries: unkeyed ones, and of a key its\n -- lowest one when nothing earlier of the key is pending. Lanes that can give nothing are passed over;\n -- of the others, the first ${INITIAL_FREE_LANES} are taken, and further ones until they cover what is\n -- still wanted, so the earliest due work of the free lanes comes first.\n SELECT runnable.lane,\n row_number() OVER (ORDER BY runnable.available_at, runnable.id) AS rank,\n sum(runnable.count) OVER (ORDER BY runnable.available_at, runnable.id ROWS UNBOUNDED PRECEDING) - runnable.count AS due_before\n FROM (\n SELECT lane_candidate.lane, lane_candidate.available_at, lane_candidate.id, depth.count\n FROM free_lanes AS lane_candidate\n CROSS JOIN LATERAL (\n -- A full window that shows nothing runnable may hide runnable work behind it: such a lane counts\n -- once, and the claim looks behind its blocked deliveries.\n SELECT GREATEST(count(*) FILTER (\n WHERE due.key IS NULL OR (due.position = 1 AND NOT EXISTS (\n SELECT 1 FROM ${deliveries} AS earlier\n WHERE earlier.lane = due.lane AND earlier.handler = due.handler AND earlier.key = due.key\n AND earlier.status = 'pending' AND earlier.key IS NOT NULL AND earlier.sequence < due.sequence\n ))\n ), CASE WHEN count(*) >= ${LANE_DEPTH_CAP} THEN 1 ELSE 0 END) AS count\n FROM (\n SELECT window_rows.*,\n row_number() OVER (PARTITION BY window_rows.handler, window_rows.key ORDER BY window_rows.sequence) AS position\n FROM (\n SELECT delivery.lane, delivery.handler, delivery.key, delivery.sequence FROM ${deliveries} AS delivery\n WHERE delivery.lane = lane_candidate.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n ORDER BY delivery.available_at, delivery.id\n LIMIT ${LANE_DEPTH_CAP}\n ) AS window_rows\n ) AS due\n ) AS depth\n WHERE NOT lane_candidate.running AND depth.count > 0\n ) AS runnable\n`;\n }\n\n /** Locks the chosen free lanes that did not change hands and picks from them. */\n #freeLaneTake(): string {\n const lanes = this.#names.lanes;\n return `), free_locked AS MATERIALIZED (\n SELECT lane.lane, lane.epoch, lane.in_flight, lane.lease_owner, lane.lease_expires_at\n FROM ${lanes} AS lane\n WHERE lane.lane IN (\n SELECT chosen.lane FROM free_depth AS chosen\n WHERE chosen.rank <= ${INITIAL_FREE_LANES} OR chosen.due_before < (SELECT count FROM wanted)\n )\n AND ${freeLane('lane')}\n ORDER BY lane.lane\n FOR UPDATE SKIP LOCKED\n), free_scope AS MATERIALIZED (\n -- A lane whose locked row is not the one the snapshot saw changed hands meanwhile: left for a later claim.\n SELECT locked.lane, locked.epoch + 1 AS epoch, '{}'::text[] AS in_flight\n FROM free_locked AS locked\n JOIN free_lanes AS seen ON seen.lane = locked.lane\n WHERE locked.epoch = seen.epoch AND locked.in_flight = seen.in_flight\n AND locked.lease_owner IS NOT DISTINCT FROM seen.lease_owner\n AND locked.lease_expires_at IS NOT DISTINCT FROM seen.lease_expires_at\n), ${this.#candidateStatements.candidates('free', { scope: 'free_scope', running: null, limit: '(SELECT count FROM wanted)' })}`;\n }\n\n /** The picked deliveries of held and taken lanes with their events, and the picks per lane. */\n #claimPicks(): string {\n const deliveries = this.#names.deliveries;\n return `, claim_scope AS MATERIALIZED (\n SELECT held_scope.lane, held_scope.epoch FROM held_scope\n UNION ALL\n SELECT free_scope.lane, free_scope.epoch FROM free_scope\n), picked_rows AS MATERIALIZED (\n SELECT candidates.available_at AS due_at, delivery.id AS delivery_id, delivery.lane::int AS lane,\n scope.epoch::text AS epoch, delivery.claims AS claims, delivery.handler, delivery.key AS delivery_key, delivery.sequence::text AS sequence, (delivery.attempts + 1)::int AS attempt,\n ${eventColumns('event')}\n FROM (\n SELECT held_candidates.id, held_candidates.lane, held_candidates.available_at FROM held_candidates\n UNION ALL\n SELECT free_candidates.id, free_candidates.lane, free_candidates.available_at FROM free_candidates\n ) AS candidates\n JOIN claim_scope AS scope ON scope.lane = candidates.lane\n JOIN ${deliveries} AS delivery ON delivery.id = candidates.id\n JOIN ${this.#names.events} AS event ON event.id = delivery.event_id\n), by_lane AS (\n SELECT picked_rows.lane, array_agg(picked_rows.delivery_id) AS ids FROM picked_rows GROUP BY picked_rows.lane\n`;\n }\n\n /** Records the picks in the held lanes and takes the free lanes that yielded picks. */\n #claimRecord(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `), still_running AS (\n -- The retained ids come from the locked \\`held\\` rows, not from the lane table: a claim that waited for the lock\n -- must see the in-flight list the claim before it recorded, which the statement snapshot may not.\n SELECT held.lane, array_agg(delivery.id) AS ids\n FROM by_lane\n JOIN held ON held.lane = by_lane.lane\n CROSS JOIN LATERAL unnest(held.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n GROUP BY held.lane\n), extended AS (\n UPDATE ${lanes} AS lane\n SET in_flight = COALESCE(still_running.ids, '{}') || by_lane.ids,\n lease_expires_at = GREATEST(lane.lease_expires_at, $5::timestamptz)\n FROM by_lane\n JOIN held_scope ON held_scope.lane = by_lane.lane\n LEFT JOIN still_running ON still_running.lane = by_lane.lane\n WHERE lane.lane = by_lane.lane\n RETURNING lane.lane\n), taken AS (\n UPDATE ${lanes} AS lane\n SET epoch = free_scope.epoch, lease_owner = $4::text, lease_expires_at = $5::timestamptz,\n in_flight = by_lane.ids, claim_floor = $6::bigint\n FROM free_scope\n JOIN by_lane ON by_lane.lane = free_scope.lane\n WHERE lane.lane = free_scope.lane\n RETURNING lane.lane\n`;\n }\n\n /** Frees the held lanes that yielded nothing and run nothing, and selects the result rows. */\n #claimRelease(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `), saturated_lanes AS (\n SELECT held_window.lane FROM held_window GROUP BY held_window.lane HAVING count(*) >= ${LANE_SCAN_WINDOW}\n), freed AS (\n UPDATE ${lanes} AS lane\n SET lease_owner = NULL, lease_expires_at = NULL, in_flight = '{}'\n FROM held\n WHERE lane.lane = held.lane\n AND lane.lane NOT IN (SELECT lane FROM by_lane)\n AND lane.lane NOT IN (SELECT lane FROM saturated_lanes)\n AND (SELECT count(*) FROM held_window) < ${CLAIM_SCAN_WINDOW}\n AND NOT (SELECT value FROM stale)\n AND ${noRunningDelivery(this.#names, 'lane')}\n RETURNING lane.lane\n)\nSELECT (SELECT value FROM stale) AS stale,\n EXISTS (SELECT 1 FROM free_lanes WHERE free_lanes.running) AS takeover_waiting,\n (SELECT count(*) FROM free_lanes) = (SELECT count FROM wanted) + ${FREE_LANE_SURPLUS} AS unexamined_free_lanes,\n (\n SELECT COALESCE(jsonb_agg(delivery.id), '[]'::jsonb)\n FROM held\n CROSS JOIN LATERAL unnest(held.in_flight) AS flying (id)\n JOIN ${deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'\n )::text AS running_ids,\n (SELECT COALESCE(jsonb_agg(held.lane), '[]'::jsonb) FROM held)::text AS examined_lanes,\n picked.*\nFROM (SELECT 1) AS anchor\nLEFT JOIN picked_rows AS picked ON true\nORDER BY picked.due_at, picked.delivery_id`;\n }\n\n /**\n * Takes up to `$3` free lanes (no lease, or an expired one) that have a due\n * delivery of the requested handlers, the ones with the oldest due delivery\n * first. Parameters: `[now, handlersJson, laneCount, leaseOwner, leaseExpiresAt, generation]`.\n * The lane gets the owner's `generation` as its `claim_floor`. A lane the owner itself holds under a live\n * lease with a lower floor was taken by a claim statement that reached the server after its caller gave up\n * and the owner reconciled (or by an earlier incarnation of the same owner): it is taken over like the lane of a\n * crashed worker, so its listed deliveries are charged an attempt.\n *\n * A taken lane gets a new epoch, which fences everything the previous owner\n * still holds. Deliveries the previous owner had in flight are the ones whose\n * attempt was never recorded (a claim writes no delivery row), so each of\n * them is charged one attempt here: a worker that crashes with a poison\n * message still runs it into the retry limit. Lanes another claimer has locked\n * are skipped, never waited for.\n */\n get takeFreeLanes(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `WITH picked AS (\n -- in_flight is read here, from the locked version of the lane: a settlement that committed after the\n -- statement took its snapshot has taken its delivery out of the list already and must not be charged again.\n SELECT free.lane, free.in_flight\n FROM ${lanes} AS free\n CROSS JOIN LATERAL (\n SELECT delivery.available_at, delivery.id\n FROM ${deliveries} AS delivery\n WHERE delivery.lane = free.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND ${HANDLER_PREDICATE}\n ORDER BY delivery.available_at, delivery.id\n LIMIT 1\n ) AS oldest\n WHERE free.lease_expires_at IS NULL OR free.lease_expires_at <= $1::timestamptz\n OR (free.lease_owner = $4::text AND free.claim_floor < $6::bigint)\n ORDER BY oldest.available_at, oldest.id\n LIMIT $3::int\n FOR UPDATE OF free SKIP LOCKED\n), charged AS (\n UPDATE ${deliveries} AS delivery SET attempts = delivery.attempts + 1, claims = delivery.claims + 1\n FROM (\n SELECT unnest(picked.in_flight) AS id FROM picked\n ) AS lost\n WHERE delivery.id = lost.id AND delivery.status = 'pending'\n RETURNING delivery.id\n), taken AS (\n UPDATE ${lanes} AS lane\n SET epoch = lane.epoch + 1, lease_owner = $4::text, lease_expires_at = $5::timestamptz, in_flight = '{}',\n claim_floor = $6::bigint\n FROM picked WHERE lane.lane = picked.lane\n RETURNING lane.lane, lane.epoch\n)\nSELECT lane::int AS lane, epoch::text AS epoch FROM taken ORDER BY lane`;\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { countChanged } from './statement-fragments.js';\n\n/** Statements that purge old deliveries and the events nothing references. */\nexport class PurgeStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Deletes one bounded batch of purgeable deliveries (or of the completion\n * history) and returns the event id of each deleted row. Parameters:\n * `[cutoff, batchSize]`. `FOR UPDATE SKIP LOCKED` keeps purge from waiting\n * on, or being waited on by, anything.\n */\n purgeCompletedBatch(): string {\n return this.#purgeBatch(this.#names.deliveries, {\n condition: `status = 'completed' AND completed_at < $1::timestamptz`,\n orderColumn: 'completed_at',\n });\n }\n\n purgeCompletionHistoryBatch(): string {\n return this.#purgeBatch(this.#names.completions, {\n condition: `completed_at < $1::timestamptz`,\n orderColumn: 'completed_at',\n });\n }\n\n purgeDeadBatch(): string {\n return this.#purgeBatch(this.#names.deliveries, {\n condition: `status = 'dead' AND updated_at < $1::timestamptz`,\n orderColumn: 'updated_at',\n });\n }\n\n /**\n * Selects and locks one bounded batch of events created before the cutoff\n * that no delivery references and that never had a delivery complete (those\n * are measured from their completion, see {@link lockCompletedOrphanEventsBatch}).\n * Parameters: `[cutoff, batchSize]`. The ids go through\n * {@link deleteOrphanEventsWithoutCompletion} or {@link deleteExpiredCompletedOrphanEvents}, which re-check under a fresh snapshot.\n */\n get lockOrphanEventsBatch(): string {\n return `SELECT event.id FROM ${this.#names.events} AS event\nWHERE event.created_at < $1::timestamptz\n AND ${this.#unreferenced('event')}\n AND NOT EXISTS (SELECT 1 FROM ${this.#names.eventCompletions} AS completion WHERE completion.event_id = event.id)\nORDER BY event.created_at, event.id\nLIMIT $2::int\nFOR UPDATE OF event SKIP LOCKED`;\n }\n\n /**\n * Like {@link lockOrphanEventsBatch} for events that had a delivery complete:\n * they go once their last completion is older than the cutoff, however old the\n * event itself is. Parameters: `[cutoff, batchSize]`.\n */\n get lockCompletedOrphanEventsBatch(): string {\n return `SELECT event.id FROM ${this.#names.events} AS event\nJOIN ${this.#names.eventCompletions} AS completion ON completion.event_id = event.id\nWHERE completion.completed_at < $1::timestamptz\n AND ${this.#unreferenced('event')}\nORDER BY completion.completed_at, event.id\nLIMIT $2::int\nFOR UPDATE OF event SKIP LOCKED`;\n }\n\n /**\n * Locks the given events, skipping any that a concurrent transaction is\n * referencing from a new delivery (a foreign key check holds `FOR KEY\n * SHARE`, which conflicts with this lock). Parameters: `[eventIdsJson]`.\n */\n get lockEvents(): string {\n return `SELECT id FROM ${this.#names.events}\nWHERE id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\nFOR UPDATE SKIP LOCKED`;\n }\n\n /**\n * Deletes events that no delivery references and whose last completion is older than\n * `$2`, checked again under the fresh snapshot of this statement: a completion recorded\n * after the sweep selected the event moves its time and keeps the event. Parameters:\n * `[eventIdsJson, cutoff]`.\n */\n get deleteExpiredCompletedOrphanEvents(): string {\n return countChanged(`DELETE FROM ${this.#names.events} AS event\nWHERE event.id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\n AND ${this.#unreferenced('event')}\n AND EXISTS (\n SELECT 1 FROM ${this.#names.eventCompletions} AS completion\n WHERE completion.event_id = event.id AND completion.completed_at < $2::timestamptz\n )`);\n }\n\n /**\n * Deletes locked events that no delivery references and that never had a delivery complete.\n * It must run as a statement of its own after {@link lockEvents}: it then takes a fresh\n * snapshot that includes every delivery committed before the lock was granted, so an event\n * that just gained a delivery is never cascaded away. Keeps events that had a delivery complete:\n * deleting dead letters must not shorten the retention of completed work.\n */\n get deleteOrphanEventsWithoutCompletion(): string {\n return countChanged(`DELETE FROM ${this.#names.events} AS event\nWHERE event.id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb)))\n AND ${this.#unreferenced('event')}\n AND NOT EXISTS (SELECT 1 FROM ${this.#names.eventCompletions} AS completion WHERE completion.event_id = event.id)`);\n }\n\n /** True when no delivery and no completion history record references the event. */\n #unreferenced(eventAlias: string): string {\n const history = this.#names.completionHistory\n ? ` AND NOT EXISTS (SELECT 1 FROM ${this.#names.completions} AS done WHERE done.event_id = ${eventAlias}.id)`\n : '';\n return `NOT EXISTS (SELECT 1 FROM ${this.#names.deliveries} AS delivery WHERE delivery.event_id = ${eventAlias}.id)${history}`;\n }\n\n #purgeBatch(\n table: string,\n { condition, orderColumn }: { readonly condition: string; readonly orderColumn: string },\n ): string {\n return `WITH batch AS MATERIALIZED (\n SELECT id FROM ${table}\n WHERE ${condition}\n ORDER BY ${orderColumn}, id\n LIMIT $2::int\n FOR UPDATE SKIP LOCKED\n), deleted AS (\n DELETE FROM ${table} AS delivery USING batch WHERE delivery.id = batch.id RETURNING delivery.event_id\n)\nSELECT event_id FROM deleted`;\n }\n}\n","import type { DeliveryQuery } from '@relaybus/core';\nimport type { PostgresParameter } from './executor.js';\nimport type { PostgresNames } from './names.js';\nimport { isoText } from './sql-fragments.js';\nimport {\n countChanged,\n eventColumns,\n noRunningDelivery,\n type PostgresStatement,\n} from './statement-fragments.js';\n\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** The bound placeholders of the filters of a listing; undefined where the query has none. */\ntype ListFilters = {\n readonly handler: string | undefined;\n readonly eventType: string | undefined;\n readonly eventId: string | undefined;\n readonly status: string | undefined;\n};\n\n/** Binds the filters, then the limit, as parameters in that order. */\nfunction bindListFilters(query: DeliveryQuery): {\n parameters: PostgresParameter[];\n filters: ListFilters;\n limit: string;\n} {\n const parameters: PostgresParameter[] = [];\n const bind = (value: PostgresParameter): string => {\n parameters.push(value);\n return `$${parameters.length}::${typeof value === 'number' ? 'int' : 'text'}`;\n };\n const filters = {\n handler: query.handler === undefined ? undefined : bind(query.handler),\n eventType: query.eventType === undefined ? undefined : bind(query.eventType),\n eventId: query.eventId === undefined ? undefined : bind(query.eventId),\n status: query.status === undefined ? undefined : bind(query.status),\n };\n const limit = bind(query.limit ?? DEFAULT_LIST_LIMIT);\n return { parameters, filters, limit };\n}\n\n/** The conditions of the handler, event type and event id filters on the rows of `alias`. */\nfunction listConditions(filters: ListFilters, alias: string): string[] {\n return [\n ...(filters.handler === undefined ? [] : [`${alias}.handler = ${filters.handler}`]),\n ...(filters.eventType === undefined ? [] : [`event.type = ${filters.eventType}`]),\n ...(filters.eventId === undefined ? [] : [`${alias}.event_id = ${filters.eventId}`]),\n ];\n}\n\n/** Statements for listing, requeueing and statistics. */\nexport class QueryStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /** Parameters: `[deliveryIdsJson, now]`. The dead rows are locked in id order first. */\n get requeue(): string {\n const deliveries = this.#names.deliveries;\n return countChanged(`WITH dead AS MATERIALIZED (\n SELECT delivery.id FROM ${deliveries} AS delivery\n WHERE delivery.id = ANY (ARRAY(SELECT jsonb_array_elements_text($1::jsonb))) AND delivery.status = 'dead'\n ORDER BY delivery.id\n FOR NO KEY UPDATE\n)\nUPDATE ${deliveries} AS delivery\nSET status = 'pending', attempts = 0, available_at = $2::timestamptz, updated_at = $2::timestamptz\nFROM dead\nWHERE delivery.id = dead.id AND delivery.status = 'dead'`);\n }\n\n /**\n * Builds the filtered, creation-ordered listing. A delivery is `processing`\n * while its row exists as `pending` and its lane lists its id; its attempt\n * count, lease owner and lease expiry then come from the claim and the lane.\n * Records of the completion history (when kept) are listed as `completed`.\n */\n listDeliveries(query: DeliveryQuery): PostgresStatement {\n const { parameters, filters, limit } = bindListFilters(query);\n const current = this.#currentDeliveries(filters);\n const includeHistory =\n this.#names.completionHistory && (query.status === undefined || query.status === 'completed');\n if (!includeHistory) {\n return {\n sql: `${current}\\nORDER BY delivery.created_at, delivery.id\\nLIMIT ${limit}`,\n parameters,\n };\n }\n const history = this.#completionHistory(filters);\n return {\n sql: `SELECT * FROM (\\n${current}\\nUNION ALL\\n${history}\\n) AS listed\\nORDER BY created_at, delivery_id\\nLIMIT ${limit}`,\n parameters,\n };\n }\n\n /** The deliveries that still exist, with a running one reported as `processing`. */\n #currentDeliveries(filters: ListFilters): string {\n const inFlight = `(delivery.status = 'pending' AND delivery.id = ANY (lane.in_flight))`;\n const whereCurrent = [\n ...listConditions(filters, 'delivery'),\n ...(filters.status === undefined\n ? []\n : [\n `(CASE WHEN ${inFlight} THEN 'processing' ELSE delivery.status END) = ${filters.status}`,\n ]),\n ];\n return `SELECT delivery.id AS delivery_id, delivery.handler,\n CASE WHEN ${inFlight} THEN 'processing' ELSE delivery.status END AS status,\n (delivery.attempts + CASE WHEN ${inFlight} THEN 1 ELSE 0 END)::int AS attempts,\n ${isoText('delivery.available_at')} AS available_at,\n CASE WHEN ${inFlight} THEN lane.lease_owner END AS lease_owner,\n CASE WHEN ${inFlight} THEN ${isoText('lane.lease_expires_at')} END AS lease_expires_at,\n delivery.last_error::text AS last_error,\n ${isoText('delivery.created_at')} AS created_at,\n ${isoText('delivery.updated_at')} AS updated_at,\n ${isoText('delivery.completed_at')} AS completed_at,\n ${eventColumns('event')}\nFROM ${this.#names.deliveries} AS delivery\nJOIN ${this.#names.lanes} AS lane ON lane.lane = delivery.lane\nJOIN ${this.#names.events} AS event ON event.id = delivery.event_id\n${whereCurrent.length === 0 ? '' : `WHERE ${whereCurrent.join(' AND ')}`}`;\n }\n\n /** The completion history records, listed as `completed`. */\n #completionHistory(filters: ListFilters): string {\n const common = (alias: string): string[] => listConditions(filters, alias);\n return `SELECT done.id AS delivery_id, done.handler, 'completed' AS status, done.attempts,\n ${isoText('done.available_at')} AS available_at,\n NULL AS lease_owner,\n NULL AS lease_expires_at,\n NULL AS last_error,\n ${isoText('done.created_at')} AS created_at,\n ${isoText('done.completed_at')} AS updated_at,\n ${isoText('done.completed_at')} AS completed_at,\n ${eventColumns('event')}\nFROM ${this.#names.completions} AS done\nJOIN ${this.#names.events} AS event ON event.id = done.event_id\n${common('done').length === 0 ? '' : `WHERE ${common('done').join(' AND ')}`}`;\n }\n\n /**\n * Counts of rows by stored status (`pending` includes running deliveries;\n * `completed` rows exist only after an upgrade from 0.1.0). Each count is\n * answered from a partial index.\n */\n get countByStatus(): string {\n const deliveries = this.#names.deliveries;\n return ['pending', 'dead', 'completed']\n .map(\n (status) =>\n `SELECT '${status}' AS status, count(*)::text AS count FROM ${deliveries} WHERE status = '${status}'`,\n )\n .join('\\nUNION ALL\\n');\n }\n\n /** Deliveries that are running: listed by a lane and still pending as rows. */\n get countRunning(): string {\n return `SELECT count(*)::text AS count\nFROM ${this.#names.lanes} AS lane\nCROSS JOIN LATERAL unnest(lane.in_flight) AS flying (id)\nJOIN ${this.#names.deliveries} AS delivery ON delivery.id = flying.id AND delivery.status = 'pending'`;\n }\n\n get countCompletionHistory(): string {\n return `SELECT count(*)::text AS count FROM ${this.#names.completions}`;\n }\n\n /**\n * Oldest instant at which a delivery became claimable: `available_at` of a\n * pending delivery that nobody runs, or the lease expiry of a lane that runs\n * deliveries. Parameters: `[now]`.\n */\n get oldestDue(): string {\n const deliveries = this.#names.deliveries;\n const lanes = this.#names.lanes;\n return `SELECT ${isoText('min(due.due_at)')} AS oldest_due_at FROM (\n SELECT waiting.available_at AS due_at\n FROM ${lanes} AS lane\n CROSS JOIN LATERAL (\n SELECT delivery.available_at FROM ${deliveries} AS delivery\n WHERE delivery.lane = lane.lane AND delivery.status = 'pending'\n AND delivery.available_at <= $1::timestamptz AND delivery.id <> ALL (lane.in_flight)\n ORDER BY delivery.available_at LIMIT 1\n ) AS waiting\n UNION ALL\n SELECT lane.lease_expires_at AS due_at\n FROM ${lanes} AS lane\n WHERE lane.lease_expires_at <= $1::timestamptz AND NOT ${noRunningDelivery(this.#names, 'lane')}\n) AS due`;\n }\n}\n","import type { PostgresNames } from './names.js';\n\n/** Statements of `setup`: the setup lock and the schema check. */\nexport class SetupStatements {\n readonly #names: PostgresNames;\n\n constructor(names: PostgresNames) {\n this.#names = names;\n }\n\n /**\n * Lock advisory key text for {@link setupLock}. It is derived from the schema\n * name only, so stores with different table prefixes in one schema also\n * serialize their `CREATE SCHEMA IF NOT EXISTS`, which is not race-free.\n */\n get setupLockKey(): string {\n return `relaybus:${this.#names.schema}`;\n }\n\n /**\n * The state of the schema, taking no table lock. Parameters: `[marker]`. Columns: `marked`, whether\n * the lane table carries `marker` as its comment (the schema statements that produce it already\n * ran), and `payload_json`, whether the payload and headers columns of the event table are both\n * `json` (the conversion of the `jsonb` columns of schemas before 0.4.1 ran).\n */\n get schemaCurrent(): string {\n // Reads the catalogs with the statement's snapshot. `to_regclass` and `obj_description` would go\n // through the backend's catalog caches, which keep \"no such table\" until the session processes\n // invalidations; a setup that waited for the setup lock would then miss a schema created meanwhile.\n return `SELECT EXISTS (\n SELECT 1 FROM pg_catalog.pg_class AS c\n JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace\n JOIN pg_catalog.pg_description AS d\n ON d.objoid = c.oid AND d.classoid = 'pg_catalog.pg_class'::regclass AND d.objsubid = 0\n WHERE n.nspname = '${this.#names.schema}' AND c.relname = '${this.#names.lanesTableName}' AND d.description = $1::text\n) AS marked, (\n SELECT count(*) FROM pg_catalog.pg_attribute AS a\n JOIN pg_catalog.pg_class AS c ON c.oid = a.attrelid\n JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace\n WHERE n.nspname = '${this.#names.schema}' AND c.relname = '${this.#names.eventsTableName}'\n AND a.attname IN ('payload', 'headers') AND a.atttypid = 'pg_catalog.json'::pg_catalog.regtype\n AND NOT a.attisdropped\n) = 2 AS payload_json`;\n }\n\n /**\n * Takes the setup lock. Returns a boolean column rather than the `void` of the lock function, which\n * some libraries cannot read (Prisma's raw queries reject a `void` column).\n */\n get setupLock(): string {\n return 'SELECT true AS locked FROM pg_advisory_xact_lock(hashtextextended($1::text, 0))';\n }\n}\n","import type { PostgresNames } from './names.js';\nimport { AppendStatements } from './statements-append.js';\nimport { ClaimStatements } from './statements-claim.js';\nimport { CompletionStatements } from './statements-completion.js';\nimport { LaneStatements } from './statements-lanes.js';\nimport { PurgeStatements } from './statements-purge.js';\nimport { QueryStatements } from './statements-queries.js';\nimport { SetupStatements } from './statements-setup.js';\n\nexport type { PostgresStatement } from './statement-fragments.js';\n\n/**\n * SQL text for every operation of the store. Statements take their data as\n * parameters; only validated identifiers are interpolated. Documents travel\n * as one JSON text parameter expanded server-side with `jsonb_to_recordset`,\n * which keeps the statements identical across drivers and avoids array\n * literal encoding differences. Events go through `json_to_recordset` instead:\n * it hands each payload and headers object to their `json` columns as the\n * exact text the producer serialized, key order included.\n *\n * Leasing is per lane, not per delivery. A lane row carries the owner, an\n * `epoch` (the fencing token: it grows every time the lane changes hands) and\n * `in_flight`, the ids of the deliveries the owner has claimed. A claim\n * therefore writes one lane row for a whole batch and no delivery row; a\n * completion deletes delivery rows and writes no lane row. `in_flight` may\n * list ids that were completed (their rows are gone): a delivery is in flight\n * only while its row exists as `pending` and its id is listed.\n *\n * **Lock order.** Every statement that can wait for a lock takes its locks in this order, and rows of\n * one table in key order, so no two of them can wait for each other in a cycle:\n *\n * 1. the setup advisory lock and the schema DDL ({@link SetupStatements.setupLock}); only while the schema is created or\n * upgraded, never on a current schema (see `PostgresEventStore.setup`);\n * 2. `key_sequences` rows, in key order ({@link AppendStatements.insertFreshEvents});\n * 3. `events` rows, in id order ({@link AppendStatements.lockExistingEvents}, the inserts of a publish, the foreign key\n * checks of new deliveries and completions);\n * 4. `lanes` rows, in lane order: `FOR NO KEY UPDATE` for the owner's held lanes, `FOR KEY SHARE` for\n * completions, `FOR UPDATE SKIP LOCKED` (never waits) for lanes taken from others;\n * 5. `deliveries` rows, only of lanes locked in step 4 (claims, completions, reschedules, takeovers),\n * or inserted new (publish), or `dead` ones in id order ({@link QueryStatements.requeue});\n * 6. `event_completions` rows, in event id order ({@link CompletionStatements.complete}).\n *\n * Publishing never touches `lanes`, and dispatching never touches `key_sequences`. Purging only takes\n * `SKIP LOCKED` row locks and then deletes rows nobody references, so it never waits in a cycle either.\n * A caller's own transaction (a transactional handler that completes and publishes) adds the locks of\n * its own statements in the order it runs them; as documented on `append`, keys appended in opposite\n * orders by two such transactions can still deadlock, and the database then rolls one back.\n */\nexport class PostgresStatements {\n readonly setup: SetupStatements;\n readonly append: AppendStatements;\n readonly lanes: LaneStatements;\n readonly claim: ClaimStatements;\n readonly completion: CompletionStatements;\n readonly queries: QueryStatements;\n readonly purge: PurgeStatements;\n\n constructor(names: PostgresNames) {\n this.setup = new SetupStatements(names);\n this.append = new AppendStatements(names);\n this.lanes = new LaneStatements(names);\n this.claim = new ClaimStatements(names);\n this.completion = new CompletionStatements(names);\n this.queries = new QueryStatements(names);\n this.purge = new PurgeStatements(names);\n }\n}\n","import {\n type AppendEntry,\n type AppendResult,\n type ClaimRequest,\n type ClaimedDelivery,\n type CloseOptions,\n type DeliveryQuery,\n type DeliveryRecord,\n type ErrorInfo,\n type EventStore,\n type EventStoreStatistics,\n type EventStoreTransactionOptions,\n type LeaseReference,\n type PurgeRequest,\n type PurgeResult,\n type RelayBusLogger,\n type TransactionIsolationLevel,\n TRANSACTION_ISOLATION_LEVELS,\n} from '@relaybus/core';\nimport { HandedOutLedger } from '@relaybus/core/internal';\nimport { Client, Pool, type PoolClient } from 'pg';\nimport type { PostgresExecutor } from './executor.js';\nimport { resolvePostgresNames } from './names.js';\nimport { NotificationListener } from './notification-listener.js';\nimport { PgExecutor } from './pg-executor.js';\nimport { withRootPool } from './root-pool-executor.js';\nimport { isPostgresSerializationFailure } from './serialization-failure.js';\nimport { PostgresAppend } from './postgres-append.js';\nimport { PostgresClaims } from './postgres-claim.js';\nimport { PostgresCompletion } from './postgres-completion.js';\nimport { OwnedConnections } from './owned-connections.js';\nimport { PostgresMaintenance } from './postgres-maintenance.js';\nimport { PostgresSetup } from './postgres-setup.js';\nimport type { PostgresStoreState } from './postgres-store-state.js';\nimport { resolveStoreSettings, type PostgresEventStoreOptions } from './postgres-store-options.js';\nimport { createPostgresSchemaStatements, version040SchemaMarker } from './schema.js';\nimport { PostgresStatements } from './statements.js';\nimport { inIsolatedTransaction } from './transaction-isolation.js';\nimport { inBudgetedTransaction } from './transaction-timeouts.js';\n\nexport type {\n PostgresConnectionOptions,\n PostgresEventStoreOptions,\n PostgresEventStoreSettings,\n PostgresExecutorOptions,\n PostgresPoolOptions,\n PostgresWakeUp,\n} from './postgres-store-options.js';\n\n/**\n * PostgreSQL {@link EventStore} (PostgreSQL 13 or newer).\n *\n * The transaction handle is whatever the chosen driver uses: a `pg`\n * `PoolClient` by default, or a Kysely / Knex / TypeORM / Drizzle / Prisma\n * transaction through the adapters in `@relaybus/postgres/<library>`. Events\n * published with that handle commit and roll back together with the caller's\n * own writes.\n *\n * Guarantees:\n * - **Atomic publish.** Events and deliveries are written in the caller's transaction.\n * - **Per-key order.** Each key has a counter row in the key-sequence table.\n * Publishing locks that row and holds the lock until commit, so two\n * transactions publishing the same key are serialized and sequence order\n * equals commit order. Claiming then hands out only the lowest unfinished\n * sequence of a (handler, key), and all deliveries of a key live in one lane,\n * so one worker at a time sees them.\n * - **Lane leases.** Workers lease lanes (256 hash buckets of the ordering key\n * or event id), not single deliveries. A claim writes one lane row for a\n * whole batch and never writes a delivery row; a completion deletes the\n * delivery rows. Delivery rows are therefore inserted once and deleted once,\n * which leaves no dead index entries from updates on the normal path.\n * - **Fenced state changes.** Complete, reschedule, bury and extend only apply\n * with the epoch of the lane lease that claimed the delivery. A lane taken\n * over by another worker gets a new epoch, which fences everything the\n * previous holder still runs. Completion takes a key-share lock on the lane\n * row, so it cannot interleave with a takeover.\n * - **Attempts survive crashes.** A claim records which deliveries it put in\n * flight in the lane row. If the holder dies, the next holder charges one\n * attempt to each of them, so a poison message still reaches the retry limit.\n * - **App clock.** Every timestamp comes from the `now` the caller passes in,\n * never from the database clock.\n *\n * Completed deliveries are deleted. Pass `completionHistory: true` to keep an\n * append-only record for `listDeliveries({ status: 'completed' })`.\n */\nexport class PostgresEventStore<TTransaction = PoolClient> implements EventStore<TTransaction> {\n readonly #state: PostgresStoreState<TTransaction>;\n readonly #appender: PostgresAppend<TTransaction>;\n readonly #claims: PostgresClaims<TTransaction>;\n readonly #completion: PostgresCompletion<TTransaction>;\n readonly #maintenance: PostgresMaintenance<TTransaction>;\n readonly #setup: PostgresSetup<TTransaction>;\n readonly #owned = new OwnedConnections();\n\n constructor(options: PostgresEventStoreOptions<TTransaction>) {\n const { purgeBatchSize, wakeUp, queryOptions } = resolveStoreSettings(options);\n const names = resolvePostgresNames(options);\n const statements = new PostgresStatements(names);\n const schemaStatements = createPostgresSchemaStatements(options);\n const logger = options.logger ?? console;\n const { executor, pool, ownedPool } = connect(options, { logger, owned: this.#owned });\n const state: PostgresStoreState<TTransaction> = {\n executor,\n statements,\n schemaStatements,\n setupLockKey: statements.setup.setupLockKey,\n schemaMarker: version040SchemaMarker(options),\n purgeBatchSize,\n completionHistory: names.completionHistory,\n logger,\n queryOptions,\n notifies: wakeUp === 'notify',\n query: ({ sql, parameters, transaction }) =>\n executor.query(sql, parameters, transaction, queryOptions),\n handedOut: new HandedOutLedger(),\n unreconciled: new Set(),\n generations: new Map(),\n drainingOwners: new Set(),\n ownedPool,\n pool,\n notificationChannel: names.notificationChannel,\n lastNotificationAt: Number.NEGATIVE_INFINITY,\n trailingNotification: undefined,\n closed: false,\n ownTransactions: new Map(),\n };\n this.#state = state;\n this.#appender = new PostgresAppend(state);\n this.#claims = new PostgresClaims(state);\n this.#completion = new PostgresCompletion(state);\n this.#maintenance = new PostgresMaintenance(state);\n this.#setup = new PostgresSetup(state, options);\n }\n\n /**\n * Creates the schema, tables and indexes if they do not exist. Safe to call\n * from many processes at once: a transaction-scoped advisory lock serializes\n * the DDL, so racing `CREATE TABLE IF NOT EXISTS` statements cannot collide.\n * When the lane table already carries the schema marker ({@link version040SchemaMarker})\n * and the payload columns are `json`, nothing runs and no table is locked, so instances\n * that start next to running dispatchers cannot deadlock with their claims.\n * Skip it (`setupStore: false`) when a migration tool applies\n * `createPostgresSchemaSql()` instead.\n */\n async setup(): Promise<void> {\n await this.#setup.run();\n }\n\n /** Every level PostgreSQL has (it runs `read uncommitted` as `read committed`, which the bus does not offer). */\n readonly isolationLevels: readonly TransactionIsolationLevel[] = TRANSACTION_ISOLATION_LEVELS;\n\n /**\n * True for a serialization failure (SQLSTATE `40001`) raised through any executor, including\n * Prisma's `P2034` and the wrappers of TypeORM and Drizzle; a custom executor can add its own\n * test with {@link PostgresExecutor.isSerializationFailure}.\n */\n isSerializationFailure(error: unknown): boolean {\n return (\n isPostgresSerializationFailure(error) ||\n this.#state.executor.isSerializationFailure?.(error) === true\n );\n }\n\n /**\n * Runs `work` in a transaction of the executor. With `options.timeoutMs` (from `bus.transaction`)\n * the server holds the transaction to the budget: `statement_timeout`, and for executors with\n * `sessionTimeouts` (`pg`) also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+,\n * `transaction_timeout`, all scoped to the transaction. An executor with `transactionWithBudget`\n * (`PgExecutor`) sets them with `BEGIN`, so the budget costs no round trip; on a pool the store\n * created they are kept per connection and sent only when the connection does not have them yet.\n * With `options.isolationLevel` the transaction runs at that level: `PgExecutor` sends it with\n * `BEGIN ISOLATION LEVEL ...` (no extra round trip), any other executor as `SET TRANSACTION\n * ISOLATION LEVEL ...` before the budget statement.\n */\n async transaction<T>(\n work: (transaction: TTransaction) => Promise<T>,\n options?: EventStoreTransactionOptions,\n ): Promise<T> {\n const own = { wake: false };\n const tracked = async (transaction: TTransaction): Promise<T> => {\n this.#state.ownTransactions.set(transaction, own);\n try {\n return await work(transaction);\n } finally {\n this.#state.ownTransactions.delete(transaction);\n }\n };\n const result = await this.#open(tracked, options);\n if (own.wake) {\n this.#appender.wakeAfterCommit();\n }\n return result;\n }\n\n /** Opens the transaction `work` runs in: plain, held to the budget, or at an isolation level too. */\n #open<T>(\n work: (transaction: TTransaction) => Promise<T>,\n options: EventStoreTransactionOptions | undefined,\n ): Promise<T> {\n if (options === undefined) {\n return this.#state.executor.transaction(work);\n }\n const { timeoutMs, isolationLevel } = options;\n return isolationLevel === undefined\n ? inBudgetedTransaction(this.#state, { work, timeoutMs })\n : inIsolatedTransaction(this.#state, { work, timeoutMs, isolationLevel });\n }\n\n /**\n * Writes the entries in `transaction`, normally with one statement\n * (`AppendStatements.insertFreshEvents`): keyed events reserve their sequence numbers (locking\n * the key rows in sorted order, so publishers cannot deadlock inside one call), then the new events and\n * their deliveries are inserted, ordered by primary key, and one notification wakes the dispatchers\n * when a delivery is due now. Events that already existed get their missing handlers' deliveries in\n * two more statements. Two transactions that append keys in opposite order across several calls can\n * still deadlock (40P01); the database rolls one back and the caller retries.\n * A duplicate event id still consumes a sequence number; gaps are harmless\n * because only the order of sequences matters.\n */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n append(\n transaction: TTransaction,\n entries: readonly AppendEntry[],\n now: Date,\n ): Promise<AppendResult> {\n return this.#appender.append(transaction, { entries, now });\n }\n\n /**\n * Claims up to `limit` due deliveries, normally with one statement\n * (`LaneStatements.claimLanes`): from the lanes this owner already holds, then from free lanes\n * it takes in the same statement, recording the batch in the lane rows. A claim that would have to take\n * over a lane whose previous holder still runs deliveries under an expired lease continues in a\n * transaction that charges their lost attempts first, taking free lanes a few at a time (4, 8, 16, ...);\n * so does a claim whose statement kept seeing a lane it holds change under it, and one that came up\n * short with more free lanes left than it looked at. The step that fails after\n * the first one has recorded deliveries returns those instead of failing: a recorded delivery nobody\n * received would be held for a whole lease. See `ClaimStatements.claim` for the rules a delivery\n * must satisfy.\n */\n claim(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n return this.#claims.claim(request);\n }\n\n extendLease(lease: LeaseReference, leaseExpiresAt: Date): Promise<boolean> {\n // A database answers with a promise; Promise.resolve returns it as it is.\n return Promise.resolve(this.#completion.extendLease({ lease, leaseExpiresAt }));\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n complete(lease: LeaseReference, now: Date, transaction?: TTransaction): Promise<boolean> {\n return this.#completion.complete(lease, { now, transaction });\n }\n\n completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]> {\n return this.#completion.completeMany(leases, now);\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n reschedule(\n lease: LeaseReference,\n availableAt: Date,\n error: ErrorInfo,\n now: Date,\n ): Promise<boolean> {\n return Promise.resolve(\n this.#completion.changeClaim({\n lease,\n change: { kind: 'reschedule', availableAt, error, now },\n }),\n );\n }\n\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n bury(lease: LeaseReference, error: ErrorInfo, now: Date): Promise<boolean> {\n return Promise.resolve(\n this.#completion.changeClaim({ lease, change: { kind: 'bury', error, now } }),\n );\n }\n\n /** Returns a leased delivery to pending, due now, without counting the attempt. */\n release(lease: LeaseReference, now: Date): Promise<boolean> {\n return Promise.resolve(\n this.#completion.changeClaim({ lease, change: { kind: 'release', now } }),\n );\n }\n\n /**\n * Calls `listener` soon after a transaction that published deliveries due at once commits, in any\n * process: `append` sends one `pg_notify` per call (merged per transaction, none for delayed\n * deliveries), and this listens with `LISTEN` on a connection of its own, opened with the settings of\n * the store's pool (one connection more than the pool's `max`). A lost connection is replaced after a\n * second. Resolves with `undefined` for a store built on an `executor`, which has no connection of its\n * own to listen on, and with `wakeUp: 'poll'`: polling then finds new deliveries (and the bus still\n * wakes its own dispatcher).\n */\n async watchNewDeliveries(listener: () => void): Promise<(() => Promise<void>) | undefined> {\n if (this.#state.pool === undefined || !this.#state.notifies) {\n return undefined;\n }\n const options = this.#state.pool.options;\n const watcher = new NotificationListener(\n async () => {\n // A client of its own, with the pool's connection settings: the pool keeps all its connections.\n const client = new Client(options);\n this.#owned.track(client);\n await client.connect();\n return client;\n },\n this.#state.notificationChannel,\n listener,\n this.#state.logger,\n );\n await watcher.start();\n return () => watcher.close();\n }\n\n /** Frees the lanes `leaseOwner` holds that run no delivery, so other workers need not wait for the lease to expire. */\n relinquish(leaseOwner: string): Promise<void> {\n return this.#maintenance.relinquish(leaseOwner);\n }\n\n listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n return this.#maintenance.listDeliveries(query);\n }\n\n requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n return this.#maintenance.requeue(deliveryIds, now);\n }\n\n /**\n * Deletes purgeable deliveries in batches of `purgeBatchSize`, one short\n * transaction per batch, then the events those batches left without any\n * delivery. Finally, events created before the earliest given cutoff that\n * have no delivery at all are removed: they are what a publish leaves behind\n * when its last delivery was purged in the same instant, or when no handler\n * was subscribed. Events that a concurrent publish is attaching a delivery\n * to are skipped and kept.\n */\n purge(request: PurgeRequest): Promise<PurgeResult> {\n return this.#maintenance.purge(request);\n }\n\n statistics(now: Date): Promise<EventStoreStatistics> {\n return this.#maintenance.statistics(now);\n }\n\n /**\n * Ends the pool this store created from `connectionString`. Pools and executors you passed in stay\n * open. Once `options.signal` aborts (the shutdown deadline passed), the connections the store opened\n * itself are destroyed: queries still running on them fail at once instead of holding the shutdown.\n */\n async close(options: CloseOptions = {}): Promise<void> {\n this.#state.closed = true;\n this.#state.trailingNotification?.();\n this.#state.trailingNotification = undefined;\n const pool = this.#state.ownedPool;\n this.#state.ownedPool = undefined;\n const { signal } = options;\n const force = (): void => this.#owned.destroyAll();\n if (signal?.aborted === true) {\n force();\n }\n signal?.addEventListener('abort', force, { once: true });\n try {\n await pool?.end();\n } finally {\n signal?.removeEventListener('abort', force);\n }\n }\n}\n\n/**\n * The executor of the store: the one passed in, or a `pg` executor on the given pool or on a pool\n * of its own (`ownedPool`, which the store ends on close).\n */\nfunction connect<TTransaction>(\n options: PostgresEventStoreOptions<TTransaction>,\n { logger, owned }: { readonly logger: RelayBusLogger; readonly owned: OwnedConnections },\n): {\n executor: PostgresExecutor<TTransaction>;\n pool: Pool | undefined;\n ownedPool: Pool | undefined;\n} {\n if (options.executor !== undefined) {\n const { executor, pool } = options;\n return {\n executor:\n pool === undefined ? executor : withRootPool(executor, new PgExecutor(pool, { logger })),\n pool,\n ownedPool: undefined,\n };\n }\n const pool =\n options.pool ??\n new Pool({\n ...options.poolConfig,\n connectionString: options.connectionString,\n Client: owned.clientClass(),\n });\n let ownedPool: Pool | undefined;\n if (options.pool === undefined) {\n const poolLogger = options.logger ?? console;\n pool.on('error', (error) => {\n poolLogger.error(\n `[PostgresEventStore](connect) Idle connection failed, the pool replaces it | error=${error.message}`,\n );\n });\n ownedPool = pool;\n }\n // Without an executor the transaction type is PoolClient, as the default type argument states.\n // A pool of its own keeps the budget per connection; a pooler is what preparedStatements: false is for.\n const executor = new PgExecutor(pool, {\n logger,\n sessionBudget: ownedPool !== undefined && options.preparedStatements !== false,\n }) as unknown as PostgresExecutor<TTransaction>;\n return { executor, pool, ownedPool };\n}\n"]}