@relaybus/kafka 0.0.0-stage → 0.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cloudevents-codec.ts","../src/kafka-transport.ts"],"names":["RelayBusError","NonRetryableError","assertEventType","ConfigurationError","toErrorInfo","toMilliseconds"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n NonRetryableError,\n RelayBusError,\n assertEventType,\n type EventEnvelope,\n} from '@relaybus/core';\nimport type { KafkaBytes, KafkaIncomingHeaders, KafkaOutgoingHeaders } from './kafka-client.js';\n\n/** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */\nexport class InvalidKafkaMessageError extends RelayBusError {}\n\n/**\n * An event that cannot be written to Kafka: its payload is not representable as\n * JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or\n * its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).\n * Retrying cannot help, so it is a {@link NonRetryableError}.\n */\nexport class UnencodableEventError extends NonRetryableError {\n override name = 'UnencodableEventError';\n}\n\n/** The wire form of one event: a Kafka record in CloudEvents binary content mode. */\nexport interface EncodedMessage {\n readonly key: string | null;\n readonly value: string;\n readonly headers: Record<string, string>;\n}\n\n/** The parts of an incoming Kafka record the decoder reads. */\nexport interface DecodableMessage {\n readonly key: KafkaBytes | null;\n readonly value: KafkaBytes | null;\n readonly headers?: KafkaIncomingHeaders | undefined;\n /** Record timestamp in epoch milliseconds, used when `ce_time` is absent. */\n readonly timestamp?: string | undefined;\n}\n\nconst SPEC_VERSION = '1.0';\nconst CONTENT_TYPE = 'content-type';\nconst JSON_MEDIA_TYPE = 'application/json';\nconst CLOUDEVENTS_PREFIX = 'ce_';\nconst ESCAPE_PREFIX = 'x-relaybus-h-';\nconst RESERVED_PREFIXES = [CLOUDEVENTS_PREFIX, 'x-relaybus-'];\n\nconst HEADER = {\n specVersion: 'ce_specversion',\n id: 'ce_id',\n type: 'ce_type',\n source: 'ce_source',\n time: 'ce_time',\n subject: 'ce_subject',\n correlationId: 'ce_correlationid',\n causationId: 'ce_causationid',\n} as const;\n\nconst PROTOCOL_HEADERS: ReadonlySet<string> = new Set([...Object.values(HEADER), CONTENT_TYPE]);\n\nconst RFC3339_PATTERN = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/i;\n\nconst strictUtf8 = new TextDecoder('utf-8', { fatal: true });\nconst lenientUtf8 = new TextDecoder('utf-8');\n\n/**\n * Encodes an envelope as a CloudEvents Kafka binary-mode record: the value is\n * the JSON payload, the event attributes travel as `ce_*` headers.\n *\n * User headers that would collide with protocol names (`ce_*`, `content-type`,\n * `x-relaybus-*`) are stored under an `x-relaybus-h-` prefix and restored on\n * decode, so every header survives a round trip unchanged.\n */\nexport function encodeEnvelope(envelope: EventEnvelope): EncodedMessage {\n const value = serializePayload(envelope);\n const entries: [string, string][] = Object.entries(envelope.headers).map(\n ([name, headerValue]) => [escapeUserHeaderName(name), headerValue],\n );\n entries.push(\n [HEADER.specVersion, SPEC_VERSION],\n [HEADER.id, envelope.id],\n [HEADER.type, envelope.type],\n [HEADER.source, envelope.source],\n [HEADER.time, formatTime(envelope)],\n [CONTENT_TYPE, JSON_MEDIA_TYPE],\n );\n if (envelope.key !== null) {\n entries.push([HEADER.subject, envelope.key]);\n }\n if (envelope.correlationId !== null) {\n entries.push([HEADER.correlationId, envelope.correlationId]);\n }\n if (envelope.causationId !== null) {\n entries.push([HEADER.causationId, envelope.causationId]);\n }\n // fromEntries defines own properties, so a header named `__proto__` is kept as data.\n return { key: envelope.key, value, headers: Object.fromEntries(entries) };\n}\n\nfunction serializePayload(envelope: EventEnvelope): string {\n let value: string | undefined;\n try {\n value = JSON.stringify(envelope.payload);\n } catch (error) {\n throw new UnencodableEventError(\n `Event ${envelope.id} has a payload that JSON cannot represent: ${(error as Error).message}`,\n );\n }\n if (value === undefined) {\n throw new UnencodableEventError(\n `Event ${envelope.id} has a payload that JSON cannot represent (undefined, a function or a symbol)`,\n );\n }\n return value;\n}\n\nfunction formatTime(envelope: EventEnvelope): string {\n const year = envelope.occurredAt.getUTCFullYear();\n if (Number.isNaN(year) || year < 0 || year > 9999) {\n throw new UnencodableEventError(\n `Event ${envelope.id} has an occurredAt that is not an RFC 3339 instant (invalid date or year outside 0..9999)`,\n );\n }\n return envelope.occurredAt.toISOString();\n}\n\n/**\n * Decodes a Kafka record strictly: the CloudEvents attributes `ce_specversion`\n * (`1.0`), `ce_id`, `ce_type`, `ce_source`, a JSON `content-type` and a JSON\n * value are required. `ce_time` is optional in CloudEvents: when absent, the\n * Kafka record timestamp is used; when present it must be RFC 3339.\n *\n * @throws InvalidKafkaMessageError for anything else. It is the only error\n * thrown for malformed input, so callers can tell poison messages from bugs.\n */\nexport function decodeEnvelope(message: DecodableMessage): EventEnvelope {\n const headers = readHeaders(message.headers);\n if (headers.get(HEADER.specVersion) !== SPEC_VERSION) {\n throw invalid(`${HEADER.specVersion} must be '${SPEC_VERSION}'`);\n }\n const type = requireHeader(headers, HEADER.type);\n try {\n assertEventType(type);\n } catch (error) {\n throw invalid(`${HEADER.type} is not a valid event type: ${(error as Error).message}`);\n }\n assertJsonContentType(headers.get(CONTENT_TYPE));\n return {\n id: requireHeader(headers, HEADER.id),\n type,\n source: requireHeader(headers, HEADER.source),\n key: resolveKey(headers.get(HEADER.subject), message.key),\n payload: parsePayload(message.value),\n headers: collectUserHeaders(headers),\n correlationId: headers.get(HEADER.correlationId) ?? null,\n causationId: headers.get(HEADER.causationId) ?? null,\n occurredAt: resolveTime(headers.get(HEADER.time), message.timestamp),\n };\n}\n\nfunction invalid(reason: string): InvalidKafkaMessageError {\n return new InvalidKafkaMessageError(reason);\n}\n\nfunction escapeUserHeaderName(name: string): string {\n const lowered = name.toLowerCase();\n const reserved = lowered === CONTENT_TYPE || RESERVED_PREFIXES.some((p) => lowered.startsWith(p));\n return reserved ? `${ESCAPE_PREFIX}${name}` : name;\n}\n\nfunction readHeaders(incoming: KafkaIncomingHeaders | undefined): Map<string, string> {\n const headers = new Map<string, string>();\n for (const [name, raw] of Object.entries(incoming ?? {})) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'string' && !(raw instanceof Uint8Array)) {\n throw invalid(`Header '${name}' is repeated`);\n }\n headers.set(name, decodeText(raw, PROTOCOL_HEADERS.has(name), `Header '${name}'`));\n }\n return headers;\n}\n\nfunction decodeText(raw: KafkaBytes | string, strict: boolean, label: string): string {\n if (typeof raw === 'string') {\n return raw;\n }\n try {\n return (strict ? strictUtf8 : lenientUtf8).decode(raw);\n } catch {\n throw invalid(`${label} is not valid UTF-8`);\n }\n}\n\nfunction requireHeader(headers: Map<string, string>, name: string): string {\n const value = headers.get(name);\n if (value === undefined || value.length === 0) {\n throw invalid(`Header '${name}' is missing or empty`);\n }\n return value;\n}\n\nfunction assertJsonContentType(contentType: string | undefined): void {\n const mediaType = contentType?.split(';')[0]?.trim().toLowerCase();\n if (mediaType !== JSON_MEDIA_TYPE) {\n throw invalid(`${CONTENT_TYPE} must be '${JSON_MEDIA_TYPE}', received '${contentType ?? ''}'`);\n }\n}\n\nfunction resolveTime(text: string | undefined, recordTimestamp: string | undefined): Date {\n if (text !== undefined && text.length > 0) {\n return parseTime(text);\n }\n const milliseconds = Number(recordTimestamp);\n const time = new Date(milliseconds);\n if (recordTimestamp === undefined || recordTimestamp === '' || Number.isNaN(time.getTime())) {\n throw invalid(`${HEADER.time} is missing and the record has no usable timestamp`);\n }\n return time;\n}\n\nfunction parseTime(text: string): Date {\n const time = new Date(text);\n if (!RFC3339_PATTERN.test(text) || Number.isNaN(time.getTime())) {\n throw invalid(`${HEADER.time} is not an RFC 3339 timestamp: '${text}'`);\n }\n return time;\n}\n\nfunction parsePayload(value: KafkaBytes | null): unknown {\n if (value === null) {\n throw invalid('Message has no value');\n }\n const text = decodeText(value, true, 'Message value');\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw invalid('Message value is not valid JSON');\n }\n}\n\nfunction resolveKey(subject: string | undefined, recordKey: KafkaBytes | null): string | null {\n const keyText = recordKey === null ? null : decodeText(recordKey, true, 'Message key');\n if (subject !== undefined && keyText !== null && subject !== keyText) {\n throw invalid(`${HEADER.subject} does not match the message key`);\n }\n return subject ?? keyText;\n}\n\nfunction collectUserHeaders(headers: Map<string, string>): Record<string, string> {\n const entries: [string, string][] = [];\n for (const [name, value] of headers) {\n if (!PROTOCOL_HEADERS.has(name)) {\n entries.push([\n name.startsWith(ESCAPE_PREFIX) ? name.slice(ESCAPE_PREFIX.length) : name,\n value,\n ]);\n }\n }\n return Object.fromEntries(entries);\n}\n\n/** Converts incoming headers to what a producer accepts, keeping every value byte-for-byte. */\nexport function toOutgoingHeaders(\n incoming: KafkaIncomingHeaders | undefined,\n): KafkaOutgoingHeaders {\n const entries: [string, Buffer | string | (Buffer | string)[]][] = [];\n for (const [name, raw] of Object.entries(incoming ?? {})) {\n if (raw !== undefined) {\n entries.push([\n name,\n Array.isArray(raw)\n ? (raw as (KafkaBytes | string)[]).map(toBufferOrString)\n : toBufferOrString(raw as KafkaBytes | string),\n ]);\n }\n }\n return Object.fromEntries(entries);\n}\n\nfunction toBufferOrString(value: KafkaBytes | string): Buffer | string {\n return typeof value === 'string' ? value : Buffer.from(value);\n}\n","import {\n ConfigurationError,\n NonRetryableError,\n RelayBusError,\n toErrorInfo,\n toMilliseconds,\n type Duration,\n type EventEnvelope,\n type RelayBusLogger,\n type Transport,\n type TransportMessageHandler,\n} from '@relaybus/core';\nimport {\n InvalidKafkaMessageError,\n decodeEnvelope,\n encodeEnvelope,\n toOutgoingHeaders,\n} from './cloudevents-codec.js';\nimport type {\n KafkaClientLike,\n KafkaConsumerEvent,\n KafkaConsumerLike,\n KafkaEachMessagePayload,\n KafkaProducerLike,\n KafkaProducerRecord,\n} from './kafka-client.js';\n\n/** A record the transport refused to hand to the bus because it is malformed. */\nexport interface InvalidKafkaMessage {\n readonly topic: string;\n readonly partition: number;\n readonly offset: string;\n /** Why the record was rejected. */\n readonly reason: string;\n readonly key: Uint8Array | null;\n readonly value: Uint8Array | null;\n}\n\n/**\n * What to do with a record that cannot be processed for good (it cannot be\n * decoded, or the bus rejected it with a `NonRetryableError`):\n * - `'dead-letter'` (default): the original record is produced to\n * `<source topic>.dead` with `relaybus-invalid-reason`, `relaybus-source-topic`,\n * `relaybus-source-partition` and `relaybus-source-offset` headers added to the\n * original ones; the offset advances only after the broker acked the copy.\n * - `{ deadLetterTopic }`: same, with a fixed topic name or a function of the\n * source topic.\n * - a function: called with the record; if it rejects, the record is retried\n * like any other failure, so nothing is dropped unless the function returns.\n * - `'skip'`: log an error and drop the record. Explicit opt-in only.\n *\n * The dead-letter topic must exist or the broker must auto-create topics;\n * otherwise the send fails and the record stays uncommitted (nothing is lost).\n */\nexport type InvalidMessagePolicy =\n | 'dead-letter'\n | 'skip'\n | ((message: InvalidKafkaMessage) => void | Promise<void>)\n | { readonly deadLetterTopic: string | ((sourceTopic: string) => string) };\n\n/** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */\nexport class PublishTimeoutError extends RelayBusError {\n override name = 'PublishTimeoutError';\n}\n\n/** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */\nexport class HandlerFailedError extends RelayBusError {\n override name = 'HandlerFailedError';\n}\n\n/** Bounded in-process retries around the inbound handler (the bus's `receive`). */\nexport interface KafkaProcessingOptions {\n /** Attempts per delivery of a record before the error is handed to the client. Default 5. */\n readonly maxAttempts?: number;\n /** Delay before the second attempt; doubles each attempt. Default `'200ms'`. */\n readonly initialBackoff?: Duration;\n /** Upper bound of the delay between attempts. Default `'5s'`. */\n readonly maxBackoff?: Duration;\n /** Interval of the heartbeats sent while sleeping between attempts. Default `'1s'`. */\n readonly heartbeatInterval?: Duration;\n}\n\n/** Backoff of the consumer restart loop that runs after an unrecoverable crash. */\nexport interface KafkaRestartOptions {\n /** Delay before the second restart attempt; doubles each failure. Default `'1s'`. */\n readonly initialBackoff?: Duration;\n /** Upper bound of the delay between restart attempts. Default `'30s'`. */\n readonly maxBackoff?: Duration;\n}\n\nexport interface KafkaTransportOptions {\n /** A `kafkajs` `Kafka` or `@confluentinc/kafka-javascript` `KafkaJS.Kafka` instance. */\n readonly kafka: KafkaClientLike;\n /** Name referenced by routes and subscriptions. Default `'kafka'`. */\n readonly name?: string;\n /** Consumer group id. Required as soon as `subscribe` is used. */\n readonly groupId?: string;\n /**\n * Where a group without committed offsets starts. Default `true` (earliest),\n * so events published before the first start are not skipped.\n */\n readonly fromBeginning?: boolean;\n /** Producer `maxInFlightRequests`, 1 to 5. Default 1, which keeps retries from reordering a key. */\n readonly maxInFlightRequests?: number;\n /** Extra producer settings; `idempotent` and `maxInFlightRequests` always win. */\n readonly producerConfig?: object;\n /** Extra consumer settings; `groupId` always wins. */\n readonly consumerConfig?: object;\n readonly processing?: KafkaProcessingOptions;\n /** How long `subscribe` waits for the consumer group join before failing. Default `'30s'`. */\n readonly startupTimeout?: Duration;\n /** How long `publish` waits for the broker ack before rejecting. Default `'30s'`. */\n readonly publishTimeout?: Duration;\n readonly restart?: KafkaRestartOptions;\n /** Handling of records that cannot be processed for good. Default `'dead-letter'`. */\n readonly onInvalidMessage?: InvalidMessagePolicy;\n /** Default `console`. */\n readonly logger?: RelayBusLogger;\n}\n\nconst DEFAULTS = {\n name: 'kafka',\n maxInFlightRequests: 1,\n maxAttempts: 5,\n initialBackoff: '200ms',\n maxBackoff: '5s',\n startupTimeout: '30s',\n publishTimeout: '30s',\n heartbeatInterval: '1s',\n restartInitialBackoff: '1s',\n restartMaxBackoff: '30s',\n} as const;\n\ntype TransportState = 'idle' | 'subscribed' | 'closed';\n\ninterface Settings {\n readonly maxAttempts: number;\n readonly initialBackoffMs: number;\n readonly maxBackoffMs: number;\n readonly startupTimeoutMs: number;\n readonly publishTimeoutMs: number;\n readonly heartbeatIntervalMs: number;\n readonly restartInitialBackoffMs: number;\n readonly restartMaxBackoffMs: number;\n}\n\n/**\n * Kafka {@link Transport}. Events travel as CloudEvents binary-mode records\n * (`ce_*` headers, JSON value), so any CloudEvents-aware consumer can read them.\n *\n * Publishing: idempotent producer, `acks=-1`, resolves after the broker ack and\n * rejects with {@link PublishTimeoutError} after `publishTimeout`. A timed-out\n * send may still complete later; the outbox then retries it and the duplicate is\n * absorbed by the consumer's inbox dedup. The record key is the envelope key, so events sharing a key land on one\n * partition and keep their order; events without a key have no ordering.\n *\n * Subscribing: one consumer, one group, one `subscribe` call. `eachMessage`\n * awaits the handler; the client commits the offset only after it resolved. A\n * failing handler is retried in-process (bounded, with backoff) and then the\n * error is rethrown (as a {@link HandlerFailedError}, so the client never treats\n * it as fatal) and the client does not commit the offset and redelivers the\n * record. A record is therefore never skipped because of a handler failure; the\n * partition simply waits. Records that can never succeed (undecodable, or\n * rejected with a `NonRetryableError`) are dead-lettered instead. If the client\n * reports an unrecoverable crash anyway, the consumer run loop is restarted with\n * bounded backoff until the transport is closed.\n */\nexport class KafkaTransport implements Transport {\n readonly name: string;\n readonly #kafka: KafkaClientLike;\n readonly #groupId: string | undefined;\n readonly #fromBeginning: boolean;\n readonly #maxInFlightRequests: number;\n readonly #producerConfig: object;\n readonly #consumerConfig: object;\n readonly #invalidPolicy: InvalidMessagePolicy;\n readonly #logger: RelayBusLogger;\n readonly #settings: Settings;\n readonly #sleepers = new Set<() => void>();\n #state: TransportState = 'idle';\n #producer: Promise<KafkaProducerLike> | undefined;\n #consumer: KafkaConsumerLike | undefined;\n #groupJoined = false;\n #consuming = false;\n #producerConnected = false;\n #restartLoop: Promise<void> | undefined;\n readonly #stalledPartitions = new Set<string>();\n #startConsuming: (() => Promise<void>) | undefined;\n #joinWaiter: { resolve(): void; reject(error: unknown): void } | undefined;\n\n constructor(options: KafkaTransportOptions) {\n this.name = options.name ?? DEFAULTS.name;\n this.#kafka = options.kafka;\n this.#groupId = options.groupId;\n this.#fromBeginning = options.fromBeginning ?? true;\n this.#maxInFlightRequests = options.maxInFlightRequests ?? DEFAULTS.maxInFlightRequests;\n if (\n !Number.isInteger(this.#maxInFlightRequests) ||\n this.#maxInFlightRequests < 1 ||\n this.#maxInFlightRequests > 5\n ) {\n throw new ConfigurationError(\n `maxInFlightRequests must be an integer from 1 to 5, received ${this.#maxInFlightRequests}`,\n );\n }\n this.#producerConfig = options.producerConfig ?? {};\n this.#consumerConfig = options.consumerConfig ?? {};\n this.#invalidPolicy = options.onInvalidMessage ?? 'dead-letter';\n this.#logger = options.logger ?? console;\n this.#settings = resolveSettings(options);\n }\n\n /**\n * True while the consumer is joined to its group, not between a crash or\n * rebalance and the next join, and no partition is stalled on a record whose\n * handler keeps failing. Use it for readiness so a consumer that silently\n * stopped is noticed.\n */\n isConsuming(): boolean {\n return this.#state === 'subscribed' && this.#groupJoined && this.#stalledPartitions.size === 0;\n }\n\n /**\n * True once the producer is connected and, if the transport subscribed, the\n * consumer is consuming. False before `connect`, after `close` and while a\n * dead consumer is being restarted.\n */\n isReady(): boolean {\n if (this.#state === 'closed' || !this.#producerConnected) {\n return false;\n }\n return this.#state === 'idle' || this.isConsuming();\n }\n\n /** Connects the producer. Called by the bus on start; `publish` also connects on demand. */\n async connect(): Promise<void> {\n await this.#connectedProducer();\n }\n\n async publish(envelope: EventEnvelope, destination: string): Promise<void> {\n const producer = await this.#connectedProducer();\n const { key, value, headers } = encodeEnvelope(envelope);\n await this.#send(producer, {\n topic: destination,\n acks: -1,\n messages: [{ key, value, headers }],\n });\n }\n\n /**\n * Starts the consumer and resolves once it joined its group, so a start-up\n * that cannot consume fails loudly instead of looking healthy.\n *\n * @throws ConfigurationError when `groupId` is missing, `destinations` is empty\n * or the transport already subscribed (create one transport per subscription).\n */\n async subscribe(\n destinations: readonly string[],\n onMessage: TransportMessageHandler,\n ): Promise<void> {\n this.#assertCanSubscribe(destinations);\n this.#state = 'subscribed';\n const consumer = this.#kafka.consumer({ ...this.#consumerConfig, groupId: this.#groupId! });\n this.#consumer = consumer;\n this.#observeConsumer(consumer);\n const start = (): Promise<void> => this.#startConsumer(consumer, [...destinations], onMessage);\n this.#startConsuming = start;\n try {\n await start();\n } catch (error) {\n // A consumer left half-started would keep running (or retrying) with nobody watching it.\n await consumer.disconnect().catch(() => undefined);\n this.#groupJoined = false;\n this.#consumer = undefined;\n this.#state = 'idle';\n throw error;\n }\n this.#consuming = true;\n this.#logger.log(\n `[KafkaTransport](subscribe) Consuming | transport=${this.name} group=${this.#groupId} topics=${destinations.join(',')}`,\n );\n }\n\n async #startConsumer(\n consumer: KafkaConsumerLike,\n destinations: string[],\n onMessage: TransportMessageHandler,\n ): Promise<void> {\n await consumer.connect();\n await consumer.subscribe({ topics: destinations, fromBeginning: this.#fromBeginning });\n const joined = this.#waitForGroupJoin(consumer);\n try {\n await consumer.run({ eachMessage: (payload) => this.#handleMessage(payload, onMessage) });\n await joined.promise;\n } finally {\n joined.dispose();\n }\n }\n\n /** Stops consuming and disconnects the consumer and the producer. Safe to call twice. */\n async close(): Promise<void> {\n if (this.#state === 'closed') {\n return;\n }\n this.#state = 'closed';\n const pendingProducer = this.#producer;\n this.#groupJoined = false;\n this.#producerConnected = false;\n for (const wake of this.#sleepers) {\n wake();\n }\n this.#joinWaiter?.reject(new RelayBusError(`Transport '${this.name}' is closed`));\n await this.#restartLoop;\n const producer = await pendingProducer?.catch(() => undefined);\n const results = await Promise.allSettled([\n this.#consumer?.disconnect(),\n producer?.disconnect(),\n ]);\n const failure = results.find((result) => result.status === 'rejected');\n if (failure !== undefined) {\n throw failure.reason;\n }\n }\n\n #assertCanSubscribe(destinations: readonly string[]): void {\n if (this.#state === 'closed') {\n throw new RelayBusError(`Transport '${this.name}' is closed`);\n }\n if (this.#state === 'subscribed') {\n throw new ConfigurationError(\n `Transport '${this.name}' already subscribed; list every topic in one subscription or use one KafkaTransport per consumer group`,\n );\n }\n if (this.#groupId === undefined || this.#groupId.length === 0) {\n throw new ConfigurationError(`Transport '${this.name}' needs a groupId to subscribe`);\n }\n if (destinations.length === 0) {\n throw new ConfigurationError(`Transport '${this.name}' subscribed to no topics`);\n }\n for (const topic of destinations) {\n const deadLetterTopic = this.#deadLetterTopicFor(topic);\n if (deadLetterTopic !== undefined && destinations.includes(deadLetterTopic)) {\n throw new ConfigurationError(\n `Dead letter topic '${deadLetterTopic}' is also consumed, which would loop`,\n );\n }\n }\n }\n\n /** The dead-letter topic for records of `sourceTopic`, or undefined when the policy does not use one. */\n #deadLetterTopicFor(sourceTopic: string): string | undefined {\n const policy = this.#invalidPolicy;\n if (policy === 'dead-letter') {\n return `${sourceTopic}.dead`;\n }\n if (typeof policy === 'object') {\n const { deadLetterTopic } = policy;\n return typeof deadLetterTopic === 'function' ? deadLetterTopic(sourceTopic) : deadLetterTopic;\n }\n return undefined;\n }\n\n /** Sends with the publish timeout; the late outcome of a timed-out send is ignored. */\n async #send(producer: KafkaProducerLike, record: KafkaProducerRecord): Promise<void> {\n let timer: NodeJS.Timeout | undefined;\n const timeout = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(\n new PublishTimeoutError(\n `Transport '${this.name}' got no broker ack for topic '${record.topic}' within ${this.#settings.publishTimeoutMs}ms`,\n ),\n );\n }, this.#settings.publishTimeoutMs);\n });\n const sending = producer.send(record);\n sending.catch(() => undefined);\n try {\n await Promise.race([sending, timeout]);\n } finally {\n clearTimeout(timer);\n }\n }\n\n #connectedProducer(): Promise<KafkaProducerLike> {\n if (this.#state === 'closed') {\n return Promise.reject(new RelayBusError(`Transport '${this.name}' is closed`));\n }\n this.#producer ??= this.#openProducer();\n return this.#producer;\n }\n\n async #openProducer(): Promise<KafkaProducerLike> {\n const producer = this.#kafka.producer({\n ...this.#producerConfig,\n idempotent: true,\n maxInFlightRequests: this.#maxInFlightRequests,\n });\n try {\n await producer.connect();\n } catch (error) {\n this.#producer = undefined;\n throw error;\n }\n this.#producerConnected = this.#state !== 'closed';\n return producer;\n }\n\n async #handleMessage(\n payload: KafkaEachMessagePayload,\n onMessage: TransportMessageHandler,\n ): Promise<void> {\n let envelope: EventEnvelope;\n try {\n envelope = decodeEnvelope(payload.message);\n } catch (error) {\n if (!(error instanceof InvalidKafkaMessageError)) {\n throw toHandlerFailure(error);\n }\n await this.#withRetries(payload, 'handleInvalid', () =>\n this.#handleInvalid(payload, error.message),\n );\n return;\n }\n await this.#withRetries(payload, 'deliver', async () => {\n try {\n await onMessage(envelope);\n } catch (error) {\n // The bus rejected the event for good; redelivering it would block the partition forever.\n if (!(error instanceof NonRetryableError)) {\n throw error;\n }\n await this.#handleInvalid(payload, error.message);\n }\n });\n }\n\n async #handleInvalid(payload: KafkaEachMessagePayload, reason: string): Promise<void> {\n const { topic, partition, message } = payload;\n const location = `topic=${topic} partition=${partition} offset=${message.offset}`;\n const policy = this.#invalidPolicy;\n const deadLetterTopic = this.#deadLetterTopicFor(topic);\n if (policy === 'skip') {\n this.#logger.error(\n `[KafkaTransport](handleInvalid) Skipping malformed message | ${location} reason=${reason}`,\n );\n } else if (typeof policy === 'function') {\n await policy({\n topic,\n partition,\n offset: message.offset,\n reason,\n key: message.key,\n value: message.value,\n });\n } else {\n const producer = await this.#connectedProducer();\n await this.#send(producer, {\n topic: deadLetterTopic!,\n acks: -1,\n messages: [\n {\n key: message.key === null ? null : Buffer.from(message.key),\n value: message.value === null ? null : Buffer.from(message.value),\n headers: {\n ...toOutgoingHeaders(message.headers),\n 'relaybus-invalid-reason': reason,\n 'relaybus-source-topic': topic,\n 'relaybus-source-partition': String(partition),\n 'relaybus-source-offset': message.offset,\n },\n },\n ],\n });\n this.#logger.error(\n `[KafkaTransport](handleInvalid) Dead-lettered malformed message | ${location} deadLetterTopic=${deadLetterTopic} reason=${reason}`,\n );\n }\n }\n\n /**\n * Runs `operation` up to `maxAttempts` times with exponential backoff. The\n * last error is rethrown so the client leaves the offset uncommitted and\n * redelivers the record; heartbeats between attempts keep the session alive.\n */\n async #withRetries(\n payload: KafkaEachMessagePayload,\n method: string,\n operation: () => Promise<void>,\n ): Promise<void> {\n const { maxAttempts, initialBackoffMs, maxBackoffMs } = this.#settings;\n const location = `topic=${payload.topic} partition=${payload.partition} offset=${payload.message.offset}`;\n const partitionKey = `${payload.topic}:${payload.partition}`;\n for (let attempt = 1; ; attempt += 1) {\n try {\n await operation();\n this.#stalledPartitions.delete(partitionKey);\n return;\n } catch (error) {\n const reason = toErrorInfo(error).message;\n if (attempt >= maxAttempts || this.#state === 'closed') {\n this.#stalledPartitions.add(partitionKey);\n this.#logger.error(\n `[KafkaTransport](${method}) Giving up for now, the record stays uncommitted and will be redelivered | ${location} attempts=${attempt} error=${reason}`,\n );\n throw toHandlerFailure(error);\n }\n this.#logger.warn(\n `[KafkaTransport](${method}) Attempt failed, retrying | ${location} attempt=${attempt} error=${reason}`,\n );\n await this.#sleepWithHeartbeats(\n Math.min(initialBackoffMs * 2 ** (attempt - 1), maxBackoffMs),\n payload,\n );\n }\n }\n }\n\n /** Sleeps in slices and heartbeats after each, so a long backoff never outlives the session timeout. */\n async #sleepWithHeartbeats(\n milliseconds: number,\n payload: KafkaEachMessagePayload,\n ): Promise<void> {\n let remaining = milliseconds;\n do {\n const slice = Math.min(remaining, this.#settings.heartbeatIntervalMs);\n await this.#sleep(slice);\n await payload.heartbeat();\n remaining -= slice;\n } while (remaining > 0 && this.#state !== 'closed');\n }\n\n #sleep(milliseconds: number): Promise<void> {\n return new Promise((resolve) => {\n const wake = (): void => {\n clearTimeout(timer);\n this.#sleepers.delete(wake);\n resolve();\n };\n const timer = setTimeout(wake, milliseconds);\n this.#sleepers.add(wake);\n });\n }\n\n /** Whether the client exposes the instrumentation needed to follow the group membership. */\n #tracksMembership(consumer: KafkaConsumerLike): boolean {\n return consumer.on !== undefined && consumer.events?.GROUP_JOIN !== undefined;\n }\n\n #observeConsumer(consumer: KafkaConsumerLike): void {\n if (!this.#tracksMembership(consumer)) {\n this.#groupJoined = true;\n return;\n }\n const names = consumer.events!;\n const listen = (\n name: string | undefined,\n listener: (event: KafkaConsumerEvent) => void,\n ): void => {\n if (name !== undefined) {\n consumer.on!(name, listener);\n }\n };\n listen(names.GROUP_JOIN, () => {\n this.#groupJoined = true;\n this.#joinWaiter?.resolve();\n this.#logger.log(`[KafkaTransport](observeConsumer) Joined group | group=${this.#groupId}`);\n });\n listen(names.REBALANCING, () => {\n this.#groupJoined = false;\n // The partition assignment is about to change; a stall is re-detected if it persists.\n this.#stalledPartitions.clear();\n this.#logger.warn(`[KafkaTransport](observeConsumer) Rebalancing | group=${this.#groupId}`);\n });\n listen(names.CRASH, (event) => this.#handleCrash(event));\n listen(names.STOP, () => {\n this.#groupJoined = false;\n });\n listen(names.DISCONNECT, () => {\n this.#groupJoined = false;\n });\n }\n\n #handleCrash(event: KafkaConsumerEvent): void {\n const { error, restart } = (event.payload ?? {}) as { error?: unknown; restart?: unknown };\n this.#groupJoined = false;\n this.#logger.error(\n `[KafkaTransport](handleCrash) Consumer crashed | group=${this.#groupId} restart=${String(restart)} error=${toErrorInfo(error).message}`,\n );\n this.#joinWaiter?.reject(error);\n if (restart === false && this.#consuming && this.#restartLoop === undefined) {\n this.#restartLoop = this.#restartConsumer().finally(() => {\n this.#restartLoop = undefined;\n });\n }\n }\n\n /**\n * The client gave up on the consumer (`restart=false`): reconnect it and run\n * again, with bounded backoff, until it joined or the transport closed.\n */\n async #restartConsumer(): Promise<void> {\n const { restartInitialBackoffMs, restartMaxBackoffMs } = this.#settings;\n const consumer = this.#consumer!;\n for (let attempt = 1; this.#state === 'subscribed'; attempt += 1) {\n await this.#sleep(\n Math.min(restartInitialBackoffMs * 2 ** (attempt - 1), restartMaxBackoffMs),\n );\n if (this.#state !== 'subscribed') {\n return;\n }\n await consumer.disconnect().catch(() => undefined);\n try {\n await this.#startConsuming!();\n this.#logger.log(\n `[KafkaTransport](restartConsumer) Consumer restarted | group=${this.#groupId} attempt=${attempt}`,\n );\n return;\n } catch (error) {\n this.#logger.error(\n `[KafkaTransport](restartConsumer) Restart failed, will retry | group=${this.#groupId} attempt=${attempt} error=${toErrorInfo(error).message}`,\n );\n }\n }\n }\n\n #waitForGroupJoin(consumer: KafkaConsumerLike): { promise: Promise<void>; dispose(): void } {\n if (!this.#tracksMembership(consumer)) {\n return { promise: Promise.resolve(), dispose: () => undefined };\n }\n let timer: NodeJS.Timeout | undefined;\n const promise = new Promise<void>((resolve, reject) => {\n this.#joinWaiter = { resolve, reject };\n timer = setTimeout(() => {\n reject(\n new RelayBusError(\n `Consumer of transport '${this.name}' did not join group '${this.#groupId}' within ${this.#settings.startupTimeoutMs}ms`,\n ),\n );\n }, this.#settings.startupTimeoutMs);\n });\n // The rejection may land while `run` is still pending; the caller awaits it afterwards.\n promise.catch(() => undefined);\n return {\n promise,\n dispose: () => {\n clearTimeout(timer);\n this.#joinWaiter = undefined;\n },\n };\n }\n}\n\nfunction resolveSettings(options: KafkaTransportOptions): Settings {\n const maxAttempts = options.processing?.maxAttempts ?? DEFAULTS.maxAttempts;\n if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {\n throw new ConfigurationError(\n `processing.maxAttempts must be a positive integer, received ${maxAttempts}`,\n );\n }\n return {\n maxAttempts,\n initialBackoffMs: toMilliseconds(\n options.processing?.initialBackoff ?? DEFAULTS.initialBackoff,\n 'processing.initialBackoff',\n ),\n maxBackoffMs: toMilliseconds(\n options.processing?.maxBackoff ?? DEFAULTS.maxBackoff,\n 'processing.maxBackoff',\n ),\n startupTimeoutMs: toMilliseconds(\n options.startupTimeout ?? DEFAULTS.startupTimeout,\n 'startupTimeout',\n ),\n publishTimeoutMs: toMilliseconds(\n options.publishTimeout ?? DEFAULTS.publishTimeout,\n 'publishTimeout',\n ),\n heartbeatIntervalMs: Math.max(\n 1,\n toMilliseconds(\n options.processing?.heartbeatInterval ?? DEFAULTS.heartbeatInterval,\n 'processing.heartbeatInterval',\n ),\n ),\n restartInitialBackoffMs: toMilliseconds(\n options.restart?.initialBackoff ?? DEFAULTS.restartInitialBackoff,\n 'restart.initialBackoff',\n ),\n restartMaxBackoffMs: toMilliseconds(\n options.restart?.maxBackoff ?? DEFAULTS.restartMaxBackoff,\n 'restart.maxBackoff',\n ),\n };\n}\n\n/**\n * Wraps a failure in a fresh error before it goes back to the Kafka client.\n * kafkajs classifies errors by type and cause chain: a handler that throws a\n * `TypeError` would be marked unrecoverable and kill the consumer for good.\n * The wrapper carries the original name and message but no `cause`.\n */\nfunction toHandlerFailure(error: unknown): Error {\n const { name, message } = toErrorInfo(error);\n return new HandlerFailedError(`${name}: ${message}`);\n}\n"]}
@@ -0,0 +1,283 @@
1
+ import { RelayBusError, NonRetryableError, EventEnvelope, Duration, Transport, RelayBusLogger, TransportMessageHandler } from '@relaybus/core';
2
+
3
+ /**
4
+ * Structural views of the Kafka client API used by this package.
5
+ *
6
+ * They are satisfied by both `kafkajs` (`new Kafka(...)`) and
7
+ * `@confluentinc/kafka-javascript` (`new KafkaJS.Kafka(...)`, the KafkaJS
8
+ * compatible API), so neither is a hard dependency. Only the members listed
9
+ * here are ever called. Methods are declared with method syntax on purpose:
10
+ * it keeps the real client classes assignable despite their richer signatures.
11
+ */
12
+ /** Bytes as delivered by a consumer: `Buffer` in both supported clients. */
13
+ type KafkaBytes = Uint8Array;
14
+ /** Header values a consumer may hand over: bytes, a string, a list of either, or nothing. */
15
+ type KafkaIncomingHeaders = Readonly<Record<string, KafkaBytes | string | readonly (KafkaBytes | string)[] | undefined>>;
16
+ /** Header values accepted when producing. */
17
+ type KafkaOutgoingHeaders = Readonly<Record<string, Buffer | string | (Buffer | string)[]>>;
18
+ /** One record handed to the producer. */
19
+ interface KafkaOutgoingMessage {
20
+ readonly key: string | Buffer | null;
21
+ readonly value: string | Buffer | null;
22
+ readonly headers: KafkaOutgoingHeaders;
23
+ }
24
+ /** Argument of `producer.send`. */
25
+ interface KafkaProducerRecord {
26
+ readonly topic: string;
27
+ readonly messages: KafkaOutgoingMessage[];
28
+ /** Always `-1`: wait for all in-sync replicas. */
29
+ readonly acks: number;
30
+ }
31
+ /** Producer settings this package decides itself; user settings are merged below them. */
32
+ interface KafkaProducerConfig {
33
+ readonly idempotent: boolean;
34
+ readonly maxInFlightRequests: number;
35
+ }
36
+ /** Consumer settings this package decides itself; user settings are merged below them. */
37
+ interface KafkaConsumerConfig {
38
+ readonly groupId: string;
39
+ }
40
+ /** Subset of the producer API: `connect`, `send`, `disconnect`. */
41
+ interface KafkaProducerLike {
42
+ connect(): Promise<void>;
43
+ send(record: KafkaProducerRecord): Promise<unknown>;
44
+ disconnect(): Promise<void>;
45
+ }
46
+ /** A message as delivered to `eachMessage`. */
47
+ interface KafkaIncomingMessage {
48
+ readonly key: KafkaBytes | null;
49
+ readonly value: KafkaBytes | null;
50
+ readonly headers?: KafkaIncomingHeaders | undefined;
51
+ readonly offset: string;
52
+ /** Record timestamp as epoch milliseconds in a string (kafkajs and Confluent). */
53
+ readonly timestamp?: string | undefined;
54
+ }
55
+ /** Argument of the `eachMessage` callback. `pause` and others are not used. */
56
+ interface KafkaEachMessagePayload {
57
+ readonly topic: string;
58
+ readonly partition: number;
59
+ readonly message: KafkaIncomingMessage;
60
+ heartbeat(): Promise<void>;
61
+ }
62
+ /** Argument of `consumer.run`. Offsets are committed automatically after `eachMessage` resolves. */
63
+ interface KafkaRunConfig {
64
+ eachMessage(payload: KafkaEachMessagePayload): Promise<void>;
65
+ }
66
+ /**
67
+ * Instrumentation event names exposed as `consumer.events`. Optional: a client
68
+ * without them still works, but start-up cannot wait for the group join and
69
+ * `isConsuming()` cannot observe crashes.
70
+ */
71
+ interface KafkaConsumerEventNames {
72
+ readonly GROUP_JOIN?: string;
73
+ readonly CRASH?: string;
74
+ readonly REBALANCING?: string;
75
+ readonly STOP?: string;
76
+ readonly DISCONNECT?: string;
77
+ }
78
+ /** Instrumentation event; `payload` carries `error` and `restart` for a crash. */
79
+ interface KafkaConsumerEvent {
80
+ readonly payload?: unknown;
81
+ }
82
+ /** Subset of the consumer API: `connect`, `subscribe`, `run`, `disconnect`, optional `on`/`events`. */
83
+ interface KafkaConsumerLike {
84
+ readonly events?: KafkaConsumerEventNames | undefined;
85
+ on?(eventName: string, listener: (event: KafkaConsumerEvent) => void): unknown;
86
+ connect(): Promise<void>;
87
+ subscribe(subscription: {
88
+ topics: string[];
89
+ fromBeginning: boolean;
90
+ }): Promise<void>;
91
+ run(config: KafkaRunConfig): Promise<void>;
92
+ disconnect(): Promise<void>;
93
+ }
94
+ /** Subset of the client API: the `producer` and `consumer` factories. */
95
+ interface KafkaClientLike {
96
+ producer(config: KafkaProducerConfig): KafkaProducerLike;
97
+ consumer(config: KafkaConsumerConfig): KafkaConsumerLike;
98
+ }
99
+
100
+ /** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
101
+ declare class InvalidKafkaMessageError extends RelayBusError {
102
+ }
103
+ /**
104
+ * An event that cannot be written to Kafka: its payload is not representable as
105
+ * JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
106
+ * its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
107
+ * Retrying cannot help, so it is a {@link NonRetryableError}.
108
+ */
109
+ declare class UnencodableEventError extends NonRetryableError {
110
+ name: string;
111
+ }
112
+ /** The wire form of one event: a Kafka record in CloudEvents binary content mode. */
113
+ interface EncodedMessage {
114
+ readonly key: string | null;
115
+ readonly value: string;
116
+ readonly headers: Record<string, string>;
117
+ }
118
+ /** The parts of an incoming Kafka record the decoder reads. */
119
+ interface DecodableMessage {
120
+ readonly key: KafkaBytes | null;
121
+ readonly value: KafkaBytes | null;
122
+ readonly headers?: KafkaIncomingHeaders | undefined;
123
+ /** Record timestamp in epoch milliseconds, used when `ce_time` is absent. */
124
+ readonly timestamp?: string | undefined;
125
+ }
126
+ /**
127
+ * Encodes an envelope as a CloudEvents Kafka binary-mode record: the value is
128
+ * the JSON payload, the event attributes travel as `ce_*` headers.
129
+ *
130
+ * User headers that would collide with protocol names (`ce_*`, `content-type`,
131
+ * `x-relaybus-*`) are stored under an `x-relaybus-h-` prefix and restored on
132
+ * decode, so every header survives a round trip unchanged.
133
+ */
134
+ declare function encodeEnvelope(envelope: EventEnvelope): EncodedMessage;
135
+ /**
136
+ * Decodes a Kafka record strictly: the CloudEvents attributes `ce_specversion`
137
+ * (`1.0`), `ce_id`, `ce_type`, `ce_source`, a JSON `content-type` and a JSON
138
+ * value are required. `ce_time` is optional in CloudEvents: when absent, the
139
+ * Kafka record timestamp is used; when present it must be RFC 3339.
140
+ *
141
+ * @throws InvalidKafkaMessageError for anything else. It is the only error
142
+ * thrown for malformed input, so callers can tell poison messages from bugs.
143
+ */
144
+ declare function decodeEnvelope(message: DecodableMessage): EventEnvelope;
145
+
146
+ /** A record the transport refused to hand to the bus because it is malformed. */
147
+ interface InvalidKafkaMessage {
148
+ readonly topic: string;
149
+ readonly partition: number;
150
+ readonly offset: string;
151
+ /** Why the record was rejected. */
152
+ readonly reason: string;
153
+ readonly key: Uint8Array | null;
154
+ readonly value: Uint8Array | null;
155
+ }
156
+ /**
157
+ * What to do with a record that cannot be processed for good (it cannot be
158
+ * decoded, or the bus rejected it with a `NonRetryableError`):
159
+ * - `'dead-letter'` (default): the original record is produced to
160
+ * `<source topic>.dead` with `relaybus-invalid-reason`, `relaybus-source-topic`,
161
+ * `relaybus-source-partition` and `relaybus-source-offset` headers added to the
162
+ * original ones; the offset advances only after the broker acked the copy.
163
+ * - `{ deadLetterTopic }`: same, with a fixed topic name or a function of the
164
+ * source topic.
165
+ * - a function: called with the record; if it rejects, the record is retried
166
+ * like any other failure, so nothing is dropped unless the function returns.
167
+ * - `'skip'`: log an error and drop the record. Explicit opt-in only.
168
+ *
169
+ * The dead-letter topic must exist or the broker must auto-create topics;
170
+ * otherwise the send fails and the record stays uncommitted (nothing is lost).
171
+ */
172
+ type InvalidMessagePolicy = 'dead-letter' | 'skip' | ((message: InvalidKafkaMessage) => void | Promise<void>) | {
173
+ readonly deadLetterTopic: string | ((sourceTopic: string) => string);
174
+ };
175
+ /** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
176
+ declare class PublishTimeoutError extends RelayBusError {
177
+ name: string;
178
+ }
179
+ /** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
180
+ declare class HandlerFailedError extends RelayBusError {
181
+ name: string;
182
+ }
183
+ /** Bounded in-process retries around the inbound handler (the bus's `receive`). */
184
+ interface KafkaProcessingOptions {
185
+ /** Attempts per delivery of a record before the error is handed to the client. Default 5. */
186
+ readonly maxAttempts?: number;
187
+ /** Delay before the second attempt; doubles each attempt. Default `'200ms'`. */
188
+ readonly initialBackoff?: Duration;
189
+ /** Upper bound of the delay between attempts. Default `'5s'`. */
190
+ readonly maxBackoff?: Duration;
191
+ /** Interval of the heartbeats sent while sleeping between attempts. Default `'1s'`. */
192
+ readonly heartbeatInterval?: Duration;
193
+ }
194
+ /** Backoff of the consumer restart loop that runs after an unrecoverable crash. */
195
+ interface KafkaRestartOptions {
196
+ /** Delay before the second restart attempt; doubles each failure. Default `'1s'`. */
197
+ readonly initialBackoff?: Duration;
198
+ /** Upper bound of the delay between restart attempts. Default `'30s'`. */
199
+ readonly maxBackoff?: Duration;
200
+ }
201
+ interface KafkaTransportOptions {
202
+ /** A `kafkajs` `Kafka` or `@confluentinc/kafka-javascript` `KafkaJS.Kafka` instance. */
203
+ readonly kafka: KafkaClientLike;
204
+ /** Name referenced by routes and subscriptions. Default `'kafka'`. */
205
+ readonly name?: string;
206
+ /** Consumer group id. Required as soon as `subscribe` is used. */
207
+ readonly groupId?: string;
208
+ /**
209
+ * Where a group without committed offsets starts. Default `true` (earliest),
210
+ * so events published before the first start are not skipped.
211
+ */
212
+ readonly fromBeginning?: boolean;
213
+ /** Producer `maxInFlightRequests`, 1 to 5. Default 1, which keeps retries from reordering a key. */
214
+ readonly maxInFlightRequests?: number;
215
+ /** Extra producer settings; `idempotent` and `maxInFlightRequests` always win. */
216
+ readonly producerConfig?: object;
217
+ /** Extra consumer settings; `groupId` always wins. */
218
+ readonly consumerConfig?: object;
219
+ readonly processing?: KafkaProcessingOptions;
220
+ /** How long `subscribe` waits for the consumer group join before failing. Default `'30s'`. */
221
+ readonly startupTimeout?: Duration;
222
+ /** How long `publish` waits for the broker ack before rejecting. Default `'30s'`. */
223
+ readonly publishTimeout?: Duration;
224
+ readonly restart?: KafkaRestartOptions;
225
+ /** Handling of records that cannot be processed for good. Default `'dead-letter'`. */
226
+ readonly onInvalidMessage?: InvalidMessagePolicy;
227
+ /** Default `console`. */
228
+ readonly logger?: RelayBusLogger;
229
+ }
230
+ /**
231
+ * Kafka {@link Transport}. Events travel as CloudEvents binary-mode records
232
+ * (`ce_*` headers, JSON value), so any CloudEvents-aware consumer can read them.
233
+ *
234
+ * Publishing: idempotent producer, `acks=-1`, resolves after the broker ack and
235
+ * rejects with {@link PublishTimeoutError} after `publishTimeout`. A timed-out
236
+ * send may still complete later; the outbox then retries it and the duplicate is
237
+ * absorbed by the consumer's inbox dedup. The record key is the envelope key, so events sharing a key land on one
238
+ * partition and keep their order; events without a key have no ordering.
239
+ *
240
+ * Subscribing: one consumer, one group, one `subscribe` call. `eachMessage`
241
+ * awaits the handler; the client commits the offset only after it resolved. A
242
+ * failing handler is retried in-process (bounded, with backoff) and then the
243
+ * error is rethrown (as a {@link HandlerFailedError}, so the client never treats
244
+ * it as fatal) and the client does not commit the offset and redelivers the
245
+ * record. A record is therefore never skipped because of a handler failure; the
246
+ * partition simply waits. Records that can never succeed (undecodable, or
247
+ * rejected with a `NonRetryableError`) are dead-lettered instead. If the client
248
+ * reports an unrecoverable crash anyway, the consumer run loop is restarted with
249
+ * bounded backoff until the transport is closed.
250
+ */
251
+ declare class KafkaTransport implements Transport {
252
+ #private;
253
+ readonly name: string;
254
+ constructor(options: KafkaTransportOptions);
255
+ /**
256
+ * True while the consumer is joined to its group, not between a crash or
257
+ * rebalance and the next join, and no partition is stalled on a record whose
258
+ * handler keeps failing. Use it for readiness so a consumer that silently
259
+ * stopped is noticed.
260
+ */
261
+ isConsuming(): boolean;
262
+ /**
263
+ * True once the producer is connected and, if the transport subscribed, the
264
+ * consumer is consuming. False before `connect`, after `close` and while a
265
+ * dead consumer is being restarted.
266
+ */
267
+ isReady(): boolean;
268
+ /** Connects the producer. Called by the bus on start; `publish` also connects on demand. */
269
+ connect(): Promise<void>;
270
+ publish(envelope: EventEnvelope, destination: string): Promise<void>;
271
+ /**
272
+ * Starts the consumer and resolves once it joined its group, so a start-up
273
+ * that cannot consume fails loudly instead of looking healthy.
274
+ *
275
+ * @throws ConfigurationError when `groupId` is missing, `destinations` is empty
276
+ * or the transport already subscribed (create one transport per subscription).
277
+ */
278
+ subscribe(destinations: readonly string[], onMessage: TransportMessageHandler): Promise<void>;
279
+ /** Stops consuming and disconnects the consumer and the producer. Safe to call twice. */
280
+ close(): Promise<void>;
281
+ }
282
+
283
+ export { type DecodableMessage, type EncodedMessage, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, PublishTimeoutError, UnencodableEventError, decodeEnvelope, encodeEnvelope };