@relaybus/kafka 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -48
- package/dist/index.cjs +267 -169
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +123 -62
- package/dist/index.d.ts +123 -62
- package/dist/index.js +256 -168
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,42 @@
|
|
|
1
|
-
import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, Transport, RelayBusLogger, TransportMessageHandler } from '@relaybus/core';
|
|
1
|
+
import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, Transport, RelayBusLogger, TransportMessageHandler, TransportSubscriptionHooks } from '@relaybus/core';
|
|
2
|
+
import { JsonEnvelopeMapping } from '@relaybus/core/internal';
|
|
3
|
+
export { fromHeader, fromPayloadField } from '@relaybus/core/internal';
|
|
4
|
+
|
|
5
|
+
/** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
|
|
6
|
+
declare class InvalidKafkaMessageError extends RelayBusError {
|
|
7
|
+
name: string;
|
|
8
|
+
readonly code: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* An event that cannot be written to Kafka: its payload is not representable as
|
|
12
|
+
* JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
|
|
13
|
+
* its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
|
|
14
|
+
* Retrying cannot help, so it is a {@link NonRetryableError}.
|
|
15
|
+
*/
|
|
16
|
+
declare class UnencodableEventError extends NonRetryableError {
|
|
17
|
+
name: string;
|
|
18
|
+
readonly code: string;
|
|
19
|
+
}
|
|
20
|
+
/** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
|
|
21
|
+
declare class PublishTimeoutError extends RelayBusError {
|
|
22
|
+
name: string;
|
|
23
|
+
readonly code: string;
|
|
24
|
+
}
|
|
25
|
+
/** The transport was closed: it no longer publishes or subscribes. */
|
|
26
|
+
declare class TransportClosedError extends RelayBusError {
|
|
27
|
+
name: string;
|
|
28
|
+
readonly code: string;
|
|
29
|
+
}
|
|
30
|
+
/** The consumer did not join its group within `startupTimeout`. */
|
|
31
|
+
declare class GroupJoinTimeoutError extends RelayBusError {
|
|
32
|
+
name: string;
|
|
33
|
+
readonly code: string;
|
|
34
|
+
}
|
|
35
|
+
/** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
|
|
36
|
+
declare class HandlerFailedError extends RelayBusError {
|
|
37
|
+
name: string;
|
|
38
|
+
readonly code: string;
|
|
39
|
+
}
|
|
2
40
|
|
|
3
41
|
/**
|
|
4
42
|
* Structural views of the Kafka client API used by this package.
|
|
@@ -97,18 +135,6 @@ interface KafkaClientLike {
|
|
|
97
135
|
consumer(config: KafkaConsumerConfig): KafkaConsumerLike;
|
|
98
136
|
}
|
|
99
137
|
|
|
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
138
|
/** The wire form of one event: a Kafka record in CloudEvents binary content mode. */
|
|
113
139
|
interface EncodedMessage {
|
|
114
140
|
readonly key: string | null;
|
|
@@ -262,6 +288,69 @@ declare function decodeCloudEvent(record: DecodableMessage): EventEnvelope;
|
|
|
262
288
|
*/
|
|
263
289
|
declare function plainJsonDecoder(options: PlainJsonDecoderOptions): KafkaMessageDecoder;
|
|
264
290
|
|
|
291
|
+
/** The record a codec produces for one event. `timestamp` is epoch milliseconds in a string. */
|
|
292
|
+
type KafkaEncodedRecord = KafkaOutgoingMessage & {
|
|
293
|
+
readonly timestamp?: string;
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* The wire format of a {@link KafkaTransport}: how an event becomes a record
|
|
297
|
+
* (`encode`, on publish) and a consumed record becomes an event (`decode`).
|
|
298
|
+
*
|
|
299
|
+
* Both must be synchronous and free of side effects. What `encode` throws
|
|
300
|
+
* fails the publish: the outbox retries it, unless it is a `NonRetryableError`
|
|
301
|
+
* such as {@link UnencodableEventError}. What `decode` throws marks the record
|
|
302
|
+
* as malformed: it goes to `onInvalidMessage` (dead-letter by default) and the
|
|
303
|
+
* consumer moves on. See {@link KafkaMessageDecoder} for the decode contract.
|
|
304
|
+
*/
|
|
305
|
+
interface KafkaCodec {
|
|
306
|
+
readonly encode: (envelope: EventEnvelope) => KafkaEncodedRecord;
|
|
307
|
+
readonly decode: KafkaMessageDecoder;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* CloudEvents 1.0 binary content mode, the default: the value is the JSON
|
|
311
|
+
* payload, the attributes travel as `ce_*` headers ({@link encodeEnvelope}).
|
|
312
|
+
* Decoding is strict: any other record is malformed ({@link decodeEnvelope}).
|
|
313
|
+
*/
|
|
314
|
+
declare const cloudEventsBinary: KafkaCodec;
|
|
315
|
+
/**
|
|
316
|
+
* CloudEvents 1.0 structured content mode: the value is one
|
|
317
|
+
* `application/cloudevents+json` document with the attributes and `data`.
|
|
318
|
+
* Decoding accepts structured and binary mode ({@link decodeCloudEvent}), so a
|
|
319
|
+
* topic can move from one to the other while both are in flight.
|
|
320
|
+
*/
|
|
321
|
+
declare const cloudEventsStructured: KafkaCodec;
|
|
322
|
+
/**
|
|
323
|
+
* Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides
|
|
324
|
+
* `{ body }` and `{ header }`, the id may be `'record-position'`: a consumed
|
|
325
|
+
* record gets `kafka:<topic>:<partition>:<offset>`, stable across redeliveries
|
|
326
|
+
* but different for two sends of one event. Records relaybus writes carry the
|
|
327
|
+
* event id in a `relaybus-event-id` header, which wins on read, so an outbox
|
|
328
|
+
* retry that sends an event twice is still deduplicated.
|
|
329
|
+
*/
|
|
330
|
+
type KafkaJsonEnvelopeMapping = JsonEnvelopeMapping<'record-position'>;
|
|
331
|
+
/**
|
|
332
|
+
* A JSON wire format declared by a mapping, in both directions: for topics
|
|
333
|
+
* shared with services that wrap events in their own envelope
|
|
334
|
+
* (`{ "eventName": ..., "data": {...} }`, MassTransit) or send the bare
|
|
335
|
+
* payload. The record key is always the event key; when `occurredAt` is not
|
|
336
|
+
* mapped, the record timestamp carries it. Event headers that are message
|
|
337
|
+
* headers are written as they are, so a name the mapping uses for another
|
|
338
|
+
* field is refused with {@link UnencodableEventError}, as are `content-type`
|
|
339
|
+
* and `relaybus-event-id`.
|
|
340
|
+
*
|
|
341
|
+
* ```ts
|
|
342
|
+
* codec: jsonEnvelope({
|
|
343
|
+
* type: { body: 'eventName' },
|
|
344
|
+
* id: { body: 'messageId' },
|
|
345
|
+
* payload: { body: 'data' },
|
|
346
|
+
* correlationId: { body: 'meta.correlationId' },
|
|
347
|
+
* })
|
|
348
|
+
* ```
|
|
349
|
+
*
|
|
350
|
+
* @throws ConfigurationError for an incomplete or self-overlapping mapping.
|
|
351
|
+
*/
|
|
352
|
+
declare function jsonEnvelope(mapping: KafkaJsonEnvelopeMapping): KafkaCodec;
|
|
353
|
+
|
|
265
354
|
/** A record the transport refused to hand to the bus because it is malformed. */
|
|
266
355
|
interface InvalidKafkaMessage {
|
|
267
356
|
readonly topic: string;
|
|
@@ -291,14 +380,6 @@ interface InvalidKafkaMessage {
|
|
|
291
380
|
type InvalidMessagePolicy = 'dead-letter' | 'skip' | ((message: InvalidKafkaMessage) => void | Promise<void>) | {
|
|
292
381
|
readonly deadLetterTopic: string | ((sourceTopic: string) => string);
|
|
293
382
|
};
|
|
294
|
-
/** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
|
|
295
|
-
declare class PublishTimeoutError extends RelayBusError {
|
|
296
|
-
name: string;
|
|
297
|
-
}
|
|
298
|
-
/** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
|
|
299
|
-
declare class HandlerFailedError extends RelayBusError {
|
|
300
|
-
name: string;
|
|
301
|
-
}
|
|
302
383
|
/** Bounded in-process retries around the inbound handler (the bus's `receive`). */
|
|
303
384
|
interface KafkaProcessingOptions {
|
|
304
385
|
/** Attempts per delivery of a record before the error is handed to the client. Default 5. */
|
|
@@ -344,14 +425,22 @@ interface KafkaTransportOptions {
|
|
|
344
425
|
/** Handling of records that cannot be processed for good. Default `'dead-letter'`. */
|
|
345
426
|
readonly onInvalidMessage?: InvalidMessagePolicy;
|
|
346
427
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
* other record is malformed and goes to
|
|
350
|
-
*
|
|
351
|
-
* {@link
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
428
|
+
* The wire format, both ways: how events become records and consumed records
|
|
429
|
+
* become events. Default {@link cloudEventsBinary}: CloudEvents binary mode,
|
|
430
|
+
* strict on read, so any other record is malformed and goes to
|
|
431
|
+
* `onInvalidMessage`. {@link cloudEventsStructured} writes structured mode
|
|
432
|
+
* and reads both, {@link jsonEnvelope} maps a JSON format of your own (an
|
|
433
|
+
* envelope with the payload inside, or the bare payload), and an object with
|
|
434
|
+
* `encode` and `decode` can do anything else. Whatever a non-default codec's
|
|
435
|
+
* `decode` throws marks the record as malformed, never crashes the consumer.
|
|
436
|
+
*/
|
|
437
|
+
readonly codec?: KafkaCodec;
|
|
438
|
+
/**
|
|
439
|
+
* How consumed records become events; events are still written in
|
|
440
|
+
* CloudEvents binary mode.
|
|
441
|
+
*
|
|
442
|
+
* @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.
|
|
443
|
+
* Giving both `decode` and `codec` is a configuration error.
|
|
355
444
|
*/
|
|
356
445
|
readonly decode?: KafkaMessageDecoder;
|
|
357
446
|
/** Default `console`. */
|
|
@@ -360,8 +449,8 @@ interface KafkaTransportOptions {
|
|
|
360
449
|
/**
|
|
361
450
|
* Kafka {@link Transport}. Events travel as CloudEvents binary-mode records
|
|
362
451
|
* (`ce_*` headers, JSON value), so any CloudEvents-aware consumer can read them.
|
|
363
|
-
*
|
|
364
|
-
*
|
|
452
|
+
* The `codec` option changes the wire format, for example to read and write
|
|
453
|
+
* the JSON format of services that do not use relaybus.
|
|
365
454
|
*
|
|
366
455
|
* Publishing: idempotent producer, `acks=-1`, resolves after the broker ack and
|
|
367
456
|
* rejects with {@link PublishTimeoutError} after `publishTimeout`. A timed-out
|
|
@@ -383,6 +472,7 @@ interface KafkaTransportOptions {
|
|
|
383
472
|
declare class KafkaTransport implements Transport {
|
|
384
473
|
#private;
|
|
385
474
|
readonly name: string;
|
|
475
|
+
readonly system = "kafka";
|
|
386
476
|
constructor(options: KafkaTransportOptions);
|
|
387
477
|
/**
|
|
388
478
|
* True while the consumer is joined to its group, not between a crash or
|
|
@@ -407,38 +497,9 @@ declare class KafkaTransport implements Transport {
|
|
|
407
497
|
* @throws ConfigurationError when `groupId` is missing, `destinations` is empty
|
|
408
498
|
* or the transport already subscribed (create one transport per subscription).
|
|
409
499
|
*/
|
|
410
|
-
subscribe(destinations: readonly string[], onMessage: TransportMessageHandler): Promise<void>;
|
|
500
|
+
subscribe(destinations: readonly string[], onMessage: TransportMessageHandler, hooks?: TransportSubscriptionHooks): Promise<void>;
|
|
411
501
|
/** Stops consuming and disconnects the consumer and the producer. Safe to call twice. */
|
|
412
502
|
close(): Promise<void>;
|
|
413
503
|
}
|
|
414
504
|
|
|
415
|
-
|
|
416
|
-
* Reads one header of an incoming message, for the `type`, `id`, `key` or
|
|
417
|
-
* `source` option of {@link plainJsonDecoder}. Header names are compared
|
|
418
|
-
* exactly (Kafka header names are case-sensitive). Returns undefined when the
|
|
419
|
-
* header is absent, so the decoder falls back to its default.
|
|
420
|
-
*
|
|
421
|
-
* ```ts
|
|
422
|
-
* plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })
|
|
423
|
-
* ```
|
|
424
|
-
*/
|
|
425
|
-
declare function fromHeader(name: string): (message: {
|
|
426
|
-
readonly headers: EventHeaders;
|
|
427
|
-
}) => string | undefined;
|
|
428
|
-
/**
|
|
429
|
-
* Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for
|
|
430
|
-
* the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A
|
|
431
|
-
* string is returned as is and a safe integer as its decimal text (numeric ids
|
|
432
|
-
* are common). Anything else returns undefined so the decoder falls back to its
|
|
433
|
-
* default: a missing field, and also a fraction or an integer beyond 2^53, which
|
|
434
|
-
* JSON parsing may already have rounded, so two different ids could collide.
|
|
435
|
-
*
|
|
436
|
-
* ```ts
|
|
437
|
-
* plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })
|
|
438
|
-
* ```
|
|
439
|
-
*/
|
|
440
|
-
declare function fromPayloadField(path: string): (message: {
|
|
441
|
-
readonly payload: unknown;
|
|
442
|
-
}) => string | undefined;
|
|
443
|
-
|
|
444
|
-
export { type DecodableMessage, type DecodedEvent, type EncodedMessage, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, UnencodableEventError, decodeCloudEvent, decodeEnvelope, encodeEnvelope, fromHeader, fromPayloadField, plainJsonDecoder };
|
|
505
|
+
export { type DecodableMessage, type DecodedEvent, type EncodedMessage, GroupJoinTimeoutError, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaCodec, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaEncodedRecord, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaJsonEnvelopeMapping, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, TransportClosedError, UnencodableEventError, cloudEventsBinary, cloudEventsStructured, decodeCloudEvent, decodeEnvelope, encodeEnvelope, jsonEnvelope, plainJsonDecoder };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,42 @@
|
|
|
1
|
-
import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, Transport, RelayBusLogger, TransportMessageHandler } from '@relaybus/core';
|
|
1
|
+
import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, Transport, RelayBusLogger, TransportMessageHandler, TransportSubscriptionHooks } from '@relaybus/core';
|
|
2
|
+
import { JsonEnvelopeMapping } from '@relaybus/core/internal';
|
|
3
|
+
export { fromHeader, fromPayloadField } from '@relaybus/core/internal';
|
|
4
|
+
|
|
5
|
+
/** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
|
|
6
|
+
declare class InvalidKafkaMessageError extends RelayBusError {
|
|
7
|
+
name: string;
|
|
8
|
+
readonly code: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* An event that cannot be written to Kafka: its payload is not representable as
|
|
12
|
+
* JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
|
|
13
|
+
* its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
|
|
14
|
+
* Retrying cannot help, so it is a {@link NonRetryableError}.
|
|
15
|
+
*/
|
|
16
|
+
declare class UnencodableEventError extends NonRetryableError {
|
|
17
|
+
name: string;
|
|
18
|
+
readonly code: string;
|
|
19
|
+
}
|
|
20
|
+
/** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
|
|
21
|
+
declare class PublishTimeoutError extends RelayBusError {
|
|
22
|
+
name: string;
|
|
23
|
+
readonly code: string;
|
|
24
|
+
}
|
|
25
|
+
/** The transport was closed: it no longer publishes or subscribes. */
|
|
26
|
+
declare class TransportClosedError extends RelayBusError {
|
|
27
|
+
name: string;
|
|
28
|
+
readonly code: string;
|
|
29
|
+
}
|
|
30
|
+
/** The consumer did not join its group within `startupTimeout`. */
|
|
31
|
+
declare class GroupJoinTimeoutError extends RelayBusError {
|
|
32
|
+
name: string;
|
|
33
|
+
readonly code: string;
|
|
34
|
+
}
|
|
35
|
+
/** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
|
|
36
|
+
declare class HandlerFailedError extends RelayBusError {
|
|
37
|
+
name: string;
|
|
38
|
+
readonly code: string;
|
|
39
|
+
}
|
|
2
40
|
|
|
3
41
|
/**
|
|
4
42
|
* Structural views of the Kafka client API used by this package.
|
|
@@ -97,18 +135,6 @@ interface KafkaClientLike {
|
|
|
97
135
|
consumer(config: KafkaConsumerConfig): KafkaConsumerLike;
|
|
98
136
|
}
|
|
99
137
|
|
|
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
138
|
/** The wire form of one event: a Kafka record in CloudEvents binary content mode. */
|
|
113
139
|
interface EncodedMessage {
|
|
114
140
|
readonly key: string | null;
|
|
@@ -262,6 +288,69 @@ declare function decodeCloudEvent(record: DecodableMessage): EventEnvelope;
|
|
|
262
288
|
*/
|
|
263
289
|
declare function plainJsonDecoder(options: PlainJsonDecoderOptions): KafkaMessageDecoder;
|
|
264
290
|
|
|
291
|
+
/** The record a codec produces for one event. `timestamp` is epoch milliseconds in a string. */
|
|
292
|
+
type KafkaEncodedRecord = KafkaOutgoingMessage & {
|
|
293
|
+
readonly timestamp?: string;
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* The wire format of a {@link KafkaTransport}: how an event becomes a record
|
|
297
|
+
* (`encode`, on publish) and a consumed record becomes an event (`decode`).
|
|
298
|
+
*
|
|
299
|
+
* Both must be synchronous and free of side effects. What `encode` throws
|
|
300
|
+
* fails the publish: the outbox retries it, unless it is a `NonRetryableError`
|
|
301
|
+
* such as {@link UnencodableEventError}. What `decode` throws marks the record
|
|
302
|
+
* as malformed: it goes to `onInvalidMessage` (dead-letter by default) and the
|
|
303
|
+
* consumer moves on. See {@link KafkaMessageDecoder} for the decode contract.
|
|
304
|
+
*/
|
|
305
|
+
interface KafkaCodec {
|
|
306
|
+
readonly encode: (envelope: EventEnvelope) => KafkaEncodedRecord;
|
|
307
|
+
readonly decode: KafkaMessageDecoder;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* CloudEvents 1.0 binary content mode, the default: the value is the JSON
|
|
311
|
+
* payload, the attributes travel as `ce_*` headers ({@link encodeEnvelope}).
|
|
312
|
+
* Decoding is strict: any other record is malformed ({@link decodeEnvelope}).
|
|
313
|
+
*/
|
|
314
|
+
declare const cloudEventsBinary: KafkaCodec;
|
|
315
|
+
/**
|
|
316
|
+
* CloudEvents 1.0 structured content mode: the value is one
|
|
317
|
+
* `application/cloudevents+json` document with the attributes and `data`.
|
|
318
|
+
* Decoding accepts structured and binary mode ({@link decodeCloudEvent}), so a
|
|
319
|
+
* topic can move from one to the other while both are in flight.
|
|
320
|
+
*/
|
|
321
|
+
declare const cloudEventsStructured: KafkaCodec;
|
|
322
|
+
/**
|
|
323
|
+
* Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides
|
|
324
|
+
* `{ body }` and `{ header }`, the id may be `'record-position'`: a consumed
|
|
325
|
+
* record gets `kafka:<topic>:<partition>:<offset>`, stable across redeliveries
|
|
326
|
+
* but different for two sends of one event. Records relaybus writes carry the
|
|
327
|
+
* event id in a `relaybus-event-id` header, which wins on read, so an outbox
|
|
328
|
+
* retry that sends an event twice is still deduplicated.
|
|
329
|
+
*/
|
|
330
|
+
type KafkaJsonEnvelopeMapping = JsonEnvelopeMapping<'record-position'>;
|
|
331
|
+
/**
|
|
332
|
+
* A JSON wire format declared by a mapping, in both directions: for topics
|
|
333
|
+
* shared with services that wrap events in their own envelope
|
|
334
|
+
* (`{ "eventName": ..., "data": {...} }`, MassTransit) or send the bare
|
|
335
|
+
* payload. The record key is always the event key; when `occurredAt` is not
|
|
336
|
+
* mapped, the record timestamp carries it. Event headers that are message
|
|
337
|
+
* headers are written as they are, so a name the mapping uses for another
|
|
338
|
+
* field is refused with {@link UnencodableEventError}, as are `content-type`
|
|
339
|
+
* and `relaybus-event-id`.
|
|
340
|
+
*
|
|
341
|
+
* ```ts
|
|
342
|
+
* codec: jsonEnvelope({
|
|
343
|
+
* type: { body: 'eventName' },
|
|
344
|
+
* id: { body: 'messageId' },
|
|
345
|
+
* payload: { body: 'data' },
|
|
346
|
+
* correlationId: { body: 'meta.correlationId' },
|
|
347
|
+
* })
|
|
348
|
+
* ```
|
|
349
|
+
*
|
|
350
|
+
* @throws ConfigurationError for an incomplete or self-overlapping mapping.
|
|
351
|
+
*/
|
|
352
|
+
declare function jsonEnvelope(mapping: KafkaJsonEnvelopeMapping): KafkaCodec;
|
|
353
|
+
|
|
265
354
|
/** A record the transport refused to hand to the bus because it is malformed. */
|
|
266
355
|
interface InvalidKafkaMessage {
|
|
267
356
|
readonly topic: string;
|
|
@@ -291,14 +380,6 @@ interface InvalidKafkaMessage {
|
|
|
291
380
|
type InvalidMessagePolicy = 'dead-letter' | 'skip' | ((message: InvalidKafkaMessage) => void | Promise<void>) | {
|
|
292
381
|
readonly deadLetterTopic: string | ((sourceTopic: string) => string);
|
|
293
382
|
};
|
|
294
|
-
/** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
|
|
295
|
-
declare class PublishTimeoutError extends RelayBusError {
|
|
296
|
-
name: string;
|
|
297
|
-
}
|
|
298
|
-
/** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
|
|
299
|
-
declare class HandlerFailedError extends RelayBusError {
|
|
300
|
-
name: string;
|
|
301
|
-
}
|
|
302
383
|
/** Bounded in-process retries around the inbound handler (the bus's `receive`). */
|
|
303
384
|
interface KafkaProcessingOptions {
|
|
304
385
|
/** Attempts per delivery of a record before the error is handed to the client. Default 5. */
|
|
@@ -344,14 +425,22 @@ interface KafkaTransportOptions {
|
|
|
344
425
|
/** Handling of records that cannot be processed for good. Default `'dead-letter'`. */
|
|
345
426
|
readonly onInvalidMessage?: InvalidMessagePolicy;
|
|
346
427
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
* other record is malformed and goes to
|
|
350
|
-
*
|
|
351
|
-
* {@link
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
428
|
+
* The wire format, both ways: how events become records and consumed records
|
|
429
|
+
* become events. Default {@link cloudEventsBinary}: CloudEvents binary mode,
|
|
430
|
+
* strict on read, so any other record is malformed and goes to
|
|
431
|
+
* `onInvalidMessage`. {@link cloudEventsStructured} writes structured mode
|
|
432
|
+
* and reads both, {@link jsonEnvelope} maps a JSON format of your own (an
|
|
433
|
+
* envelope with the payload inside, or the bare payload), and an object with
|
|
434
|
+
* `encode` and `decode` can do anything else. Whatever a non-default codec's
|
|
435
|
+
* `decode` throws marks the record as malformed, never crashes the consumer.
|
|
436
|
+
*/
|
|
437
|
+
readonly codec?: KafkaCodec;
|
|
438
|
+
/**
|
|
439
|
+
* How consumed records become events; events are still written in
|
|
440
|
+
* CloudEvents binary mode.
|
|
441
|
+
*
|
|
442
|
+
* @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.
|
|
443
|
+
* Giving both `decode` and `codec` is a configuration error.
|
|
355
444
|
*/
|
|
356
445
|
readonly decode?: KafkaMessageDecoder;
|
|
357
446
|
/** Default `console`. */
|
|
@@ -360,8 +449,8 @@ interface KafkaTransportOptions {
|
|
|
360
449
|
/**
|
|
361
450
|
* Kafka {@link Transport}. Events travel as CloudEvents binary-mode records
|
|
362
451
|
* (`ce_*` headers, JSON value), so any CloudEvents-aware consumer can read them.
|
|
363
|
-
*
|
|
364
|
-
*
|
|
452
|
+
* The `codec` option changes the wire format, for example to read and write
|
|
453
|
+
* the JSON format of services that do not use relaybus.
|
|
365
454
|
*
|
|
366
455
|
* Publishing: idempotent producer, `acks=-1`, resolves after the broker ack and
|
|
367
456
|
* rejects with {@link PublishTimeoutError} after `publishTimeout`. A timed-out
|
|
@@ -383,6 +472,7 @@ interface KafkaTransportOptions {
|
|
|
383
472
|
declare class KafkaTransport implements Transport {
|
|
384
473
|
#private;
|
|
385
474
|
readonly name: string;
|
|
475
|
+
readonly system = "kafka";
|
|
386
476
|
constructor(options: KafkaTransportOptions);
|
|
387
477
|
/**
|
|
388
478
|
* True while the consumer is joined to its group, not between a crash or
|
|
@@ -407,38 +497,9 @@ declare class KafkaTransport implements Transport {
|
|
|
407
497
|
* @throws ConfigurationError when `groupId` is missing, `destinations` is empty
|
|
408
498
|
* or the transport already subscribed (create one transport per subscription).
|
|
409
499
|
*/
|
|
410
|
-
subscribe(destinations: readonly string[], onMessage: TransportMessageHandler): Promise<void>;
|
|
500
|
+
subscribe(destinations: readonly string[], onMessage: TransportMessageHandler, hooks?: TransportSubscriptionHooks): Promise<void>;
|
|
411
501
|
/** Stops consuming and disconnects the consumer and the producer. Safe to call twice. */
|
|
412
502
|
close(): Promise<void>;
|
|
413
503
|
}
|
|
414
504
|
|
|
415
|
-
|
|
416
|
-
* Reads one header of an incoming message, for the `type`, `id`, `key` or
|
|
417
|
-
* `source` option of {@link plainJsonDecoder}. Header names are compared
|
|
418
|
-
* exactly (Kafka header names are case-sensitive). Returns undefined when the
|
|
419
|
-
* header is absent, so the decoder falls back to its default.
|
|
420
|
-
*
|
|
421
|
-
* ```ts
|
|
422
|
-
* plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })
|
|
423
|
-
* ```
|
|
424
|
-
*/
|
|
425
|
-
declare function fromHeader(name: string): (message: {
|
|
426
|
-
readonly headers: EventHeaders;
|
|
427
|
-
}) => string | undefined;
|
|
428
|
-
/**
|
|
429
|
-
* Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for
|
|
430
|
-
* the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A
|
|
431
|
-
* string is returned as is and a safe integer as its decimal text (numeric ids
|
|
432
|
-
* are common). Anything else returns undefined so the decoder falls back to its
|
|
433
|
-
* default: a missing field, and also a fraction or an integer beyond 2^53, which
|
|
434
|
-
* JSON parsing may already have rounded, so two different ids could collide.
|
|
435
|
-
*
|
|
436
|
-
* ```ts
|
|
437
|
-
* plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })
|
|
438
|
-
* ```
|
|
439
|
-
*/
|
|
440
|
-
declare function fromPayloadField(path: string): (message: {
|
|
441
|
-
readonly payload: unknown;
|
|
442
|
-
}) => string | undefined;
|
|
443
|
-
|
|
444
|
-
export { type DecodableMessage, type DecodedEvent, type EncodedMessage, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, UnencodableEventError, decodeCloudEvent, decodeEnvelope, encodeEnvelope, fromHeader, fromPayloadField, plainJsonDecoder };
|
|
505
|
+
export { type DecodableMessage, type DecodedEvent, type EncodedMessage, GroupJoinTimeoutError, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaCodec, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaEncodedRecord, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaJsonEnvelopeMapping, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, TransportClosedError, UnencodableEventError, cloudEventsBinary, cloudEventsStructured, decodeCloudEvent, decodeEnvelope, encodeEnvelope, jsonEnvelope, plainJsonDecoder };
|