@platformatic/kafka 0.2.0 → 0.4.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/dist/clients/consumer/consumer.js +6 -5
- package/dist/clients/consumer/messages-stream.js +2 -2
- package/dist/clients/consumer/options.d.ts +119 -0
- package/dist/clients/consumer/options.js +13 -3
- package/dist/clients/producer/options.d.ts +30 -0
- package/dist/clients/producer/options.js +1 -1
- package/dist/clients/producer/producer.js +15 -10
- package/dist/clients/serde.d.ts +6 -4
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ import { defaultBaseOptions } from "../base/options.js";
|
|
|
16
16
|
import { createPromisifiedCallback, kCallbackPromise, runConcurrentCallbacks } from "../callbacks.js";
|
|
17
17
|
import { ensureMetric } from "../metrics.js";
|
|
18
18
|
import { MessagesStream } from "./messages-stream.js";
|
|
19
|
-
import { commitOptionsValidator, consumeOptionsValidator, consumerOptionsValidator, defaultConsumerOptions, fetchOptionsValidator, groupOptionsValidator, listCommitsOptionsValidator, listOffsetsOptionsValidator } from "./options.js";
|
|
19
|
+
import { commitOptionsValidator, consumeOptionsValidator, consumerOptionsValidator, defaultConsumerOptions, fetchOptionsValidator, groupIdAndOptionsValidator, groupOptionsValidator, listCommitsOptionsValidator, listOffsetsOptionsValidator } from "./options.js";
|
|
20
20
|
import { TopicsMap } from "./topics-map.js";
|
|
21
21
|
export class Consumer extends Base {
|
|
22
22
|
groupId;
|
|
@@ -64,7 +64,7 @@ export class Consumer extends Base {
|
|
|
64
64
|
this.#coordinatorId = null;
|
|
65
65
|
this.#heartbeatInterval = null;
|
|
66
66
|
this.#streams = new Set();
|
|
67
|
-
this.#validateGroupOptions(this[kOptions]);
|
|
67
|
+
this.#validateGroupOptions(this[kOptions], groupIdAndOptionsValidator);
|
|
68
68
|
// Initialize connection pool
|
|
69
69
|
this[kFetchConnections] = this[kCreateConnectionPool]();
|
|
70
70
|
if (this[kPrometheus]) {
|
|
@@ -688,10 +688,11 @@ export class Consumer extends Base {
|
|
|
688
688
|
});
|
|
689
689
|
});
|
|
690
690
|
}
|
|
691
|
-
#validateGroupOptions(options) {
|
|
692
|
-
|
|
691
|
+
#validateGroupOptions(options, validator) {
|
|
692
|
+
validator ??= groupOptionsValidator;
|
|
693
|
+
const valid = validator(options);
|
|
693
694
|
if (!valid) {
|
|
694
|
-
throw new UserError(this[kFormatValidationErrors](
|
|
695
|
+
throw new UserError(this[kFormatValidationErrors](validator, '/options'));
|
|
695
696
|
}
|
|
696
697
|
}
|
|
697
698
|
/*
|
|
@@ -269,12 +269,12 @@ export class MessagesStream extends Readable {
|
|
|
269
269
|
const firstTimestamp = records.firstTimestamp;
|
|
270
270
|
const leaderEpoch = metadata.topics.get(topic).partitions[partition].leaderEpoch;
|
|
271
271
|
for (const record of records.records) {
|
|
272
|
-
const key = keyDeserializer(record.key);
|
|
273
|
-
const value = valueDeserializer(record.value);
|
|
274
272
|
const headers = new Map();
|
|
275
273
|
for (const [headerKey, headerValue] of record.headers) {
|
|
276
274
|
headers.set(headerKeyDeserializer(headerKey), headerValueDeserializer(headerValue));
|
|
277
275
|
}
|
|
276
|
+
const key = keyDeserializer(record.key, headers);
|
|
277
|
+
const value = valueDeserializer(record.value, headers);
|
|
278
278
|
this.#metricsConsumedMessages?.inc();
|
|
279
279
|
canPush = this.push({
|
|
280
280
|
key,
|
|
@@ -1,4 +1,120 @@
|
|
|
1
1
|
import { type ConsumerOptions } from './types.ts';
|
|
2
|
+
export declare const groupOptionsProperties: {
|
|
3
|
+
sessionTimeout: {
|
|
4
|
+
type: string;
|
|
5
|
+
minimum: number;
|
|
6
|
+
};
|
|
7
|
+
rebalanceTimeout: {
|
|
8
|
+
type: string;
|
|
9
|
+
minimum: number;
|
|
10
|
+
};
|
|
11
|
+
heartbeatInterval: {
|
|
12
|
+
type: string;
|
|
13
|
+
minimum: number;
|
|
14
|
+
};
|
|
15
|
+
protocols: {
|
|
16
|
+
type: string;
|
|
17
|
+
items: {
|
|
18
|
+
type: string;
|
|
19
|
+
properties: {
|
|
20
|
+
name: {
|
|
21
|
+
type: string;
|
|
22
|
+
pattern: string;
|
|
23
|
+
};
|
|
24
|
+
version: {
|
|
25
|
+
type: string;
|
|
26
|
+
minimum: number;
|
|
27
|
+
};
|
|
28
|
+
topics: {
|
|
29
|
+
type: string;
|
|
30
|
+
items: {
|
|
31
|
+
type: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
metadata: {
|
|
35
|
+
oneOf: ({
|
|
36
|
+
type: string;
|
|
37
|
+
buffer?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
buffer: boolean;
|
|
40
|
+
type?: undefined;
|
|
41
|
+
})[];
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export declare const groupOptionsAdditionalValidations: {
|
|
48
|
+
rebalanceTimeout: {
|
|
49
|
+
properties: {
|
|
50
|
+
rebalanceTimeout: {
|
|
51
|
+
type: string;
|
|
52
|
+
minimum: number;
|
|
53
|
+
gteProperty: string;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
heartbeatInterval: {
|
|
58
|
+
properties: {
|
|
59
|
+
heartbeatInterval: {
|
|
60
|
+
type: string;
|
|
61
|
+
minimum: number;
|
|
62
|
+
allOf: {
|
|
63
|
+
lteProperty: string;
|
|
64
|
+
}[];
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export declare const consumeOptionsProperties: {
|
|
70
|
+
autocommit: {
|
|
71
|
+
oneOf: ({
|
|
72
|
+
type: string;
|
|
73
|
+
minimum?: undefined;
|
|
74
|
+
} | {
|
|
75
|
+
type: string;
|
|
76
|
+
minimum: number;
|
|
77
|
+
})[];
|
|
78
|
+
};
|
|
79
|
+
minBytes: {
|
|
80
|
+
type: string;
|
|
81
|
+
minimum: number;
|
|
82
|
+
};
|
|
83
|
+
maxBytes: {
|
|
84
|
+
type: string;
|
|
85
|
+
minimum: number;
|
|
86
|
+
};
|
|
87
|
+
maxWaitTime: {
|
|
88
|
+
type: string;
|
|
89
|
+
minimum: number;
|
|
90
|
+
};
|
|
91
|
+
isolationLevel: {
|
|
92
|
+
type: string;
|
|
93
|
+
enum: string[];
|
|
94
|
+
};
|
|
95
|
+
deserializers: {
|
|
96
|
+
type: string;
|
|
97
|
+
properties: {
|
|
98
|
+
key: {
|
|
99
|
+
function: boolean;
|
|
100
|
+
};
|
|
101
|
+
value: {
|
|
102
|
+
function: boolean;
|
|
103
|
+
};
|
|
104
|
+
headerKey: {
|
|
105
|
+
function: boolean;
|
|
106
|
+
};
|
|
107
|
+
headerValue: {
|
|
108
|
+
function: boolean;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
additionalProperties: boolean;
|
|
112
|
+
};
|
|
113
|
+
highWaterMark: {
|
|
114
|
+
type: string;
|
|
115
|
+
minimum: number;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
2
118
|
export declare const groupOptionsSchema: {
|
|
3
119
|
type: string;
|
|
4
120
|
properties: {
|
|
@@ -500,6 +616,9 @@ export declare const listOffsetsOptionsSchema: {
|
|
|
500
616
|
additionalProperties: boolean;
|
|
501
617
|
};
|
|
502
618
|
export declare const groupOptionsValidator: import("ajv").ValidateFunction<unknown>;
|
|
619
|
+
export declare const groupIdAndOptionsValidator: import("ajv").ValidateFunction<{
|
|
620
|
+
groupId: any;
|
|
621
|
+
}>;
|
|
503
622
|
export declare const consumeOptionsValidator: import("ajv").ValidateFunction<{
|
|
504
623
|
[x: string]: {};
|
|
505
624
|
}>;
|
|
@@ -3,7 +3,7 @@ import { ajv } from "../../utils.js";
|
|
|
3
3
|
import { idProperty, topicWithPartitionAndOffsetProperties } from "../base/options.js";
|
|
4
4
|
import { serdeProperties } from "../serde.js";
|
|
5
5
|
import { MessagesStreamFallbackModes, MessagesStreamModes } from "./types.js";
|
|
6
|
-
const groupOptionsProperties = {
|
|
6
|
+
export const groupOptionsProperties = {
|
|
7
7
|
sessionTimeout: { type: 'number', minimum: 0 },
|
|
8
8
|
rebalanceTimeout: { type: 'number', minimum: 0 },
|
|
9
9
|
heartbeatInterval: { type: 'number', minimum: 0 },
|
|
@@ -23,7 +23,7 @@ const groupOptionsProperties = {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
-
const groupOptionsAdditionalValidations = {
|
|
26
|
+
export const groupOptionsAdditionalValidations = {
|
|
27
27
|
rebalanceTimeout: {
|
|
28
28
|
properties: {
|
|
29
29
|
rebalanceTimeout: {
|
|
@@ -50,7 +50,7 @@ const groupOptionsAdditionalValidations = {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
|
-
const consumeOptionsProperties = {
|
|
53
|
+
export const consumeOptionsProperties = {
|
|
54
54
|
autocommit: { oneOf: [{ type: 'boolean' }, { type: 'number', minimum: 100 }] },
|
|
55
55
|
minBytes: { type: 'number', minimum: 0 },
|
|
56
56
|
maxBytes: { type: 'number', minimum: 0 },
|
|
@@ -187,6 +187,16 @@ export const groupOptionsValidator = ajv.compile({
|
|
|
187
187
|
...groupOptionsSchema,
|
|
188
188
|
dependentSchemas: groupOptionsAdditionalValidations
|
|
189
189
|
});
|
|
190
|
+
export const groupIdAndOptionsValidator = ajv.compile({
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: {
|
|
193
|
+
groupId: idProperty,
|
|
194
|
+
...groupOptionsProperties
|
|
195
|
+
},
|
|
196
|
+
required: ['groupId'],
|
|
197
|
+
additionalProperties: true,
|
|
198
|
+
dependentSchemas: groupOptionsAdditionalValidations
|
|
199
|
+
});
|
|
190
200
|
export const consumeOptionsValidator = ajv.compile(consumeOptionsSchema);
|
|
191
201
|
export const consumerOptionsValidator = ajv.compile(consumerOptionsSchema);
|
|
192
202
|
export const fetchOptionsValidator = ajv.compile(fetchOptionsSchema);
|
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
export declare const produceOptionsProperties: {
|
|
2
|
+
producerId: {
|
|
3
|
+
bigint: boolean;
|
|
4
|
+
};
|
|
5
|
+
producerEpoch: {
|
|
6
|
+
type: string;
|
|
7
|
+
};
|
|
8
|
+
idempotent: {
|
|
9
|
+
type: string;
|
|
10
|
+
};
|
|
11
|
+
acks: {
|
|
12
|
+
type: string;
|
|
13
|
+
enum: (0 | 1 | -1)[];
|
|
14
|
+
errorMessage: string;
|
|
15
|
+
};
|
|
16
|
+
compression: {
|
|
17
|
+
type: string;
|
|
18
|
+
enum: string[];
|
|
19
|
+
errorMessage: string;
|
|
20
|
+
};
|
|
21
|
+
partitioner: {
|
|
22
|
+
function: boolean;
|
|
23
|
+
};
|
|
24
|
+
autocreateTopics: {
|
|
25
|
+
type: string;
|
|
26
|
+
};
|
|
27
|
+
repeatOnStaleMetadata: {
|
|
28
|
+
type: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
1
31
|
export declare const produceOptionsSchema: {
|
|
2
32
|
type: string;
|
|
3
33
|
properties: {
|
|
@@ -3,7 +3,7 @@ import { compressionsAlgorithms } from "../../protocol/compression.js";
|
|
|
3
3
|
import { messageSchema } from "../../protocol/records.js";
|
|
4
4
|
import { ajv, enumErrorMessage } from "../../utils.js";
|
|
5
5
|
import { serdeProperties } from "../serde.js";
|
|
6
|
-
const produceOptionsProperties = {
|
|
6
|
+
export const produceOptionsProperties = {
|
|
7
7
|
producerId: { bigint: true },
|
|
8
8
|
producerEpoch: { type: 'number' },
|
|
9
9
|
idempotent: { type: 'boolean' },
|
|
@@ -159,8 +159,19 @@ export class Producer extends Base {
|
|
|
159
159
|
const messages = [];
|
|
160
160
|
for (const message of options.messages) {
|
|
161
161
|
const topic = message.topic;
|
|
162
|
-
|
|
163
|
-
const
|
|
162
|
+
let headers = new Map();
|
|
163
|
+
const serializedHeaders = new Map();
|
|
164
|
+
if (message.headers) {
|
|
165
|
+
headers =
|
|
166
|
+
message.headers instanceof Map
|
|
167
|
+
? message.headers
|
|
168
|
+
: new Map(Object.entries(message.headers));
|
|
169
|
+
for (const [key, value] of headers) {
|
|
170
|
+
serializedHeaders.set(this.#headerKeySerializer(key), this.#headerValueSerializer(value));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const key = this.#keySerializer(message.key, headers);
|
|
174
|
+
const value = this.#valueSerializer(message.value, headers);
|
|
164
175
|
let partition = 0;
|
|
165
176
|
if (typeof message.partition !== 'number') {
|
|
166
177
|
if (partitioner) {
|
|
@@ -177,17 +188,11 @@ export class Producer extends Base {
|
|
|
177
188
|
else {
|
|
178
189
|
partition = message.partition;
|
|
179
190
|
}
|
|
180
|
-
if (message.headers) {
|
|
181
|
-
const entries = message.headers instanceof Map ? message.headers : Object.entries(message.headers);
|
|
182
|
-
for (const [key, value] of entries) {
|
|
183
|
-
headers.set(this.#headerKeySerializer(key), this.#headerValueSerializer(value));
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
191
|
topics.add(topic);
|
|
187
192
|
messages.push({
|
|
188
193
|
key,
|
|
189
|
-
value
|
|
190
|
-
headers,
|
|
194
|
+
value,
|
|
195
|
+
headers: serializedHeaders,
|
|
191
196
|
topic,
|
|
192
197
|
partition,
|
|
193
198
|
timestamp: message.timestamp
|
package/dist/clients/serde.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
export type Serializer<InputType = unknown> = (data?: InputType) => Buffer | undefined;
|
|
2
2
|
export type Deserializer<OutputType = unknown> = (data?: Buffer) => OutputType | undefined;
|
|
3
|
+
export type SerializerWithHeaders<InputType = unknown, HeaderKey = unknown, HeaderValue = unknown> = (data?: InputType, headers?: Map<HeaderKey, HeaderValue>) => Buffer | undefined;
|
|
4
|
+
export type DeserializerWithHeaders<OutputType = unknown, HeaderKey = unknown, HeaderValue = unknown> = (data?: Buffer, headers?: Map<HeaderKey, HeaderValue>) => OutputType | undefined;
|
|
3
5
|
export interface Serializers<Key, Value, HeaderKey, HeaderValue> {
|
|
4
|
-
key:
|
|
5
|
-
value:
|
|
6
|
+
key: SerializerWithHeaders<Key, HeaderKey, HeaderValue>;
|
|
7
|
+
value: SerializerWithHeaders<Value, HeaderKey, HeaderValue>;
|
|
6
8
|
headerKey: Serializer<HeaderKey>;
|
|
7
9
|
headerValue: Serializer<HeaderValue>;
|
|
8
10
|
}
|
|
9
11
|
export interface Deserializers<Key, Value, HeaderKey, HeaderValue> {
|
|
10
|
-
key:
|
|
11
|
-
value:
|
|
12
|
+
key: DeserializerWithHeaders<Key>;
|
|
13
|
+
value: DeserializerWithHeaders<Value>;
|
|
12
14
|
headerKey: Deserializer<HeaderKey>;
|
|
13
15
|
headerValue: Deserializer<HeaderValue>;
|
|
14
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/kafka",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Modern and performant client for Apache Kafka",
|
|
5
5
|
"homepage": "https://github.com/platformatic/kafka",
|
|
6
6
|
"author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
|