@platformatic/kafka 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +270 -0
- package/dist/apis/admin/alter-client-quotas.d.ts +33 -0
- package/dist/apis/admin/alter-client-quotas.js +64 -0
- package/dist/apis/admin/alter-configs.d.ts +26 -0
- package/dist/apis/admin/alter-configs.js +57 -0
- package/dist/apis/admin/alter-partition-reassignments.d.ts +30 -0
- package/dist/apis/admin/alter-partition-reassignments.js +68 -0
- package/dist/apis/admin/alter-partition.d.ts +39 -0
- package/dist/apis/admin/alter-partition.js +87 -0
- package/dist/apis/admin/alter-replica-log-dirs.d.ts +26 -0
- package/dist/apis/admin/alter-replica-log-dirs.js +55 -0
- package/dist/apis/admin/alter-user-scram-credentials.d.ts +27 -0
- package/dist/apis/admin/alter-user-scram-credentials.js +60 -0
- package/dist/apis/admin/consumer-group-describe.d.ts +41 -0
- package/dist/apis/admin/consumer-group-describe.js +103 -0
- package/dist/apis/admin/create-acls.d.ts +24 -0
- package/dist/apis/admin/create-acls.js +55 -0
- package/dist/apis/admin/create-delegation-token.d.ts +24 -0
- package/dist/apis/admin/create-delegation-token.js +54 -0
- package/dist/apis/admin/create-partitions.d.ts +24 -0
- package/dist/apis/admin/create-partitions.js +54 -0
- package/dist/apis/admin/create-topics.d.ts +42 -0
- package/dist/apis/admin/create-topics.js +86 -0
- package/dist/apis/admin/delete-acls.d.ts +36 -0
- package/dist/apis/admin/delete-acls.js +82 -0
- package/dist/apis/admin/delete-groups.d.ts +14 -0
- package/dist/apis/admin/delete-groups.js +40 -0
- package/dist/apis/admin/delete-records.d.ts +27 -0
- package/dist/apis/admin/delete-records.js +59 -0
- package/dist/apis/admin/delete-topics.d.ts +21 -0
- package/dist/apis/admin/delete-topics.js +50 -0
- package/dist/apis/admin/describe-acls.d.ts +25 -0
- package/dist/apis/admin/describe-acls.js +66 -0
- package/dist/apis/admin/describe-client-quotas.d.ts +30 -0
- package/dist/apis/admin/describe-client-quotas.js +57 -0
- package/dist/apis/admin/describe-cluster.d.ts +23 -0
- package/dist/apis/admin/describe-cluster.js +50 -0
- package/dist/apis/admin/describe-configs.d.ts +38 -0
- package/dist/apis/admin/describe-configs.js +85 -0
- package/dist/apis/admin/describe-delegation-token.d.ts +31 -0
- package/dist/apis/admin/describe-delegation-token.js +62 -0
- package/dist/apis/admin/describe-groups.d.ts +28 -0
- package/dist/apis/admin/describe-groups.js +67 -0
- package/dist/apis/admin/describe-log-dirs.d.ts +32 -0
- package/dist/apis/admin/describe-log-dirs.js +75 -0
- package/dist/apis/admin/describe-producers.d.ts +33 -0
- package/dist/apis/admin/describe-producers.js +70 -0
- package/dist/apis/admin/describe-quorum.d.ts +50 -0
- package/dist/apis/admin/describe-quorum.js +116 -0
- package/dist/apis/admin/describe-topic-partitions.d.ts +42 -0
- package/dist/apis/admin/describe-topic-partitions.js +94 -0
- package/dist/apis/admin/describe-transactions.d.ts +24 -0
- package/dist/apis/admin/describe-transactions.js +59 -0
- package/dist/apis/admin/describe-user-scram-credentials.d.ts +26 -0
- package/dist/apis/admin/describe-user-scram-credentials.js +62 -0
- package/dist/apis/admin/envelope.d.ts +10 -0
- package/dist/apis/admin/envelope.js +32 -0
- package/dist/apis/admin/expire-delegation-token.d.ts +11 -0
- package/dist/apis/admin/expire-delegation-token.js +29 -0
- package/dist/apis/admin/incremental-alter-configs.d.ts +27 -0
- package/dist/apis/admin/incremental-alter-configs.js +58 -0
- package/dist/apis/admin/index.d.ts +37 -0
- package/dist/apis/admin/index.js +37 -0
- package/dist/apis/admin/list-groups.d.ts +18 -0
- package/dist/apis/admin/list-groups.js +43 -0
- package/dist/apis/admin/list-partition-reassignments.d.ts +27 -0
- package/dist/apis/admin/list-partition-reassignments.js +56 -0
- package/dist/apis/admin/list-transactions.d.ts +18 -0
- package/dist/apis/admin/list-transactions.js +45 -0
- package/dist/apis/admin/offset-delete.d.ts +26 -0
- package/dist/apis/admin/offset-delete.js +59 -0
- package/dist/apis/admin/renew-delegation-token.d.ts +11 -0
- package/dist/apis/admin/renew-delegation-token.js +29 -0
- package/dist/apis/admin/unregister-broker.d.ts +12 -0
- package/dist/apis/admin/unregister-broker.js +28 -0
- package/dist/apis/admin/update-features.d.ts +23 -0
- package/dist/apis/admin/update-features.js +60 -0
- package/dist/apis/consumer/consumer-group-heartbeat.d.ts +27 -0
- package/dist/apis/consumer/consumer-group-heartbeat.js +70 -0
- package/dist/apis/consumer/fetch.d.ts +46 -0
- package/dist/apis/consumer/fetch.js +121 -0
- package/dist/apis/consumer/heartbeat.d.ts +11 -0
- package/dist/apis/consumer/heartbeat.js +34 -0
- package/dist/apis/consumer/index.d.ts +9 -0
- package/dist/apis/consumer/index.js +9 -0
- package/dist/apis/consumer/join-group.d.ts +27 -0
- package/dist/apis/consumer/join-group.js +71 -0
- package/dist/apis/consumer/leave-group.d.ts +22 -0
- package/dist/apis/consumer/leave-group.js +57 -0
- package/dist/apis/consumer/list-offsets.d.ts +30 -0
- package/dist/apis/consumer/list-offsets.js +68 -0
- package/dist/apis/consumer/offset-commit.d.ts +29 -0
- package/dist/apis/consumer/offset-commit.js +68 -0
- package/dist/apis/consumer/offset-fetch.d.ts +37 -0
- package/dist/apis/consumer/offset-fetch.js +81 -0
- package/dist/apis/consumer/sync-group.d.ts +18 -0
- package/dist/apis/consumer/sync-group.js +49 -0
- package/dist/apis/definitions.d.ts +16 -0
- package/dist/apis/definitions.js +12 -0
- package/dist/apis/enumerations.d.ts +114 -0
- package/dist/apis/enumerations.js +78 -0
- package/dist/apis/index.d.ts +8 -0
- package/dist/apis/index.js +10 -0
- package/dist/apis/metadata/api-versions.d.ts +17 -0
- package/dist/apis/metadata/api-versions.js +41 -0
- package/dist/apis/metadata/find-coordinator.d.ts +19 -0
- package/dist/apis/metadata/find-coordinator.js +50 -0
- package/dist/apis/metadata/index.d.ts +3 -0
- package/dist/apis/metadata/index.js +3 -0
- package/dist/apis/metadata/metadata.d.ts +37 -0
- package/dist/apis/metadata/metadata.js +92 -0
- package/dist/apis/producer/add-offsets-to-txn.d.ts +10 -0
- package/dist/apis/producer/add-offsets-to-txn.js +34 -0
- package/dist/apis/producer/add-partitions-to-txn.d.ts +34 -0
- package/dist/apis/producer/add-partitions-to-txn.js +79 -0
- package/dist/apis/producer/end-txn.d.ts +10 -0
- package/dist/apis/producer/end-txn.js +34 -0
- package/dist/apis/producer/index.d.ts +6 -0
- package/dist/apis/producer/index.js +6 -0
- package/dist/apis/producer/init-producer-id.d.ts +21 -0
- package/dist/apis/producer/init-producer-id.js +38 -0
- package/dist/apis/producer/produce.d.ts +29 -0
- package/dist/apis/producer/produce.js +104 -0
- package/dist/apis/producer/txn-offset-commit.d.ts +29 -0
- package/dist/apis/producer/txn-offset-commit.js +77 -0
- package/dist/apis/security/index.d.ts +2 -0
- package/dist/apis/security/index.js +2 -0
- package/dist/apis/security/sasl-authenticate.d.ts +15 -0
- package/dist/apis/security/sasl-authenticate.js +30 -0
- package/dist/apis/security/sasl-handshake.d.ts +10 -0
- package/dist/apis/security/sasl-handshake.js +28 -0
- package/dist/apis/telemetry/get-telemetry-subscriptions.d.ts +18 -0
- package/dist/apis/telemetry/get-telemetry-subscriptions.js +46 -0
- package/dist/apis/telemetry/index.d.ts +3 -0
- package/dist/apis/telemetry/index.js +3 -0
- package/dist/apis/telemetry/list-client-metrics-resources.d.ts +14 -0
- package/dist/apis/telemetry/list-client-metrics-resources.js +32 -0
- package/dist/apis/telemetry/push-telemetry.d.ts +10 -0
- package/dist/apis/telemetry/push-telemetry.js +36 -0
- package/dist/clients/admin/admin.d.ts +18 -0
- package/dist/clients/admin/admin.js +322 -0
- package/dist/clients/admin/index.d.ts +3 -0
- package/dist/clients/admin/index.js +3 -0
- package/dist/clients/admin/options.d.ts +135 -0
- package/dist/clients/admin/options.js +81 -0
- package/dist/clients/admin/types.d.ts +56 -0
- package/dist/clients/admin/types.js +1 -0
- package/dist/clients/base/base.d.ts +48 -0
- package/dist/clients/base/base.js +242 -0
- package/dist/clients/base/index.d.ts +3 -0
- package/dist/clients/base/index.js +3 -0
- package/dist/clients/base/options.d.ts +115 -0
- package/dist/clients/base/options.js +59 -0
- package/dist/clients/base/types.d.ts +38 -0
- package/dist/clients/base/types.js +1 -0
- package/dist/clients/callbacks.d.ts +8 -0
- package/dist/clients/callbacks.js +42 -0
- package/dist/clients/consumer/consumer.d.ts +33 -0
- package/dist/clients/consumer/consumer.js +767 -0
- package/dist/clients/consumer/index.d.ts +5 -0
- package/dist/clients/consumer/index.js +5 -0
- package/dist/clients/consumer/messages-stream.d.ts +56 -0
- package/dist/clients/consumer/messages-stream.js +404 -0
- package/dist/clients/consumer/options.d.ts +521 -0
- package/dist/clients/consumer/options.js +177 -0
- package/dist/clients/consumer/topics-map.d.ts +8 -0
- package/dist/clients/consumer/topics-map.js +48 -0
- package/dist/clients/consumer/types.d.ts +74 -0
- package/dist/clients/consumer/types.js +11 -0
- package/dist/clients/index.d.ts +6 -0
- package/dist/clients/index.js +6 -0
- package/dist/clients/producer/index.d.ts +3 -0
- package/dist/clients/producer/index.js +3 -0
- package/dist/clients/producer/options.d.ts +122 -0
- package/dist/clients/producer/options.js +47 -0
- package/dist/clients/producer/producer.d.ts +13 -0
- package/dist/clients/producer/producer.js +272 -0
- package/dist/clients/producer/types.d.ts +29 -0
- package/dist/clients/producer/types.js +1 -0
- package/dist/clients/serde.d.ts +40 -0
- package/dist/clients/serde.js +49 -0
- package/dist/errors.d.ts +67 -0
- package/dist/errors.js +160 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/network/connection-pool.d.ts +11 -0
- package/dist/network/connection-pool.js +101 -0
- package/dist/network/connection.d.ts +49 -0
- package/dist/network/connection.js +319 -0
- package/dist/network/index.d.ts +2 -0
- package/dist/network/index.js +2 -0
- package/dist/protocol/apis.d.ts +2 -0
- package/dist/protocol/apis.js +191 -0
- package/dist/protocol/compression.d.ts +70 -0
- package/dist/protocol/compression.js +114 -0
- package/dist/protocol/crc32c.d.ts +2 -0
- package/dist/protocol/crc32c.js +83 -0
- package/dist/protocol/definitions.d.ts +12 -0
- package/dist/protocol/definitions.js +11 -0
- package/dist/protocol/dynamic-buffer.d.ts +65 -0
- package/dist/protocol/dynamic-buffer.js +557 -0
- package/dist/protocol/errors.d.ts +8 -0
- package/dist/protocol/errors.js +908 -0
- package/dist/protocol/index.d.ts +14 -0
- package/dist/protocol/index.js +14 -0
- package/dist/protocol/murmur2.d.ts +1 -0
- package/dist/protocol/murmur2.js +55 -0
- package/dist/protocol/reader.d.ts +58 -0
- package/dist/protocol/reader.js +296 -0
- package/dist/protocol/records.d.ts +110 -0
- package/dist/protocol/records.js +149 -0
- package/dist/protocol/sasl/plain.d.ts +3 -0
- package/dist/protocol/sasl/plain.js +3 -0
- package/dist/protocol/sasl/scram-sha.d.ts +28 -0
- package/dist/protocol/sasl/scram-sha.js +104 -0
- package/dist/protocol/varint.d.ts +12 -0
- package/dist/protocol/varint.js +36 -0
- package/dist/protocol/writer.d.ts +48 -0
- package/dist/protocol/writer.js +223 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +127 -0
- package/package.json +75 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export class TopicsMap extends Map {
|
|
2
|
+
#current = [];
|
|
3
|
+
get current() {
|
|
4
|
+
return this.#current;
|
|
5
|
+
}
|
|
6
|
+
track(topic) {
|
|
7
|
+
let updated = false;
|
|
8
|
+
let existing = this.get(topic);
|
|
9
|
+
if (typeof existing === 'undefined') {
|
|
10
|
+
existing = 0;
|
|
11
|
+
updated = true;
|
|
12
|
+
}
|
|
13
|
+
this.set(topic, existing + 1);
|
|
14
|
+
if (updated) {
|
|
15
|
+
this.#updateCurrentList();
|
|
16
|
+
}
|
|
17
|
+
return updated;
|
|
18
|
+
}
|
|
19
|
+
trackAll(...topics) {
|
|
20
|
+
const updated = [];
|
|
21
|
+
for (const topic of topics.flat()) {
|
|
22
|
+
updated.push(this.track(topic));
|
|
23
|
+
}
|
|
24
|
+
return updated;
|
|
25
|
+
}
|
|
26
|
+
untrack(topic) {
|
|
27
|
+
const existing = this.get(topic);
|
|
28
|
+
if (existing === 1) {
|
|
29
|
+
this.delete(topic);
|
|
30
|
+
this.#updateCurrentList();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
else if (typeof existing === 'number') {
|
|
34
|
+
this.set(topic, existing - 1);
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
untrackAll(...topics) {
|
|
39
|
+
const updated = [];
|
|
40
|
+
for (const topic of topics.flat()) {
|
|
41
|
+
updated.push(this.untrack(topic));
|
|
42
|
+
}
|
|
43
|
+
return updated;
|
|
44
|
+
}
|
|
45
|
+
#updateCurrentList() {
|
|
46
|
+
this.#current = Array.from(this.keys());
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type FetchRequestTopic } from '../../apis/consumer/fetch.ts';
|
|
2
|
+
import { type FetchIsolationLevel } from '../../apis/enumerations.ts';
|
|
3
|
+
import { type BaseOptions, type TopicWithPartitionAndOffset } from '../base/types.ts';
|
|
4
|
+
import { type Deserializers } from '../serde.ts';
|
|
5
|
+
export interface GroupProtocolSubscription {
|
|
6
|
+
name: string;
|
|
7
|
+
version: number;
|
|
8
|
+
metadata?: Buffer | string;
|
|
9
|
+
}
|
|
10
|
+
export interface GroupAssignment {
|
|
11
|
+
topic: string;
|
|
12
|
+
partitions: number[];
|
|
13
|
+
}
|
|
14
|
+
export interface ExtendedGroupProtocolSubscription extends Omit<GroupProtocolSubscription, 'name'> {
|
|
15
|
+
topics?: string[];
|
|
16
|
+
memberId: string;
|
|
17
|
+
}
|
|
18
|
+
export type Offsets = Map<string, bigint[]>;
|
|
19
|
+
export declare const MessagesStreamModes: {
|
|
20
|
+
readonly LATEST: "latest";
|
|
21
|
+
readonly EARLIEST: "earliest";
|
|
22
|
+
readonly COMMITTED: "committed";
|
|
23
|
+
readonly MANUAL: "manual";
|
|
24
|
+
};
|
|
25
|
+
export type MessagesStreamMode = keyof typeof MessagesStreamModes;
|
|
26
|
+
export declare const MessagesStreamFallbackModes: {
|
|
27
|
+
readonly LATEST: "latest";
|
|
28
|
+
readonly EARLIEST: "earliest";
|
|
29
|
+
readonly FAIL: "fail";
|
|
30
|
+
};
|
|
31
|
+
export type MessagesStreamFallbackMode = keyof typeof MessagesStreamFallbackModes;
|
|
32
|
+
export interface GroupOptions {
|
|
33
|
+
sessionTimeout?: number;
|
|
34
|
+
rebalanceTimeout?: number;
|
|
35
|
+
heartbeatInterval?: number;
|
|
36
|
+
protocols?: GroupProtocolSubscription[];
|
|
37
|
+
}
|
|
38
|
+
export interface ConsumeBaseOptions<Key, Value, HeaderKey, HeaderValue> {
|
|
39
|
+
autocommit?: boolean | number;
|
|
40
|
+
minBytes?: number;
|
|
41
|
+
maxBytes?: number;
|
|
42
|
+
maxWaitTime?: number;
|
|
43
|
+
isolationLevel?: FetchIsolationLevel;
|
|
44
|
+
deserializers?: Partial<Deserializers<Key, Value, HeaderKey, HeaderValue>>;
|
|
45
|
+
highWaterMark?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface StreamOptions {
|
|
48
|
+
topics: string[];
|
|
49
|
+
mode?: string;
|
|
50
|
+
fallbackMode?: string;
|
|
51
|
+
offsets?: TopicWithPartitionAndOffset[];
|
|
52
|
+
}
|
|
53
|
+
export type ConsumeOptions<Key, Value, HeaderKey, HeaderValue> = StreamOptions & ConsumeBaseOptions<Key, Value, HeaderKey, HeaderValue> & GroupOptions;
|
|
54
|
+
export type ConsumerOptions<Key, Value, HeaderKey, HeaderValue> = BaseOptions & {
|
|
55
|
+
groupId: string;
|
|
56
|
+
} & GroupOptions & ConsumeBaseOptions<Key, Value, HeaderKey, HeaderValue>;
|
|
57
|
+
export type FetchOptions<Key, Value, HeaderKey, HeaderValue> = Omit<ConsumeBaseOptions<Key, Value, HeaderKey, HeaderValue>, 'deserializers'> & GroupOptions & {
|
|
58
|
+
node: number;
|
|
59
|
+
topics: FetchRequestTopic[];
|
|
60
|
+
};
|
|
61
|
+
export interface CommitOptionsPartition extends TopicWithPartitionAndOffset {
|
|
62
|
+
leaderEpoch: number;
|
|
63
|
+
}
|
|
64
|
+
export interface CommitOptions {
|
|
65
|
+
offsets: CommitOptionsPartition[];
|
|
66
|
+
}
|
|
67
|
+
export interface ListCommitsOptions {
|
|
68
|
+
topics: GroupAssignment[];
|
|
69
|
+
}
|
|
70
|
+
export interface ListOffsetsOptions {
|
|
71
|
+
topics: string[];
|
|
72
|
+
timestamp?: bigint;
|
|
73
|
+
isolationLevel?: FetchIsolationLevel;
|
|
74
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export declare const produceOptionsSchema: {
|
|
2
|
+
type: string;
|
|
3
|
+
properties: {
|
|
4
|
+
producerId: {
|
|
5
|
+
bigint: boolean;
|
|
6
|
+
};
|
|
7
|
+
producerEpoch: {
|
|
8
|
+
type: string;
|
|
9
|
+
};
|
|
10
|
+
idempotent: {
|
|
11
|
+
type: string;
|
|
12
|
+
};
|
|
13
|
+
acks: {
|
|
14
|
+
type: string;
|
|
15
|
+
enum: (0 | 1 | -1)[];
|
|
16
|
+
errorMessage: string;
|
|
17
|
+
};
|
|
18
|
+
compression: {
|
|
19
|
+
type: string;
|
|
20
|
+
enum: string[];
|
|
21
|
+
errorMessage: string;
|
|
22
|
+
};
|
|
23
|
+
partitioner: {
|
|
24
|
+
function: boolean;
|
|
25
|
+
};
|
|
26
|
+
autocreateTopics: {
|
|
27
|
+
type: string;
|
|
28
|
+
};
|
|
29
|
+
repeatOnStaleMetadata: {
|
|
30
|
+
type: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
additionalProperties: boolean;
|
|
34
|
+
};
|
|
35
|
+
export declare const produceOptionsValidator: import("ajv").ValidateFunction<unknown>;
|
|
36
|
+
export declare const producerOptionsValidator: import("ajv").ValidateFunction<unknown>;
|
|
37
|
+
export declare const sendOptionsSchema: {
|
|
38
|
+
type: string;
|
|
39
|
+
properties: {
|
|
40
|
+
producerId: {
|
|
41
|
+
bigint: boolean;
|
|
42
|
+
};
|
|
43
|
+
producerEpoch: {
|
|
44
|
+
type: string;
|
|
45
|
+
};
|
|
46
|
+
idempotent: {
|
|
47
|
+
type: string;
|
|
48
|
+
};
|
|
49
|
+
acks: {
|
|
50
|
+
type: string;
|
|
51
|
+
enum: (0 | 1 | -1)[];
|
|
52
|
+
errorMessage: string;
|
|
53
|
+
};
|
|
54
|
+
compression: {
|
|
55
|
+
type: string;
|
|
56
|
+
enum: string[];
|
|
57
|
+
errorMessage: string;
|
|
58
|
+
};
|
|
59
|
+
partitioner: {
|
|
60
|
+
function: boolean;
|
|
61
|
+
};
|
|
62
|
+
autocreateTopics: {
|
|
63
|
+
type: string;
|
|
64
|
+
};
|
|
65
|
+
repeatOnStaleMetadata: {
|
|
66
|
+
type: string;
|
|
67
|
+
};
|
|
68
|
+
messages: {
|
|
69
|
+
type: string;
|
|
70
|
+
items: {
|
|
71
|
+
type: string;
|
|
72
|
+
properties: {
|
|
73
|
+
key: {
|
|
74
|
+
oneOf: ({
|
|
75
|
+
type: string;
|
|
76
|
+
buffer?: undefined;
|
|
77
|
+
} | {
|
|
78
|
+
buffer: boolean;
|
|
79
|
+
type?: undefined;
|
|
80
|
+
})[];
|
|
81
|
+
};
|
|
82
|
+
value: {
|
|
83
|
+
oneOf: ({
|
|
84
|
+
type: string;
|
|
85
|
+
buffer?: undefined;
|
|
86
|
+
} | {
|
|
87
|
+
buffer: boolean;
|
|
88
|
+
type?: undefined;
|
|
89
|
+
})[];
|
|
90
|
+
};
|
|
91
|
+
headers: {
|
|
92
|
+
anyOf: ({
|
|
93
|
+
map: boolean;
|
|
94
|
+
type?: undefined;
|
|
95
|
+
additionalProperties?: undefined;
|
|
96
|
+
} | {
|
|
97
|
+
type: string;
|
|
98
|
+
additionalProperties: boolean;
|
|
99
|
+
map?: undefined;
|
|
100
|
+
})[];
|
|
101
|
+
};
|
|
102
|
+
topic: {
|
|
103
|
+
type: string;
|
|
104
|
+
};
|
|
105
|
+
partition: {
|
|
106
|
+
type: string;
|
|
107
|
+
};
|
|
108
|
+
timestamp: {
|
|
109
|
+
bigint: boolean;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
required: string[];
|
|
113
|
+
additionalProperties: boolean;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
required: string[];
|
|
118
|
+
additionalProperties: boolean;
|
|
119
|
+
};
|
|
120
|
+
export declare const sendOptionsValidator: import("ajv").ValidateFunction<{
|
|
121
|
+
[x: string]: {};
|
|
122
|
+
}>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ProduceAcks } from "../../apis/enumerations.js";
|
|
2
|
+
import { compressionsAlgorithms } from "../../protocol/compression.js";
|
|
3
|
+
import { messageSchema } from "../../protocol/records.js";
|
|
4
|
+
import { ajv, enumErrorMessage } from "../../utils.js";
|
|
5
|
+
import { serdeProperties } from "../serde.js";
|
|
6
|
+
const produceOptionsProperties = {
|
|
7
|
+
producerId: { bigint: true },
|
|
8
|
+
producerEpoch: { type: 'number' },
|
|
9
|
+
idempotent: { type: 'boolean' },
|
|
10
|
+
acks: {
|
|
11
|
+
type: 'number',
|
|
12
|
+
enum: Object.values(ProduceAcks),
|
|
13
|
+
errorMessage: enumErrorMessage(ProduceAcks)
|
|
14
|
+
},
|
|
15
|
+
compression: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
enum: Object.keys(compressionsAlgorithms),
|
|
18
|
+
errorMessage: enumErrorMessage(compressionsAlgorithms, true)
|
|
19
|
+
},
|
|
20
|
+
partitioner: { function: true },
|
|
21
|
+
autocreateTopics: { type: 'boolean' },
|
|
22
|
+
repeatOnStaleMetadata: { type: 'boolean' }
|
|
23
|
+
};
|
|
24
|
+
export const produceOptionsSchema = {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: produceOptionsProperties,
|
|
27
|
+
additionalProperties: false
|
|
28
|
+
};
|
|
29
|
+
export const produceOptionsValidator = ajv.compile(produceOptionsSchema);
|
|
30
|
+
export const producerOptionsValidator = ajv.compile({
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
...produceOptionsProperties,
|
|
34
|
+
serializers: serdeProperties
|
|
35
|
+
},
|
|
36
|
+
additionalProperties: true
|
|
37
|
+
});
|
|
38
|
+
export const sendOptionsSchema = {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
messages: { type: 'array', items: messageSchema },
|
|
42
|
+
...produceOptionsProperties
|
|
43
|
+
},
|
|
44
|
+
required: ['messages'],
|
|
45
|
+
additionalProperties: false
|
|
46
|
+
};
|
|
47
|
+
export const sendOptionsValidator = ajv.compile(sendOptionsSchema);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Base } from '../base/base.ts';
|
|
2
|
+
import { type CallbackWithPromise } from '../callbacks.ts';
|
|
3
|
+
import { type ProduceOptions, type ProduceResult, type ProducerInfo, type ProducerOptions, type SendOptions } from './types.ts';
|
|
4
|
+
export declare class Producer<Key = Buffer, Value = Buffer, HeaderKey = Buffer, HeaderValue = Buffer> extends Base<ProducerOptions<Key, Value, HeaderKey, HeaderValue>> {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(options: ProducerOptions<Key, Value, HeaderKey, HeaderValue>);
|
|
7
|
+
get producerId(): bigint | undefined;
|
|
8
|
+
get producerEpoch(): number | undefined;
|
|
9
|
+
initIdempotentProducer(options: ProduceOptions<Key, Value, HeaderKey, HeaderValue>, callback: CallbackWithPromise<ProducerInfo>): void;
|
|
10
|
+
initIdempotentProducer(options: ProduceOptions<Key, Value, HeaderKey, HeaderValue>): Promise<ProducerInfo>;
|
|
11
|
+
send(options: SendOptions<Key, Value, HeaderKey, HeaderValue>, callback: CallbackWithPromise<ProduceResult>): void;
|
|
12
|
+
send(options: SendOptions<Key, Value, HeaderKey, HeaderValue>): Promise<ProduceResult>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { ProduceAcks } from "../../apis/enumerations.js";
|
|
2
|
+
import { api as initProducerIdV5 } from "../../apis/producer/init-producer-id.js";
|
|
3
|
+
import { api as produceV11 } from "../../apis/producer/produce.js";
|
|
4
|
+
import { UserError } from "../../errors.js";
|
|
5
|
+
import { murmur2 } from "../../protocol/murmur2.js";
|
|
6
|
+
import { NumericMap } from "../../utils.js";
|
|
7
|
+
import { Base, kBootstrapBrokers, kCheckNotClosed, kClearMetadata, kConnections, kMetadata, kOptions, kPerformDeduplicated, kPerformWithRetry, kValidateOptions } from "../base/base.js";
|
|
8
|
+
import { createPromisifiedCallback, kCallbackPromise, runConcurrentCallbacks } from "../callbacks.js";
|
|
9
|
+
import { produceOptionsValidator, producerOptionsValidator, sendOptionsValidator } from "./options.js";
|
|
10
|
+
// Don't move this function as being in the same file will enable V8 to remove.
|
|
11
|
+
// For futher info, ask Matteo.
|
|
12
|
+
function noopSerializer(data) {
|
|
13
|
+
return data;
|
|
14
|
+
}
|
|
15
|
+
export class Producer extends Base {
|
|
16
|
+
#partitionsRoundRobin;
|
|
17
|
+
// These two values should be serializable and loadable in the constructor in order to restore
|
|
18
|
+
// the idempotent producer status.
|
|
19
|
+
#producerInfo;
|
|
20
|
+
#sequences;
|
|
21
|
+
#keySerializer;
|
|
22
|
+
#valueSerializer;
|
|
23
|
+
#headerKeySerializer;
|
|
24
|
+
#headerValueSerializer;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
if (options.idempotent) {
|
|
27
|
+
options.maxInflights = 1;
|
|
28
|
+
options.acks = ProduceAcks.ALL;
|
|
29
|
+
options.retries = Number.MAX_SAFE_INTEGER;
|
|
30
|
+
}
|
|
31
|
+
options.repeatOnStaleMetadata ??= true;
|
|
32
|
+
super(options);
|
|
33
|
+
this.#partitionsRoundRobin = new NumericMap();
|
|
34
|
+
this.#sequences = new NumericMap();
|
|
35
|
+
this.#keySerializer = options.serializers?.key ?? noopSerializer;
|
|
36
|
+
this.#valueSerializer = options.serializers?.value ?? noopSerializer;
|
|
37
|
+
this.#headerKeySerializer = options.serializers?.headerKey ?? noopSerializer;
|
|
38
|
+
this.#headerValueSerializer = options.serializers?.headerValue ?? noopSerializer;
|
|
39
|
+
this[kValidateOptions](options, producerOptionsValidator, '/options');
|
|
40
|
+
}
|
|
41
|
+
get producerId() {
|
|
42
|
+
return this.#producerInfo?.producerId;
|
|
43
|
+
}
|
|
44
|
+
get producerEpoch() {
|
|
45
|
+
return this.#producerInfo?.producerEpoch;
|
|
46
|
+
}
|
|
47
|
+
initIdempotentProducer(options, callback) {
|
|
48
|
+
if (!callback) {
|
|
49
|
+
callback = createPromisifiedCallback();
|
|
50
|
+
}
|
|
51
|
+
if (this[kCheckNotClosed](callback)) {
|
|
52
|
+
return callback[kCallbackPromise];
|
|
53
|
+
}
|
|
54
|
+
const validationError = this[kValidateOptions](options, produceOptionsValidator, '/options', false);
|
|
55
|
+
if (validationError) {
|
|
56
|
+
callback(validationError, undefined);
|
|
57
|
+
return callback[kCallbackPromise];
|
|
58
|
+
}
|
|
59
|
+
return this[kPerformDeduplicated]('initProducerId', deduplicateCallback => {
|
|
60
|
+
this[kPerformWithRetry]('initProducerId', retryCallback => {
|
|
61
|
+
this[kConnections].getFirstAvailable(this[kBootstrapBrokers], (error, connection) => {
|
|
62
|
+
if (error) {
|
|
63
|
+
callback(error, undefined);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
initProducerIdV5(connection, null, this[kOptions].timeout, options.producerId ?? this[kOptions].producerId ?? 0n, options.producerEpoch ?? this[kOptions].producerEpoch ?? 0, retryCallback);
|
|
67
|
+
});
|
|
68
|
+
}, (error, response) => {
|
|
69
|
+
if (error) {
|
|
70
|
+
callback(error, undefined);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this.#producerInfo = { producerId: response.producerId, producerEpoch: response.producerEpoch };
|
|
74
|
+
deduplicateCallback(null, this.#producerInfo);
|
|
75
|
+
}, 0);
|
|
76
|
+
}, callback);
|
|
77
|
+
}
|
|
78
|
+
send(options, callback) {
|
|
79
|
+
if (!callback) {
|
|
80
|
+
callback = createPromisifiedCallback();
|
|
81
|
+
}
|
|
82
|
+
if (this[kCheckNotClosed](callback)) {
|
|
83
|
+
return callback[kCallbackPromise];
|
|
84
|
+
}
|
|
85
|
+
const validationError = this[kValidateOptions](options, sendOptionsValidator, '/options', false);
|
|
86
|
+
if (validationError) {
|
|
87
|
+
callback(validationError, undefined);
|
|
88
|
+
return callback[kCallbackPromise];
|
|
89
|
+
}
|
|
90
|
+
options.idempotent ??= this[kOptions].idempotent ?? false;
|
|
91
|
+
/* c8 ignore next */
|
|
92
|
+
options.repeatOnStaleMetadata ??= this[kOptions].repeatOnStaleMetadata ?? true;
|
|
93
|
+
options.partitioner ??= this[kOptions].partitioner;
|
|
94
|
+
const { idempotent, partitioner } = options;
|
|
95
|
+
if (idempotent) {
|
|
96
|
+
options.acks ??= ProduceAcks.ALL;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
options.acks ??= ProduceAcks.LEADER;
|
|
100
|
+
}
|
|
101
|
+
// We still need to initialize the producerId
|
|
102
|
+
if (idempotent) {
|
|
103
|
+
if (!this.#producerInfo) {
|
|
104
|
+
const { messages, ...initOptions } = options;
|
|
105
|
+
this.initIdempotentProducer(initOptions, error => {
|
|
106
|
+
if (error) {
|
|
107
|
+
callback(error, undefined);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.send(options, callback);
|
|
111
|
+
});
|
|
112
|
+
return callback[kCallbackPromise];
|
|
113
|
+
}
|
|
114
|
+
if (typeof options.producerId !== 'undefined' || typeof options.producerEpoch !== 'undefined') {
|
|
115
|
+
callback(new UserError('Cannot specify producerId or producerEpoch when using idempotent producer.'), undefined);
|
|
116
|
+
return callback[kCallbackPromise];
|
|
117
|
+
}
|
|
118
|
+
if (options.acks !== ProduceAcks.ALL) {
|
|
119
|
+
callback(new UserError('Idempotent producer requires acks to be ALL (-1).'), undefined);
|
|
120
|
+
return callback[kCallbackPromise];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const produceOptions = {
|
|
124
|
+
compression: options.compression ?? this[kOptions].compression,
|
|
125
|
+
producerId: idempotent ? this.#producerInfo.producerId : options.producerId,
|
|
126
|
+
producerEpoch: idempotent ? this.#producerInfo.producerEpoch : options.producerEpoch,
|
|
127
|
+
sequences: idempotent ? this.#sequences : undefined
|
|
128
|
+
};
|
|
129
|
+
// Build messages records out of messages
|
|
130
|
+
const topics = new Set();
|
|
131
|
+
const messages = [];
|
|
132
|
+
for (const message of options.messages) {
|
|
133
|
+
const topic = message.topic;
|
|
134
|
+
const key = this.#keySerializer(message.key);
|
|
135
|
+
const headers = new Map();
|
|
136
|
+
let partition = 0;
|
|
137
|
+
if (typeof message.partition !== 'number') {
|
|
138
|
+
if (partitioner) {
|
|
139
|
+
partition = partitioner(message);
|
|
140
|
+
}
|
|
141
|
+
else if (key) {
|
|
142
|
+
partition = murmur2(key) >>> 0;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Use the roundrobin
|
|
146
|
+
partition = this.#partitionsRoundRobin.postIncrement(topic, 1, -1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
partition = message.partition;
|
|
151
|
+
}
|
|
152
|
+
if (message.headers) {
|
|
153
|
+
const entries = message.headers instanceof Map ? message.headers : Object.entries(message.headers);
|
|
154
|
+
for (const [key, value] of entries) {
|
|
155
|
+
headers.set(this.#headerKeySerializer(key), this.#headerValueSerializer(value));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
topics.add(topic);
|
|
159
|
+
messages.push({
|
|
160
|
+
key,
|
|
161
|
+
value: this.#valueSerializer(message.value),
|
|
162
|
+
headers,
|
|
163
|
+
topic,
|
|
164
|
+
partition,
|
|
165
|
+
timestamp: message.timestamp
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
this.#performSend(Array.from(topics), messages, options, produceOptions, callback);
|
|
169
|
+
return callback[kCallbackPromise];
|
|
170
|
+
}
|
|
171
|
+
#performSend(topics, messages, sendOptions, produceOptions, callback) {
|
|
172
|
+
// Get the metadata with the topic/partitions informations
|
|
173
|
+
this[kMetadata]({ topics, autocreateTopics: sendOptions.autocreateTopics }, (error, metadata) => {
|
|
174
|
+
if (error) {
|
|
175
|
+
callback(error, undefined);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const messagesByDestination = new Map();
|
|
179
|
+
// Track the number of messages per partition so we can update the sequence number
|
|
180
|
+
const messagesPerPartition = new NumericMap();
|
|
181
|
+
// Normalize the partition of all messages, then enqueue them to their destination
|
|
182
|
+
for (const message of messages) {
|
|
183
|
+
message.partition %= metadata.topics.get(message.topic).partitionsCount;
|
|
184
|
+
const { topic, partition } = message;
|
|
185
|
+
const leader = metadata.topics.get(topic).partitions[partition].leader;
|
|
186
|
+
let destination = messagesByDestination.get(leader);
|
|
187
|
+
if (!destination) {
|
|
188
|
+
destination = [];
|
|
189
|
+
messagesByDestination.set(leader, destination);
|
|
190
|
+
}
|
|
191
|
+
const messagePartitionKey = `${message.topic}:${partition}`;
|
|
192
|
+
messagesPerPartition.postIncrement(messagePartitionKey, 1, 0);
|
|
193
|
+
destination.push(message);
|
|
194
|
+
}
|
|
195
|
+
// Track nodes so that we can get their ID for delayed write reporting
|
|
196
|
+
const nodes = [];
|
|
197
|
+
runConcurrentCallbacks('Producing messages failed.', messagesByDestination, ([destination, messages], concurrentCallback) => {
|
|
198
|
+
nodes.push(destination);
|
|
199
|
+
this.#performSingleDestinationSend(topics, messages, this[kOptions].timeout, sendOptions.acks, sendOptions.autocreateTopics, sendOptions.repeatOnStaleMetadata, produceOptions, concurrentCallback);
|
|
200
|
+
}, (error, apiResults) => {
|
|
201
|
+
if (error) {
|
|
202
|
+
callback(error, undefined);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const results = {};
|
|
206
|
+
if (sendOptions.acks === ProduceAcks.NO_RESPONSE) {
|
|
207
|
+
const unwritableNodes = [];
|
|
208
|
+
for (let i = 0; i < apiResults.length; i++) {
|
|
209
|
+
if (apiResults[i] === false) {
|
|
210
|
+
unwritableNodes.push(nodes[i]);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
results.unwritableNodes = unwritableNodes;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
const topics = [];
|
|
217
|
+
for (const result of apiResults) {
|
|
218
|
+
for (const { name, partitionResponses } of result.responses) {
|
|
219
|
+
for (const partitionResponse of partitionResponses) {
|
|
220
|
+
topics.push({
|
|
221
|
+
topic: name,
|
|
222
|
+
partition: partitionResponse.index,
|
|
223
|
+
offset: partitionResponse.baseOffset
|
|
224
|
+
});
|
|
225
|
+
const partitionKey = `${name}:${partitionResponse.index}`;
|
|
226
|
+
this.#sequences.postIncrement(partitionKey, messagesPerPartition.get(partitionKey), 0);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
results.offsets = topics;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
callback(null, results);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
#performSingleDestinationSend(topics, messages, timeout, acks, autocreateTopics, repeatOnStaleMetadata, produceOptions, callback) {
|
|
237
|
+
// Get the metadata with the topic/partitions informations
|
|
238
|
+
this[kMetadata]({ topics, autocreateTopics }, (error, metadata) => {
|
|
239
|
+
if (error) {
|
|
240
|
+
callback(error, undefined);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const { topic, partition } = messages[0];
|
|
244
|
+
const leader = metadata.topics.get(topic).partitions[partition].leader;
|
|
245
|
+
this[kPerformWithRetry]('produce', retryCallback => {
|
|
246
|
+
this[kConnections].get(metadata.brokers.get(leader), (error, connection) => {
|
|
247
|
+
if (error) {
|
|
248
|
+
retryCallback(error, undefined);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
produceV11(connection, acks, timeout, messages, produceOptions, retryCallback);
|
|
252
|
+
});
|
|
253
|
+
}, (error, results) => {
|
|
254
|
+
if (error) {
|
|
255
|
+
// If the last error was due to stale metadata, we retry the operation with this set of messages
|
|
256
|
+
// since the partition is already set, it should attempt on the new destination
|
|
257
|
+
const hasStaleMetadata = error.findBy('hasStaleMetadata', true);
|
|
258
|
+
if (hasStaleMetadata && repeatOnStaleMetadata) {
|
|
259
|
+
this[kClearMetadata]();
|
|
260
|
+
this.#performSingleDestinationSend(topics, messages, timeout, acks, autocreateTopics, false, produceOptions, callback);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
callback(error, undefined);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
callback(error, results);
|
|
267
|
+
}, 0, [], (error) => {
|
|
268
|
+
return repeatOnStaleMetadata && !!error.findBy('hasStaleMetadata', true);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type CompressionAlgorithms } from '../../protocol/compression.ts';
|
|
2
|
+
import { type MessageToProduce } from '../../protocol/records.ts';
|
|
3
|
+
import { type BaseOptions, type TopicWithPartitionAndOffset } from '../base/types.ts';
|
|
4
|
+
import { type Serializers } from '../serde.ts';
|
|
5
|
+
export interface ProducerInfo {
|
|
6
|
+
producerId: bigint;
|
|
7
|
+
producerEpoch: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ProduceResult {
|
|
10
|
+
offsets?: TopicWithPartitionAndOffset[];
|
|
11
|
+
unwritableNodes?: number[];
|
|
12
|
+
}
|
|
13
|
+
export type Partitioner<Key, Value, HeaderKey, HeaderValue> = (message: MessageToProduce<Key, Value, HeaderKey, HeaderValue>) => number;
|
|
14
|
+
export interface ProduceOptions<Key, Value, HeaderKey, HeaderValue> {
|
|
15
|
+
producerId?: bigint;
|
|
16
|
+
producerEpoch?: number;
|
|
17
|
+
idempotent?: boolean;
|
|
18
|
+
acks?: number;
|
|
19
|
+
compression?: CompressionAlgorithms;
|
|
20
|
+
partitioner?: Partitioner<Key, Value, HeaderKey, HeaderValue>;
|
|
21
|
+
autocreateTopics?: boolean;
|
|
22
|
+
repeatOnStaleMetadata?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export type ProducerOptions<Key, Value, HeaderKey, HeaderValue> = BaseOptions & ProduceOptions<Key, Value, HeaderKey, HeaderValue> & {
|
|
25
|
+
serializers?: Partial<Serializers<Key, Value, HeaderKey, HeaderValue>>;
|
|
26
|
+
};
|
|
27
|
+
export type SendOptions<Key, Value, HeaderKey, HeaderValue> = {
|
|
28
|
+
messages: MessageToProduce<Key, Value, HeaderKey, HeaderValue>[];
|
|
29
|
+
} & ProduceOptions<Key, Value, HeaderKey, HeaderValue>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|