kafka-ts 1.1.8 → 1.2.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 +1 -1
- package/dist/consumer/consumer-group.js +84 -99
- package/dist/consumer/consumer.js +23 -32
- package/dist/consumer/offset-manager.js +6 -5
- package/dist/distributors/group-by-leader-id.d.ts +10 -0
- package/dist/distributors/group-by-leader-id.js +13 -0
- package/dist/distributors/group-partitions-by-topic.d.ts +6 -0
- package/dist/distributors/group-partitions-by-topic.js +12 -0
- package/dist/metadata.d.ts +1 -1
- package/dist/metadata.js +1 -1
- package/dist/producer/producer-buffer.d.ts +20 -0
- package/dist/producer/producer-buffer.js +118 -0
- package/dist/producer/producer-state.d.ts +15 -0
- package/dist/producer/producer-state.js +33 -0
- package/dist/producer/producer.d.ts +6 -11
- package/dist/producer/producer.js +32 -108
- package/dist/utils/decoder.js +13 -8
- package/dist/utils/encoder.d.ts +10 -8
- package/dist/utils/encoder.js +95 -58
- package/dist/utils/promise-chain.d.ts +5 -0
- package/dist/utils/promise-chain.js +39 -0
- package/dist/utils/retry.d.ts +1 -0
- package/dist/utils/retry.js +19 -0
- package/dist/utils/shared.d.ts +1 -1
- package/dist/utils/shared.js +8 -7
- package/package.json +1 -1
- package/dist/consumer/metadata.d.ts +0 -24
- package/dist/consumer/metadata.js +0 -64
- package/dist/distributors/messages-to-topic-partition-leaders.d.ts +0 -17
- package/dist/distributors/messages-to-topic-partition-leaders.js +0 -15
- package/dist/distributors/messages-to-topic-partition-leaders.test.d.ts +0 -1
- package/dist/distributors/messages-to-topic-partition-leaders.test.js +0 -30
- package/dist/examples/src/replicator.js +0 -34
- package/dist/examples/src/utils/json.js +0 -5
- package/dist/request-handler.d.ts +0 -16
- package/dist/request-handler.js +0 -67
- package/dist/request-handler.test.d.ts +0 -1
- package/dist/request-handler.test.js +0 -340
- package/dist/src/api/api-versions.js +0 -18
- package/dist/src/api/create-topics.js +0 -46
- package/dist/src/api/delete-topics.js +0 -26
- package/dist/src/api/fetch.js +0 -95
- package/dist/src/api/find-coordinator.js +0 -34
- package/dist/src/api/heartbeat.js +0 -22
- package/dist/src/api/index.js +0 -38
- package/dist/src/api/init-producer-id.js +0 -24
- package/dist/src/api/join-group.js +0 -48
- package/dist/src/api/leave-group.js +0 -30
- package/dist/src/api/list-offsets.js +0 -39
- package/dist/src/api/metadata.js +0 -47
- package/dist/src/api/offset-commit.js +0 -39
- package/dist/src/api/offset-fetch.js +0 -44
- package/dist/src/api/produce.js +0 -119
- package/dist/src/api/sync-group.js +0 -31
- package/dist/src/broker.js +0 -35
- package/dist/src/connection.js +0 -21
- package/dist/src/consumer/consumer-group.js +0 -131
- package/dist/src/consumer/consumer.js +0 -103
- package/dist/src/consumer/metadata.js +0 -52
- package/dist/src/consumer/offset-manager.js +0 -23
- package/dist/src/index.js +0 -19
- package/dist/src/producer/producer.js +0 -84
- package/dist/src/request-handler.js +0 -57
- package/dist/src/request-handler.test.js +0 -321
- package/dist/src/types.js +0 -2
- package/dist/src/utils/api.js +0 -5
- package/dist/src/utils/decoder.js +0 -161
- package/dist/src/utils/encoder.js +0 -137
- package/dist/src/utils/error.js +0 -10
- package/dist/utils/debug.d.ts +0 -2
- package/dist/utils/debug.js +0 -11
- package/dist/utils/lock.d.ts +0 -8
- package/dist/utils/lock.js +0 -44
- package/dist/utils/memo.d.ts +0 -1
- package/dist/utils/memo.js +0 -16
- package/dist/utils/mutex.d.ts +0 -3
- package/dist/utils/mutex.js +0 -32
|
@@ -4,25 +4,20 @@ import { Message } from '../types';
|
|
|
4
4
|
export type ProducerOptions = {
|
|
5
5
|
allowTopicAutoCreation?: boolean;
|
|
6
6
|
partitioner?: Partitioner;
|
|
7
|
+
maxBatchSize?: number;
|
|
7
8
|
};
|
|
8
9
|
export declare class Producer {
|
|
9
10
|
private cluster;
|
|
10
11
|
private options;
|
|
11
12
|
private metadata;
|
|
12
|
-
private
|
|
13
|
-
private producerEpoch;
|
|
14
|
-
private sequences;
|
|
13
|
+
private state;
|
|
15
14
|
private partition;
|
|
16
|
-
private
|
|
15
|
+
private chain;
|
|
16
|
+
private bufferByNodeId;
|
|
17
17
|
constructor(cluster: Cluster, options: ProducerOptions);
|
|
18
|
-
send(messages: Message[]
|
|
19
|
-
acks?: -1 | 1;
|
|
20
|
-
}): Promise<void>;
|
|
18
|
+
send(messages: Message[]): Promise<void>;
|
|
21
19
|
close(): Promise<void>;
|
|
22
20
|
private ensureProducerInitialized;
|
|
23
|
-
private
|
|
24
|
-
private getSequence;
|
|
25
|
-
private updateSequence;
|
|
26
|
-
private fetchMetadata;
|
|
21
|
+
private fetchMetadataForTopics;
|
|
27
22
|
private handleError;
|
|
28
23
|
}
|
|
@@ -11,106 +11,60 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.Producer = void 0;
|
|
13
13
|
const api_1 = require("../api");
|
|
14
|
-
const
|
|
14
|
+
const group_by_leader_id_1 = require("../distributors/group-by-leader-id");
|
|
15
15
|
const partitioner_1 = require("../distributors/partitioner");
|
|
16
16
|
const metadata_1 = require("../metadata");
|
|
17
17
|
const error_1 = require("../utils/error");
|
|
18
|
-
const lock_1 = require("../utils/lock");
|
|
19
18
|
const logger_1 = require("../utils/logger");
|
|
19
|
+
const promise_chain_1 = require("../utils/promise-chain");
|
|
20
20
|
const shared_1 = require("../utils/shared");
|
|
21
21
|
const tracer_1 = require("../utils/tracer");
|
|
22
|
+
const producer_buffer_1 = require("./producer-buffer");
|
|
23
|
+
const producer_state_1 = require("./producer-state");
|
|
22
24
|
const trace = (0, tracer_1.createTracer)('Producer');
|
|
23
25
|
class Producer {
|
|
24
26
|
cluster;
|
|
25
27
|
options;
|
|
26
28
|
metadata;
|
|
27
|
-
|
|
28
|
-
producerEpoch = 0;
|
|
29
|
-
sequences = {};
|
|
29
|
+
state;
|
|
30
30
|
partition;
|
|
31
|
-
|
|
31
|
+
chain = new promise_chain_1.PromiseChain();
|
|
32
|
+
bufferByNodeId = {};
|
|
32
33
|
constructor(cluster, options) {
|
|
33
34
|
this.cluster = cluster;
|
|
34
35
|
this.options = {
|
|
35
36
|
...options,
|
|
36
37
|
allowTopicAutoCreation: options.allowTopicAutoCreation ?? false,
|
|
37
38
|
partitioner: options.partitioner ?? partitioner_1.defaultPartitioner,
|
|
39
|
+
maxBatchSize: options.maxBatchSize ?? 500,
|
|
38
40
|
};
|
|
39
41
|
this.metadata = new metadata_1.Metadata({ cluster });
|
|
42
|
+
this.state = new producer_state_1.ProducerState({ cluster });
|
|
40
43
|
this.partition = this.options.partitioner({ metadata: this.metadata });
|
|
41
44
|
}
|
|
42
|
-
async send(messages
|
|
45
|
+
async send(messages) {
|
|
43
46
|
await this.ensureProducerInitialized();
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
const topics = new Set(messages.map((message) => message.topic));
|
|
47
|
-
await this.lock.acquire([...topics].map((topic) => `metadata:${topic}`), () => this.metadata.fetchMetadataIfNecessary({ topics, allowTopicAutoCreation }));
|
|
47
|
+
const topics = [...new Set(messages.map((message) => message.topic))];
|
|
48
|
+
await this.fetchMetadataForTopics(topics);
|
|
48
49
|
const partitionedMessages = messages.map((message) => {
|
|
49
50
|
message.partition = this.partition(message);
|
|
50
51
|
return message;
|
|
51
52
|
});
|
|
52
|
-
const
|
|
53
|
-
await Promise.all(Object.entries(
|
|
53
|
+
const messagesByLeaderId = (0, group_by_leader_id_1.groupByLeaderId)(partitionedMessages, this.metadata.getTopicPartitionLeaderIds());
|
|
54
|
+
await Promise.all(Object.entries(messagesByLeaderId).map(async ([leaderId, messages]) => {
|
|
55
|
+
const nodeId = parseInt(leaderId);
|
|
56
|
+
const buffer = (this.bufferByNodeId[nodeId] ??= new producer_buffer_1.ProducerBuffer({
|
|
57
|
+
nodeId,
|
|
58
|
+
maxBatchSize: this.options.maxBatchSize,
|
|
59
|
+
cluster: this.cluster,
|
|
60
|
+
state: this.state,
|
|
61
|
+
}));
|
|
54
62
|
try {
|
|
55
|
-
await
|
|
56
|
-
const topicData = Object.entries(topicPartitionMessages).map(([topic, partitionMessages]) => ({
|
|
57
|
-
name: topic,
|
|
58
|
-
partitionData: Object.entries(partitionMessages).map(([partition, messages]) => {
|
|
59
|
-
const partitionIndex = parseInt(partition);
|
|
60
|
-
let baseTimestamp;
|
|
61
|
-
let maxTimestamp;
|
|
62
|
-
messages.forEach(({ timestamp = defaultTimestamp }) => {
|
|
63
|
-
if (!baseTimestamp || timestamp < baseTimestamp) {
|
|
64
|
-
baseTimestamp = timestamp;
|
|
65
|
-
}
|
|
66
|
-
if (!maxTimestamp || timestamp > maxTimestamp) {
|
|
67
|
-
maxTimestamp = timestamp;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
return {
|
|
71
|
-
index: partitionIndex,
|
|
72
|
-
baseOffset: 0n,
|
|
73
|
-
partitionLeaderEpoch: -1,
|
|
74
|
-
attributes: 0,
|
|
75
|
-
lastOffsetDelta: messages.length - 1,
|
|
76
|
-
baseTimestamp: baseTimestamp ?? 0n,
|
|
77
|
-
maxTimestamp: maxTimestamp ?? 0n,
|
|
78
|
-
producerId: this.producerId,
|
|
79
|
-
producerEpoch: 0,
|
|
80
|
-
baseSequence: this.getSequence(topic, partitionIndex),
|
|
81
|
-
records: messages.map((message, index) => ({
|
|
82
|
-
attributes: 0,
|
|
83
|
-
timestampDelta: (message.timestamp ?? defaultTimestamp) - (baseTimestamp ?? 0n),
|
|
84
|
-
offsetDelta: index,
|
|
85
|
-
key: message.key ?? null,
|
|
86
|
-
value: message.value,
|
|
87
|
-
headers: Object.entries(message.headers ?? {}).map(([key, value]) => ({
|
|
88
|
-
key,
|
|
89
|
-
value,
|
|
90
|
-
})),
|
|
91
|
-
})),
|
|
92
|
-
};
|
|
93
|
-
}),
|
|
94
|
-
}));
|
|
95
|
-
await this.cluster.sendRequestToNode(parseInt(nodeId))(api_1.API.PRODUCE, {
|
|
96
|
-
transactionalId: null,
|
|
97
|
-
acks,
|
|
98
|
-
timeoutMs: 30000,
|
|
99
|
-
topicData,
|
|
100
|
-
});
|
|
101
|
-
topicData.forEach(({ name, partitionData }) => {
|
|
102
|
-
partitionData.forEach(({ index, records }) => {
|
|
103
|
-
this.updateSequence(name, index, records.length);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
});
|
|
63
|
+
await buffer.enqueue(messages);
|
|
107
64
|
}
|
|
108
65
|
catch (error) {
|
|
109
66
|
await this.handleError(error);
|
|
110
|
-
|
|
111
|
-
.flatMap((partitionMessages) => Object.values(partitionMessages).flat())
|
|
112
|
-
.map(({ partition, ...message }) => message);
|
|
113
|
-
return this.send(messages, { acks });
|
|
67
|
+
return this.send(messages);
|
|
114
68
|
}
|
|
115
69
|
}));
|
|
116
70
|
}
|
|
@@ -119,55 +73,25 @@ class Producer {
|
|
|
119
73
|
}
|
|
120
74
|
ensureProducerInitialized = (0, shared_1.shared)(async () => {
|
|
121
75
|
await this.cluster.ensureConnected();
|
|
122
|
-
if (!this.producerId) {
|
|
123
|
-
await this.initProducerId();
|
|
76
|
+
if (!this.state.producerId) {
|
|
77
|
+
await this.state.initProducerId();
|
|
124
78
|
}
|
|
125
79
|
});
|
|
126
|
-
async
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
transactionTimeoutMs: 0,
|
|
131
|
-
producerId: this.producerId,
|
|
132
|
-
producerEpoch: this.producerEpoch,
|
|
133
|
-
});
|
|
134
|
-
this.producerId = result.producerId;
|
|
135
|
-
this.producerEpoch = result.producerEpoch;
|
|
136
|
-
this.sequences = {};
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
await this.handleError(error);
|
|
140
|
-
return this.initProducerId();
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
getSequence(topic, partition) {
|
|
144
|
-
return this.sequences[topic]?.[partition] ?? 0;
|
|
145
|
-
}
|
|
146
|
-
updateSequence(topic, partition, messagesCount) {
|
|
147
|
-
this.sequences[topic] ??= {};
|
|
148
|
-
this.sequences[topic][partition] ??= 0;
|
|
149
|
-
this.sequences[topic][partition] += messagesCount;
|
|
150
|
-
}
|
|
151
|
-
async fetchMetadata(topics, allowTopicAutoCreation) {
|
|
152
|
-
try {
|
|
153
|
-
await this.metadata.fetchMetadata({ topics, allowTopicAutoCreation });
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
await this.handleError(error);
|
|
157
|
-
return this.fetchMetadata(topics, allowTopicAutoCreation);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
80
|
+
fetchMetadataForTopics = (0, shared_1.shared)(async (topics) => {
|
|
81
|
+
const { allowTopicAutoCreation } = this.options;
|
|
82
|
+
await this.chain.run(topics.map((topic) => `metadata:${topic}`), () => this.metadata.fetchMetadataIfNecessary({ topics, allowTopicAutoCreation }));
|
|
83
|
+
});
|
|
160
84
|
async handleError(error) {
|
|
161
85
|
await (0, api_1.handleApiError)(error).catch(async (error) => {
|
|
162
86
|
if (error instanceof error_1.KafkaTSApiError && error.errorCode === api_1.API_ERROR.NOT_LEADER_OR_FOLLOWER) {
|
|
163
87
|
logger_1.log.debug('Refreshing metadata', { reason: error.message });
|
|
164
88
|
const topics = Object.keys(this.metadata.getTopicPartitions());
|
|
165
|
-
await this.fetchMetadata(topics, false);
|
|
89
|
+
await this.metadata.fetchMetadata({ topics, allowTopicAutoCreation: false });
|
|
166
90
|
return;
|
|
167
91
|
}
|
|
168
92
|
if (error instanceof error_1.KafkaTSApiError && error.errorCode === api_1.API_ERROR.OUT_OF_ORDER_SEQUENCE_NUMBER) {
|
|
169
93
|
logger_1.log.debug('Out of order sequence number. Reinitializing producer ID');
|
|
170
|
-
await this.initProducerId();
|
|
94
|
+
await this.state.initProducerId();
|
|
171
95
|
return;
|
|
172
96
|
}
|
|
173
97
|
throw error;
|
|
@@ -178,6 +102,6 @@ exports.Producer = Producer;
|
|
|
178
102
|
__decorate([
|
|
179
103
|
trace(() => ({ root: true })),
|
|
180
104
|
__metadata("design:type", Function),
|
|
181
|
-
__metadata("design:paramtypes", [Array
|
|
105
|
+
__metadata("design:paramtypes", [Array]),
|
|
182
106
|
__metadata("design:returntype", Promise)
|
|
183
107
|
], Producer.prototype, "send", null);
|
package/dist/utils/decoder.js
CHANGED
|
@@ -110,12 +110,16 @@ class Decoder {
|
|
|
110
110
|
}
|
|
111
111
|
readArray(callback) {
|
|
112
112
|
const length = this.readInt32();
|
|
113
|
-
const results = Array
|
|
113
|
+
const results = new Array(length);
|
|
114
|
+
for (let i = 0; i < length; i++)
|
|
115
|
+
results[i] = callback(this);
|
|
114
116
|
return results;
|
|
115
117
|
}
|
|
116
118
|
readCompactArray(callback) {
|
|
117
119
|
const length = this.readUVarInt() - 1;
|
|
118
|
-
const results = Array
|
|
120
|
+
const results = new Array(length);
|
|
121
|
+
for (let i = 0; i < length; i++)
|
|
122
|
+
results[i] = callback(this);
|
|
119
123
|
return results;
|
|
120
124
|
}
|
|
121
125
|
readVarIntArray(callback) {
|
|
@@ -125,15 +129,16 @@ class Decoder {
|
|
|
125
129
|
}
|
|
126
130
|
readRecords(callback) {
|
|
127
131
|
const length = this.readInt32();
|
|
128
|
-
|
|
132
|
+
const results = [];
|
|
133
|
+
for (let i = 0; i < length; i++) {
|
|
129
134
|
const size = this.readVarInt();
|
|
130
|
-
if (!size)
|
|
131
|
-
|
|
132
|
-
}
|
|
135
|
+
if (!size)
|
|
136
|
+
continue;
|
|
133
137
|
const child = new Decoder(this.buffer.subarray(this.offset, this.offset + size));
|
|
134
138
|
this.offset += size;
|
|
135
|
-
|
|
136
|
-
}
|
|
139
|
+
results.push(callback(child));
|
|
140
|
+
}
|
|
141
|
+
return results;
|
|
137
142
|
}
|
|
138
143
|
read(length) {
|
|
139
144
|
const value = this.buffer.subarray(this.offset, length !== undefined ? this.offset + length : undefined);
|
package/dist/utils/encoder.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export declare class Encoder {
|
|
2
|
-
private
|
|
3
|
-
|
|
2
|
+
private buffer;
|
|
3
|
+
private offset;
|
|
4
|
+
constructor(initialCapacity?: number);
|
|
5
|
+
private ensure;
|
|
4
6
|
getBufferLength(): number;
|
|
5
|
-
write(
|
|
6
|
-
writeEncoder(
|
|
7
|
+
write(src: Buffer): this;
|
|
8
|
+
writeEncoder(other: Encoder): this;
|
|
7
9
|
writeInt8(value: number): this;
|
|
8
10
|
writeInt16(value: number): this;
|
|
9
11
|
writeInt32(value: number): this;
|
|
@@ -18,10 +20,10 @@ export declare class Encoder {
|
|
|
18
20
|
writeVarIntString(value: string | null): this;
|
|
19
21
|
writeUUID(value: string | null): this;
|
|
20
22
|
writeBoolean(value: boolean): this;
|
|
21
|
-
writeArray<T>(arr: T[], callback: (encoder: Encoder, item: T) =>
|
|
22
|
-
writeCompactArray<T>(arr: T[] | null, callback: (encoder: Encoder, item: T) =>
|
|
23
|
-
writeVarIntArray<T>(arr: T[], callback: (encoder: Encoder, item: T) =>
|
|
23
|
+
writeArray<T>(arr: T[], callback: (encoder: Encoder, item: T) => void): this;
|
|
24
|
+
writeCompactArray<T>(arr: T[] | null, callback: (encoder: Encoder, item: T) => void): this;
|
|
25
|
+
writeVarIntArray<T>(arr: T[], callback: (encoder: Encoder, item: T) => void): this;
|
|
24
26
|
writeBytes(value: Buffer): this;
|
|
25
27
|
writeCompactBytes(value: Buffer): this;
|
|
26
|
-
value(): Buffer<
|
|
28
|
+
value(): Buffer<ArrayBufferLike>;
|
|
27
29
|
}
|
package/dist/utils/encoder.js
CHANGED
|
@@ -2,121 +2,158 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Encoder = void 0;
|
|
4
4
|
class Encoder {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
buffer;
|
|
6
|
+
offset = 0;
|
|
7
|
+
constructor(initialCapacity = 512) {
|
|
8
|
+
this.buffer = Buffer.allocUnsafe(initialCapacity);
|
|
9
|
+
}
|
|
10
|
+
ensure(extra) {
|
|
11
|
+
const need = this.offset + extra;
|
|
12
|
+
if (need <= this.buffer.length)
|
|
13
|
+
return;
|
|
14
|
+
let cap = this.buffer.length;
|
|
15
|
+
while (cap < need)
|
|
16
|
+
cap <<= 1;
|
|
17
|
+
const n = Buffer.allocUnsafe(cap);
|
|
18
|
+
this.buffer.copy(n, 0, 0, this.offset);
|
|
19
|
+
this.buffer = n;
|
|
8
20
|
}
|
|
9
21
|
getBufferLength() {
|
|
10
|
-
return this.
|
|
22
|
+
return this.offset;
|
|
11
23
|
}
|
|
12
|
-
write(
|
|
13
|
-
this.
|
|
24
|
+
write(src) {
|
|
25
|
+
this.ensure(src.length);
|
|
26
|
+
src.copy(this.buffer, this.offset);
|
|
27
|
+
this.offset += src.length;
|
|
14
28
|
return this;
|
|
15
29
|
}
|
|
16
|
-
writeEncoder(
|
|
17
|
-
|
|
30
|
+
writeEncoder(other) {
|
|
31
|
+
this.write(other.buffer.subarray(0, other.offset));
|
|
32
|
+
return this;
|
|
18
33
|
}
|
|
19
34
|
writeInt8(value) {
|
|
20
|
-
|
|
21
|
-
buffer.writeInt8(value);
|
|
22
|
-
|
|
35
|
+
this.ensure(1);
|
|
36
|
+
this.buffer.writeInt8(value, this.offset);
|
|
37
|
+
this.offset += 1;
|
|
38
|
+
return this;
|
|
23
39
|
}
|
|
24
40
|
writeInt16(value) {
|
|
25
|
-
|
|
26
|
-
buffer.writeInt16BE(value);
|
|
27
|
-
|
|
41
|
+
this.ensure(2);
|
|
42
|
+
this.buffer.writeInt16BE(value, this.offset);
|
|
43
|
+
this.offset += 2;
|
|
44
|
+
return this;
|
|
28
45
|
}
|
|
29
46
|
writeInt32(value) {
|
|
30
|
-
|
|
31
|
-
buffer.writeInt32BE(value);
|
|
32
|
-
|
|
47
|
+
this.ensure(4);
|
|
48
|
+
this.buffer.writeInt32BE(value, this.offset);
|
|
49
|
+
this.offset += 4;
|
|
50
|
+
return this;
|
|
33
51
|
}
|
|
34
52
|
writeUInt32(value) {
|
|
35
|
-
|
|
36
|
-
buffer.writeUInt32BE(value);
|
|
37
|
-
|
|
53
|
+
this.ensure(4);
|
|
54
|
+
this.buffer.writeUInt32BE(value, this.offset);
|
|
55
|
+
this.offset += 4;
|
|
56
|
+
return this;
|
|
38
57
|
}
|
|
39
58
|
writeInt64(value) {
|
|
40
|
-
|
|
41
|
-
buffer.writeBigInt64BE(value);
|
|
42
|
-
|
|
59
|
+
this.ensure(8);
|
|
60
|
+
this.buffer.writeBigInt64BE(value, this.offset);
|
|
61
|
+
this.offset += 8;
|
|
62
|
+
return this;
|
|
43
63
|
}
|
|
44
64
|
writeUVarInt(value) {
|
|
45
|
-
|
|
46
|
-
while (
|
|
47
|
-
|
|
65
|
+
this.ensure(5);
|
|
66
|
+
while (value & 0xffffff80) {
|
|
67
|
+
this.buffer[this.offset++] = (value & 0x7f) | 0x80;
|
|
48
68
|
value >>>= 7;
|
|
49
69
|
}
|
|
50
|
-
|
|
51
|
-
return this
|
|
70
|
+
this.buffer[this.offset++] = value & 0x7f;
|
|
71
|
+
return this;
|
|
52
72
|
}
|
|
53
73
|
writeVarInt(value) {
|
|
54
|
-
|
|
55
|
-
return this.writeUVarInt(encodedValue);
|
|
74
|
+
return this.writeUVarInt((value << 1) ^ (value >> 31));
|
|
56
75
|
}
|
|
57
76
|
writeUVarLong(value) {
|
|
58
|
-
|
|
59
|
-
while (
|
|
60
|
-
|
|
77
|
+
this.ensure(10);
|
|
78
|
+
while (value >= 0x80n) {
|
|
79
|
+
this.buffer[this.offset++] = Number((value & 0x7fn) | 0x80n);
|
|
61
80
|
value >>= 7n;
|
|
62
81
|
}
|
|
63
|
-
|
|
64
|
-
return this
|
|
82
|
+
this.buffer[this.offset++] = Number(value);
|
|
83
|
+
return this;
|
|
65
84
|
}
|
|
66
85
|
writeVarLong(value) {
|
|
67
|
-
|
|
68
|
-
return this.writeUVarLong(encodedValue);
|
|
86
|
+
return this.writeUVarLong((value << 1n) ^ (value >> 63n));
|
|
69
87
|
}
|
|
70
88
|
writeString(value) {
|
|
71
|
-
if (value === null)
|
|
89
|
+
if (value === null)
|
|
72
90
|
return this.writeInt16(-1);
|
|
73
|
-
}
|
|
74
91
|
const buffer = Buffer.from(value, 'utf-8');
|
|
75
|
-
|
|
92
|
+
this.writeInt16(buffer.length);
|
|
93
|
+
this.write(buffer);
|
|
94
|
+
return this;
|
|
76
95
|
}
|
|
77
96
|
writeCompactString(value) {
|
|
78
|
-
if (value === null)
|
|
97
|
+
if (value === null)
|
|
79
98
|
return this.writeUVarInt(0);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
const b = Buffer.from(value, 'utf-8');
|
|
100
|
+
this.writeUVarInt(b.length + 1);
|
|
101
|
+
this.write(b);
|
|
102
|
+
return this;
|
|
83
103
|
}
|
|
84
104
|
writeVarIntString(value) {
|
|
85
|
-
if (value === null)
|
|
105
|
+
if (value === null)
|
|
86
106
|
return this.writeVarInt(-1);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
107
|
+
const b = Buffer.from(value, 'utf-8');
|
|
108
|
+
this.writeVarInt(b.length);
|
|
109
|
+
this.write(b);
|
|
110
|
+
return this;
|
|
90
111
|
}
|
|
91
112
|
writeUUID(value) {
|
|
92
113
|
if (value === null) {
|
|
93
|
-
|
|
114
|
+
this.ensure(16);
|
|
115
|
+
this.buffer.fill(0, this.offset, this.offset + 16);
|
|
116
|
+
this.offset += 16;
|
|
117
|
+
return this;
|
|
94
118
|
}
|
|
95
|
-
|
|
119
|
+
this.write(Buffer.from(value, 'hex'));
|
|
120
|
+
return this;
|
|
96
121
|
}
|
|
97
122
|
writeBoolean(value) {
|
|
98
123
|
return this.writeInt8(value ? 1 : 0);
|
|
99
124
|
}
|
|
100
125
|
writeArray(arr, callback) {
|
|
101
|
-
|
|
126
|
+
this.writeInt32(arr.length);
|
|
127
|
+
for (const it of arr)
|
|
128
|
+
callback(this, it);
|
|
129
|
+
return this;
|
|
102
130
|
}
|
|
103
131
|
writeCompactArray(arr, callback) {
|
|
104
|
-
if (arr === null)
|
|
132
|
+
if (arr === null)
|
|
105
133
|
return this.writeUVarInt(0);
|
|
106
|
-
|
|
107
|
-
|
|
134
|
+
this.writeUVarInt(arr.length + 1);
|
|
135
|
+
for (const it of arr)
|
|
136
|
+
callback(this, it);
|
|
137
|
+
return this;
|
|
108
138
|
}
|
|
109
139
|
writeVarIntArray(arr, callback) {
|
|
110
|
-
|
|
140
|
+
this.writeVarInt(arr.length);
|
|
141
|
+
for (const it of arr)
|
|
142
|
+
callback(this, it);
|
|
143
|
+
return this;
|
|
111
144
|
}
|
|
112
145
|
writeBytes(value) {
|
|
113
|
-
|
|
146
|
+
this.writeInt32(value.length);
|
|
147
|
+
this.write(value);
|
|
148
|
+
return this;
|
|
114
149
|
}
|
|
115
150
|
writeCompactBytes(value) {
|
|
116
|
-
|
|
151
|
+
this.writeUVarInt(value.length + 1);
|
|
152
|
+
this.write(value);
|
|
153
|
+
return this;
|
|
117
154
|
}
|
|
118
155
|
value() {
|
|
119
|
-
return
|
|
156
|
+
return this.buffer.subarray(0, this.offset);
|
|
120
157
|
}
|
|
121
158
|
}
|
|
122
159
|
exports.Encoder = Encoder;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PromiseChain = void 0;
|
|
4
|
+
class PromiseChain {
|
|
5
|
+
locks = new Map();
|
|
6
|
+
async run(keys, callback) {
|
|
7
|
+
const orderedKeys = [...new Set(keys)].sort();
|
|
8
|
+
const releases = [];
|
|
9
|
+
for (const key of orderedKeys) {
|
|
10
|
+
const release = await this.acquire(key);
|
|
11
|
+
releases.push(release);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
await callback();
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
releases.reverse().forEach((release) => release());
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async acquire(key) {
|
|
21
|
+
const previousTail = this.locks.get(key);
|
|
22
|
+
let release;
|
|
23
|
+
const currentTail = new Promise((resolve) => (release = resolve));
|
|
24
|
+
if (previousTail) {
|
|
25
|
+
this.locks.set(key, previousTail.then(() => currentTail));
|
|
26
|
+
await previousTail;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.locks.set(key, currentTail);
|
|
30
|
+
}
|
|
31
|
+
return () => {
|
|
32
|
+
release();
|
|
33
|
+
if (this.locks.get(key) === currentTail) {
|
|
34
|
+
this.locks.delete(key);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.PromiseChain = PromiseChain;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const withRetry: (handleError: (error: unknown) => Promise<void>) => <T>(func: () => Promise<T>) => Promise<T>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withRetry = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const withRetry = (handleError) => async (func) => {
|
|
6
|
+
let lastError;
|
|
7
|
+
for (let i = 0; i < 15; i++) {
|
|
8
|
+
try {
|
|
9
|
+
return await func();
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
await handleError(error);
|
|
13
|
+
lastError = error;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
logger_1.log.warn('Retries exhausted', { lastError });
|
|
17
|
+
throw lastError;
|
|
18
|
+
};
|
|
19
|
+
exports.withRetry = withRetry;
|
package/dist/utils/shared.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const shared: <F extends () => Promise<any>>(func: F) => () => ReturnType<F>;
|
|
1
|
+
export declare const shared: <F extends (...args: any[]) => Promise<any>>(func: F) => (...args: Parameters<F>) => ReturnType<F>;
|
package/dist/utils/shared.js
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.shared = void 0;
|
|
4
4
|
const shared = (func) => {
|
|
5
|
-
let
|
|
6
|
-
return () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
let promises = {};
|
|
6
|
+
return (...args) => {
|
|
7
|
+
const key = JSON.stringify(args);
|
|
8
|
+
if (!promises[key]) {
|
|
9
|
+
promises[key] = func(...args);
|
|
10
|
+
promises[key].finally(() => {
|
|
11
|
+
delete promises[key];
|
|
11
12
|
});
|
|
12
13
|
}
|
|
13
|
-
return
|
|
14
|
+
return promises[key];
|
|
14
15
|
};
|
|
15
16
|
};
|
|
16
17
|
exports.shared = shared;
|
package/package.json
CHANGED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { IsolationLevel } from "../api/fetch";
|
|
2
|
-
import { Assignment } from "../api/sync-group";
|
|
3
|
-
import { Cluster } from "../cluster";
|
|
4
|
-
import { OffsetManager } from "./offset-manager";
|
|
5
|
-
export type Metadata = ReturnType<typeof createMetadata>;
|
|
6
|
-
type MetadataOptions = {
|
|
7
|
-
cluster: Cluster;
|
|
8
|
-
topics?: string[];
|
|
9
|
-
isolationLevel?: IsolationLevel;
|
|
10
|
-
allowTopicAutoCreation?: boolean;
|
|
11
|
-
fromBeginning?: boolean;
|
|
12
|
-
offsetManager?: OffsetManager;
|
|
13
|
-
};
|
|
14
|
-
export declare const createMetadata: ({ cluster, topics, isolationLevel, allowTopicAutoCreation, fromBeginning, offsetManager, }: MetadataOptions) => {
|
|
15
|
-
init: () => Promise<void>;
|
|
16
|
-
getTopicPartitions: () => Record<string, number[]>;
|
|
17
|
-
getTopicIdByName: (name: string) => string;
|
|
18
|
-
getTopicNameById: (id: string) => string;
|
|
19
|
-
getAssignment: () => Assignment;
|
|
20
|
-
setAssignment: (newAssignment: Assignment) => void;
|
|
21
|
-
getLeaderIdByTopicPartition: (topic: string, partition: number) => number;
|
|
22
|
-
getIsrNodeIdsByTopicPartition: (topic: string, partition: number) => number[];
|
|
23
|
-
};
|
|
24
|
-
export {};
|