kafka-ts 0.0.3-beta → 0.0.4
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 +72 -8
- package/dist/api/api-versions.d.ts +9 -0
- package/{src/api/api-versions.ts → dist/api/api-versions.js} +8 -5
- package/dist/api/create-topics.d.ts +38 -0
- package/dist/api/create-topics.js +53 -0
- package/dist/api/delete-topics.d.ts +18 -0
- package/dist/api/delete-topics.js +33 -0
- package/dist/api/fetch.d.ts +84 -0
- package/dist/api/fetch.js +142 -0
- package/dist/api/find-coordinator.d.ts +21 -0
- package/{src/api/find-coordinator.ts → dist/api/find-coordinator.js} +14 -14
- package/dist/api/heartbeat.d.ts +11 -0
- package/dist/api/heartbeat.js +27 -0
- package/dist/api/index.d.ts +576 -0
- package/{src/api/index.ts → dist/api/index.js} +42 -41
- package/dist/api/init-producer-id.d.ts +13 -0
- package/dist/api/init-producer-id.js +29 -0
- package/dist/api/join-group.d.ts +34 -0
- package/dist/api/join-group.js +51 -0
- package/dist/api/leave-group.d.ts +19 -0
- package/dist/api/leave-group.js +39 -0
- package/dist/api/list-offsets.d.ts +29 -0
- package/dist/api/list-offsets.js +48 -0
- package/dist/api/metadata.d.ts +40 -0
- package/{src/api/metadata.ts → dist/api/metadata.js} +18 -26
- package/dist/api/offset-commit.d.ts +28 -0
- package/dist/api/offset-commit.js +48 -0
- package/dist/api/offset-fetch.d.ts +31 -0
- package/dist/api/offset-fetch.js +55 -0
- package/dist/api/produce.d.ts +54 -0
- package/{src/api/produce.ts → dist/api/produce.js} +55 -102
- package/dist/api/sasl-authenticate.d.ts +11 -0
- package/dist/api/sasl-authenticate.js +23 -0
- package/dist/api/sasl-handshake.d.ts +6 -0
- package/dist/api/sasl-handshake.js +19 -0
- package/dist/api/sync-group.d.ts +24 -0
- package/dist/api/sync-group.js +36 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +8 -0
- package/dist/auth/plain.d.ts +5 -0
- package/dist/auth/plain.js +12 -0
- package/dist/auth/scram.d.ts +9 -0
- package/dist/auth/scram.js +40 -0
- package/dist/broker.d.ts +30 -0
- package/dist/broker.js +55 -0
- package/dist/client.d.ts +22 -0
- package/dist/client.js +36 -0
- package/dist/cluster.d.ts +27 -0
- package/dist/cluster.js +70 -0
- package/dist/cluster.test.d.ts +1 -0
- package/{src/cluster.test.ts → dist/cluster.test.js} +87 -113
- package/dist/codecs/gzip.d.ts +2 -0
- package/dist/codecs/gzip.js +8 -0
- package/dist/codecs/index.d.ts +2 -0
- package/dist/codecs/index.js +17 -0
- package/dist/codecs/none.d.ts +2 -0
- package/dist/codecs/none.js +7 -0
- package/dist/codecs/types.d.ts +5 -0
- package/dist/codecs/types.js +2 -0
- package/dist/connection.d.ts +26 -0
- package/dist/connection.js +175 -0
- package/dist/consumer/consumer-group.d.ts +41 -0
- package/dist/consumer/consumer-group.js +215 -0
- package/dist/consumer/consumer-metadata.d.ts +7 -0
- package/dist/consumer/consumer-metadata.js +14 -0
- package/dist/consumer/consumer.d.ts +44 -0
- package/dist/consumer/consumer.js +225 -0
- package/dist/consumer/fetch-manager.d.ts +33 -0
- package/dist/consumer/fetch-manager.js +140 -0
- package/dist/consumer/fetcher.d.ts +25 -0
- package/dist/consumer/fetcher.js +64 -0
- package/dist/consumer/offset-manager.d.ts +22 -0
- package/dist/consumer/offset-manager.js +66 -0
- package/dist/consumer/processor.d.ts +19 -0
- package/dist/consumer/processor.js +59 -0
- package/dist/distributors/assignments-to-replicas.d.ts +16 -0
- package/{src/distributors/assignments-to-replicas.ts → dist/distributors/assignments-to-replicas.js} +15 -41
- package/dist/distributors/assignments-to-replicas.test.d.ts +1 -0
- package/dist/distributors/assignments-to-replicas.test.js +40 -0
- package/dist/distributors/messages-to-topic-partition-leaders.d.ts +17 -0
- package/dist/distributors/messages-to-topic-partition-leaders.js +15 -0
- package/dist/distributors/messages-to-topic-partition-leaders.test.d.ts +1 -0
- package/dist/distributors/messages-to-topic-partition-leaders.test.js +30 -0
- package/dist/distributors/partitioner.d.ts +7 -0
- package/dist/distributors/partitioner.js +23 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +26 -0
- package/dist/metadata.d.ts +24 -0
- package/dist/metadata.js +106 -0
- package/dist/producer/producer.d.ts +24 -0
- package/dist/producer/producer.js +131 -0
- package/{src/types.ts → dist/types.d.ts} +4 -4
- package/dist/types.js +2 -0
- package/{src/utils/api.ts → dist/utils/api.d.ts} +2 -4
- package/dist/utils/api.js +5 -0
- package/dist/utils/crypto.d.ts +8 -0
- package/dist/utils/crypto.js +18 -0
- package/dist/utils/decoder.d.ts +30 -0
- package/{src/utils/decoder.ts → dist/utils/decoder.js} +41 -57
- package/dist/utils/delay.d.ts +1 -0
- package/dist/utils/delay.js +5 -0
- package/dist/utils/encoder.d.ts +28 -0
- package/{src/utils/encoder.ts → dist/utils/encoder.js} +50 -66
- package/dist/utils/error.d.ts +11 -0
- package/dist/utils/error.js +27 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/memo.d.ts +1 -0
- package/{src/utils/memo.ts → dist/utils/memo.js} +7 -3
- package/dist/utils/murmur2.d.ts +3 -0
- package/dist/utils/murmur2.js +40 -0
- package/dist/utils/retrier.d.ts +10 -0
- package/dist/utils/retrier.js +22 -0
- package/dist/utils/tracer.d.ts +5 -0
- package/dist/utils/tracer.js +39 -0
- package/package.json +11 -2
- package/.github/workflows/release.yml +0 -17
- package/.prettierrc +0 -8
- package/certs/ca.crt +0 -29
- package/certs/ca.key +0 -52
- package/certs/ca.srl +0 -1
- package/certs/kafka.crt +0 -29
- package/certs/kafka.csr +0 -26
- package/certs/kafka.key +0 -52
- package/certs/kafka.keystore.jks +0 -0
- package/certs/kafka.truststore.jks +0 -0
- package/docker-compose.yml +0 -104
- package/examples/package-lock.json +0 -31
- package/examples/package.json +0 -14
- package/examples/src/client.ts +0 -9
- package/examples/src/consumer.ts +0 -18
- package/examples/src/create-topic.ts +0 -44
- package/examples/src/producer.ts +0 -24
- package/examples/src/replicator.ts +0 -25
- package/examples/src/utils/delay.ts +0 -1
- package/examples/src/utils/json.ts +0 -1
- package/examples/tsconfig.json +0 -7
- package/log4j.properties +0 -95
- package/scripts/generate-certs.sh +0 -24
- package/src/__snapshots__/request-handler.test.ts.snap +0 -978
- package/src/api/create-topics.ts +0 -78
- package/src/api/delete-topics.ts +0 -42
- package/src/api/fetch.ts +0 -143
- package/src/api/heartbeat.ts +0 -33
- package/src/api/init-producer-id.ts +0 -35
- package/src/api/join-group.ts +0 -67
- package/src/api/leave-group.ts +0 -48
- package/src/api/list-offsets.ts +0 -65
- package/src/api/offset-commit.ts +0 -67
- package/src/api/offset-fetch.ts +0 -74
- package/src/api/sasl-authenticate.ts +0 -21
- package/src/api/sasl-handshake.ts +0 -16
- package/src/api/sync-group.ts +0 -54
- package/src/broker.ts +0 -74
- package/src/client.ts +0 -47
- package/src/cluster.ts +0 -87
- package/src/connection.ts +0 -143
- package/src/consumer/consumer-group.ts +0 -209
- package/src/consumer/consumer-metadata.ts +0 -14
- package/src/consumer/consumer.ts +0 -231
- package/src/consumer/fetch-manager.ts +0 -179
- package/src/consumer/fetcher.ts +0 -57
- package/src/consumer/offset-manager.ts +0 -93
- package/src/consumer/processor.ts +0 -47
- package/src/distributors/assignments-to-replicas.test.ts +0 -43
- package/src/distributors/messages-to-topic-partition-leaders.test.ts +0 -32
- package/src/distributors/messages-to-topic-partition-leaders.ts +0 -19
- package/src/index.ts +0 -4
- package/src/metadata.ts +0 -122
- package/src/producer/producer.ts +0 -132
- package/src/utils/debug.ts +0 -9
- package/src/utils/delay.ts +0 -1
- package/src/utils/error.ts +0 -21
- package/src/utils/retrier.ts +0 -39
- package/src/utils/tracer.ts +0 -31
- package/tsconfig.json +0 -17
|
@@ -1,58 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const crypto_1 = require("crypto");
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const vitest_1 = require("vitest");
|
|
6
|
+
const api_1 = require("./api");
|
|
7
|
+
const find_coordinator_1 = require("./api/find-coordinator");
|
|
8
|
+
const auth_1 = require("./auth");
|
|
9
|
+
const client_1 = require("./client");
|
|
10
|
+
const kafka = (0, client_1.createKafkaClient)({
|
|
11
11
|
clientId: 'kafka-ts',
|
|
12
12
|
bootstrapServers: [{ host: 'localhost', port: 9092 }],
|
|
13
|
-
sasl: {
|
|
14
|
-
ssl: { ca: readFileSync('./certs/ca.crt').toString() },
|
|
13
|
+
sasl: (0, auth_1.saslPlain)({ username: 'admin', password: 'admin' }),
|
|
14
|
+
ssl: { ca: (0, fs_1.readFileSync)('./certs/ca.crt').toString() },
|
|
15
15
|
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
cluster = await kafka.createCluster().connect();
|
|
24
|
-
|
|
25
|
-
const metadataResult = await cluster.sendRequest(API.METADATA, {
|
|
16
|
+
vitest_1.describe.sequential('Low-level API', () => {
|
|
17
|
+
const groupId = (0, crypto_1.randomBytes)(16).toString('hex');
|
|
18
|
+
let cluster;
|
|
19
|
+
(0, vitest_1.beforeAll)(async () => {
|
|
20
|
+
cluster = await kafka.createCluster();
|
|
21
|
+
await cluster.connect();
|
|
22
|
+
const metadataResult = await cluster.sendRequest(api_1.API.METADATA, {
|
|
26
23
|
topics: null,
|
|
27
24
|
allowTopicAutoCreation: false,
|
|
28
25
|
includeTopicAuthorizedOperations: false,
|
|
29
26
|
});
|
|
30
27
|
if (metadataResult.topics.some((topic) => topic.name === 'kafka-ts-test-topic')) {
|
|
31
|
-
await cluster.sendRequest(API.DELETE_TOPICS, {
|
|
28
|
+
await cluster.sendRequest(api_1.API.DELETE_TOPICS, {
|
|
32
29
|
topics: [{ name: 'kafka-ts-test-topic', topicId: null }],
|
|
33
30
|
timeoutMs: 10000,
|
|
34
31
|
});
|
|
35
32
|
}
|
|
36
33
|
});
|
|
37
|
-
|
|
38
|
-
afterAll(async () => {
|
|
34
|
+
(0, vitest_1.afterAll)(async () => {
|
|
39
35
|
await cluster.disconnect();
|
|
40
36
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
expect(result).toMatchSnapshot();
|
|
37
|
+
(0, vitest_1.it)('should request api versions', async () => {
|
|
38
|
+
const result = await cluster.sendRequest(api_1.API.API_VERSIONS, {});
|
|
39
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
45
40
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
it('should create topics', async () => {
|
|
50
|
-
const result = await cluster.sendRequest(API.CREATE_TOPICS, {
|
|
41
|
+
let topicId = 'd6718d178e1b47c886441ad2d19faea5';
|
|
42
|
+
(0, vitest_1.it)('should create topics', async () => {
|
|
43
|
+
const result = await cluster.sendRequest(api_1.API.CREATE_TOPICS, {
|
|
51
44
|
topics: [
|
|
52
45
|
{
|
|
53
46
|
name: 'kafka-ts-test-topic',
|
|
54
|
-
numPartitions:
|
|
55
|
-
replicationFactor:
|
|
47
|
+
numPartitions: 10,
|
|
48
|
+
replicationFactor: 3,
|
|
56
49
|
assignments: [],
|
|
57
50
|
configs: [],
|
|
58
51
|
},
|
|
@@ -64,13 +57,11 @@ describe.sequential('Request handler', () => {
|
|
|
64
57
|
result.topics.forEach((topic) => {
|
|
65
58
|
topic.topicId = 'Any<UUID>';
|
|
66
59
|
});
|
|
67
|
-
expect(result).toMatchSnapshot();
|
|
68
|
-
|
|
60
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
69
61
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
70
62
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const result = await cluster.sendRequest(API.METADATA, {
|
|
63
|
+
(0, vitest_1.it)('should request metadata for all topics', async () => {
|
|
64
|
+
const result = await cluster.sendRequest(api_1.API.METADATA, {
|
|
74
65
|
topics: null,
|
|
75
66
|
allowTopicAutoCreation: false,
|
|
76
67
|
includeTopicAuthorizedOperations: false,
|
|
@@ -85,17 +76,17 @@ describe.sequential('Request handler', () => {
|
|
|
85
76
|
partition.replicaNodes = [0];
|
|
86
77
|
});
|
|
87
78
|
});
|
|
88
|
-
expect(result).toMatchSnapshot();
|
|
79
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
89
80
|
});
|
|
90
|
-
|
|
81
|
+
let partitionIndex = 0;
|
|
91
82
|
let leaderId = 0;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const result = await cluster.sendRequest(API.METADATA, {
|
|
83
|
+
(0, vitest_1.it)('should request metadata for a topic', async () => {
|
|
84
|
+
const result = await cluster.sendRequest(api_1.API.METADATA, {
|
|
95
85
|
topics: [{ id: topicId, name: 'kafka-ts-test-topic' }],
|
|
96
86
|
allowTopicAutoCreation: false,
|
|
97
87
|
includeTopicAuthorizedOperations: false,
|
|
98
88
|
});
|
|
89
|
+
partitionIndex = result.topics[0].partitions[0].partitionIndex;
|
|
99
90
|
leaderId = result.topics[0].partitions[0].leaderId;
|
|
100
91
|
result.controllerId = 0;
|
|
101
92
|
result.topics.forEach((topic) => {
|
|
@@ -106,25 +97,22 @@ describe.sequential('Request handler', () => {
|
|
|
106
97
|
partition.replicaNodes = [0];
|
|
107
98
|
});
|
|
108
99
|
});
|
|
109
|
-
expect(result).toMatchSnapshot();
|
|
100
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
110
101
|
});
|
|
111
|
-
|
|
112
102
|
let producerId = 9n;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const result = await cluster.sendRequest(API.INIT_PRODUCER_ID, {
|
|
103
|
+
(0, vitest_1.it)('should init producer id', async () => {
|
|
104
|
+
const result = await cluster.sendRequest(api_1.API.INIT_PRODUCER_ID, {
|
|
116
105
|
transactionalId: null,
|
|
117
106
|
transactionTimeoutMs: 0,
|
|
118
107
|
producerId,
|
|
119
108
|
producerEpoch: 0,
|
|
120
109
|
});
|
|
121
110
|
result.producerId = 0n;
|
|
122
|
-
expect(result).toMatchSnapshot();
|
|
111
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
123
112
|
});
|
|
124
|
-
|
|
125
|
-
it('should produce messages', async () => {
|
|
113
|
+
(0, vitest_1.it)('should produce messages', async () => {
|
|
126
114
|
const now = Date.now();
|
|
127
|
-
const result = await cluster.sendRequestToNode(leaderId)(API.PRODUCE, {
|
|
115
|
+
const result = await cluster.sendRequestToNode(leaderId)(api_1.API.PRODUCE, {
|
|
128
116
|
transactionalId: null,
|
|
129
117
|
timeoutMs: 10000,
|
|
130
118
|
acks: 1,
|
|
@@ -133,7 +121,7 @@ describe.sequential('Request handler', () => {
|
|
|
133
121
|
name: 'kafka-ts-test-topic',
|
|
134
122
|
partitionData: [
|
|
135
123
|
{
|
|
136
|
-
index:
|
|
124
|
+
index: partitionIndex,
|
|
137
125
|
baseOffset: 0n,
|
|
138
126
|
partitionLeaderEpoch: 0,
|
|
139
127
|
attributes: 0,
|
|
@@ -148,12 +136,12 @@ describe.sequential('Request handler', () => {
|
|
|
148
136
|
attributes: 0,
|
|
149
137
|
offsetDelta: 0,
|
|
150
138
|
timestampDelta: 0n,
|
|
151
|
-
key: 'key',
|
|
152
|
-
value: 'value',
|
|
139
|
+
key: Buffer.from('key'),
|
|
140
|
+
value: Buffer.from('value'),
|
|
153
141
|
headers: [
|
|
154
142
|
{
|
|
155
|
-
key: 'header-key',
|
|
156
|
-
value: 'header-value',
|
|
143
|
+
key: Buffer.from('header-key'),
|
|
144
|
+
value: Buffer.from('header-value'),
|
|
157
145
|
},
|
|
158
146
|
],
|
|
159
147
|
},
|
|
@@ -163,11 +151,10 @@ describe.sequential('Request handler', () => {
|
|
|
163
151
|
},
|
|
164
152
|
],
|
|
165
153
|
});
|
|
166
|
-
expect(result).toMatchSnapshot();
|
|
154
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
167
155
|
});
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const result = await cluster.sendRequestToNode(leaderId)(API.FETCH, {
|
|
156
|
+
(0, vitest_1.it)('should fetch messages', async () => {
|
|
157
|
+
const result = await cluster.sendRequestToNode(leaderId)(api_1.API.FETCH, {
|
|
171
158
|
maxWaitMs: 100,
|
|
172
159
|
minBytes: 1,
|
|
173
160
|
maxBytes: 10485760,
|
|
@@ -179,7 +166,7 @@ describe.sequential('Request handler', () => {
|
|
|
179
166
|
topicId,
|
|
180
167
|
partitions: [
|
|
181
168
|
{
|
|
182
|
-
partition:
|
|
169
|
+
partition: partitionIndex,
|
|
183
170
|
currentLeaderEpoch: -1,
|
|
184
171
|
fetchOffset: 0n,
|
|
185
172
|
lastFetchedEpoch: 0,
|
|
@@ -196,23 +183,20 @@ describe.sequential('Request handler', () => {
|
|
|
196
183
|
response.topicId = 'Any<UUID>';
|
|
197
184
|
response.partitions.forEach((partition) => {
|
|
198
185
|
partition.records.forEach((record) => {
|
|
199
|
-
expect(record.baseTimestamp).toBeGreaterThan(1721926744730n);
|
|
200
|
-
expect(record.maxTimestamp).toBeGreaterThan(1721926744730n);
|
|
201
|
-
expect(record.crc).toBeGreaterThan(0);
|
|
202
|
-
|
|
186
|
+
(0, vitest_1.expect)(record.baseTimestamp).toBeGreaterThan(1721926744730n);
|
|
187
|
+
(0, vitest_1.expect)(record.maxTimestamp).toBeGreaterThan(1721926744730n);
|
|
188
|
+
(0, vitest_1.expect)(record.crc).toBeGreaterThan(0);
|
|
203
189
|
record.baseTimestamp = 0n;
|
|
204
190
|
record.maxTimestamp = 0n;
|
|
205
191
|
record.crc = 0;
|
|
206
192
|
});
|
|
207
193
|
});
|
|
208
194
|
});
|
|
209
|
-
expect(result).toMatchSnapshot();
|
|
195
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
210
196
|
});
|
|
211
|
-
|
|
212
197
|
let coordinatorId = -1;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const result = await cluster.sendRequest(API.FIND_COORDINATOR, { keyType: KEY_TYPE.GROUP, keys: [groupId] });
|
|
198
|
+
(0, vitest_1.it)('should find coordinator', async () => {
|
|
199
|
+
const result = await cluster.sendRequest(api_1.API.FIND_COORDINATOR, { keyType: find_coordinator_1.KEY_TYPE.GROUP, keys: [groupId] });
|
|
216
200
|
result.coordinators.forEach((coordinator) => {
|
|
217
201
|
coordinator.key = 'Any<String>';
|
|
218
202
|
});
|
|
@@ -221,14 +205,12 @@ describe.sequential('Request handler', () => {
|
|
|
221
205
|
coordinator.nodeId = 1;
|
|
222
206
|
coordinator.port = 9093;
|
|
223
207
|
});
|
|
224
|
-
expect(result).toMatchSnapshot();
|
|
208
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
225
209
|
});
|
|
226
|
-
|
|
227
210
|
let memberId = '';
|
|
228
|
-
|
|
229
|
-
it('should fail join group request with new memberId', async () => {
|
|
211
|
+
(0, vitest_1.it)('should fail join group request with new memberId', async () => {
|
|
230
212
|
try {
|
|
231
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.JOIN_GROUP, {
|
|
213
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.JOIN_GROUP, {
|
|
232
214
|
groupId,
|
|
233
215
|
sessionTimeoutMs: 30000,
|
|
234
216
|
rebalanceTimeoutMs: 60000,
|
|
@@ -243,17 +225,17 @@ describe.sequential('Request handler', () => {
|
|
|
243
225
|
],
|
|
244
226
|
reason: null,
|
|
245
227
|
});
|
|
246
|
-
expect(false, 'Should throw an error').toBe(true);
|
|
247
|
-
}
|
|
248
|
-
|
|
228
|
+
(0, vitest_1.expect)(false, 'Should throw an error').toBe(true);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
const { response } = error;
|
|
249
232
|
memberId = response.memberId;
|
|
250
233
|
response.memberId = 'Any<UUID>';
|
|
251
|
-
expect(response).toMatchSnapshot();
|
|
234
|
+
(0, vitest_1.expect)(response).toMatchSnapshot();
|
|
252
235
|
}
|
|
253
236
|
});
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.JOIN_GROUP, {
|
|
237
|
+
(0, vitest_1.it)('should join group', async () => {
|
|
238
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.JOIN_GROUP, {
|
|
257
239
|
groupId,
|
|
258
240
|
sessionTimeoutMs: 30000,
|
|
259
241
|
rebalanceTimeoutMs: 60000,
|
|
@@ -273,11 +255,10 @@ describe.sequential('Request handler', () => {
|
|
|
273
255
|
result.members.forEach((member) => {
|
|
274
256
|
member.memberId = 'Any<UUID>';
|
|
275
257
|
});
|
|
276
|
-
expect(result).toMatchSnapshot();
|
|
258
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
277
259
|
});
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.SYNC_GROUP, {
|
|
260
|
+
(0, vitest_1.it)('should sync group', async () => {
|
|
261
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.SYNC_GROUP, {
|
|
281
262
|
groupId,
|
|
282
263
|
generationId: 1,
|
|
283
264
|
memberId,
|
|
@@ -291,11 +272,10 @@ describe.sequential('Request handler', () => {
|
|
|
291
272
|
},
|
|
292
273
|
],
|
|
293
274
|
});
|
|
294
|
-
expect(result).toMatchSnapshot();
|
|
275
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
295
276
|
});
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.OFFSET_COMMIT, {
|
|
277
|
+
(0, vitest_1.it)('should commit offsets', async () => {
|
|
278
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.OFFSET_COMMIT, {
|
|
299
279
|
groupId,
|
|
300
280
|
generationIdOrMemberEpoch: 1,
|
|
301
281
|
memberId,
|
|
@@ -309,16 +289,13 @@ describe.sequential('Request handler', () => {
|
|
|
309
289
|
},
|
|
310
290
|
],
|
|
311
291
|
});
|
|
312
|
-
expect(result).toMatchSnapshot();
|
|
292
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
313
293
|
});
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.OFFSET_FETCH, {
|
|
294
|
+
(0, vitest_1.it)('should fetch offsets', async () => {
|
|
295
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.OFFSET_FETCH, {
|
|
317
296
|
groups: [
|
|
318
297
|
{
|
|
319
298
|
groupId,
|
|
320
|
-
memberId,
|
|
321
|
-
memberEpoch: 0,
|
|
322
299
|
topics: [
|
|
323
300
|
{
|
|
324
301
|
name: 'kafka-ts-test-topic',
|
|
@@ -332,38 +309,35 @@ describe.sequential('Request handler', () => {
|
|
|
332
309
|
result.groups.forEach((group) => {
|
|
333
310
|
group.groupId = 'Any<String>';
|
|
334
311
|
});
|
|
335
|
-
expect(result).toMatchSnapshot();
|
|
312
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
336
313
|
});
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.HEARTBEAT, {
|
|
314
|
+
(0, vitest_1.it)('should heartbeat', async () => {
|
|
315
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.HEARTBEAT, {
|
|
340
316
|
groupId,
|
|
341
317
|
generationId: 1,
|
|
342
318
|
memberId,
|
|
343
319
|
groupInstanceId: null,
|
|
344
320
|
});
|
|
345
|
-
expect(result).toMatchSnapshot();
|
|
321
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
346
322
|
});
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const result = await cluster.sendRequestToNode(coordinatorId)(API.LEAVE_GROUP, {
|
|
323
|
+
(0, vitest_1.it)('should leave group', async () => {
|
|
324
|
+
const result = await cluster.sendRequestToNode(coordinatorId)(api_1.API.LEAVE_GROUP, {
|
|
350
325
|
groupId,
|
|
351
326
|
members: [{ memberId, groupInstanceId: null, reason: null }],
|
|
352
327
|
});
|
|
353
328
|
result.members.forEach((member) => {
|
|
354
329
|
member.memberId = 'Any<UUID>';
|
|
355
330
|
});
|
|
356
|
-
expect(result).toMatchSnapshot();
|
|
331
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
357
332
|
});
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const result = await cluster.sendRequest(API.DELETE_TOPICS, {
|
|
333
|
+
(0, vitest_1.it)('should delete topics', async () => {
|
|
334
|
+
const result = await cluster.sendRequest(api_1.API.DELETE_TOPICS, {
|
|
361
335
|
topics: [{ name: 'kafka-ts-test-topic', topicId: null }],
|
|
362
336
|
timeoutMs: 10000,
|
|
363
337
|
});
|
|
364
338
|
result.responses.forEach((response) => {
|
|
365
339
|
response.topicId = 'Any<UUID>';
|
|
366
340
|
});
|
|
367
|
-
expect(result).toMatchSnapshot();
|
|
341
|
+
(0, vitest_1.expect)(result).toMatchSnapshot();
|
|
368
342
|
});
|
|
369
343
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GZIP = void 0;
|
|
4
|
+
const zlib_1 = require("zlib");
|
|
5
|
+
exports.GZIP = {
|
|
6
|
+
compress: async (data) => new Promise((resolve, reject) => (0, zlib_1.gzip)(data, (err, result) => (err ? reject(err) : resolve(result)))),
|
|
7
|
+
decompress: async (data) => new Promise((resolve, reject) => (0, zlib_1.unzip)(data, (err, result) => (err ? reject(err) : resolve(result)))),
|
|
8
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findCodec = void 0;
|
|
4
|
+
const gzip_1 = require("./gzip");
|
|
5
|
+
const none_1 = require("./none");
|
|
6
|
+
const codecs = {
|
|
7
|
+
0: none_1.NONE,
|
|
8
|
+
1: gzip_1.GZIP,
|
|
9
|
+
};
|
|
10
|
+
const findCodec = (type) => {
|
|
11
|
+
const codec = codecs[type];
|
|
12
|
+
if (!codec) {
|
|
13
|
+
throw new Error(`Unsupported codec: ${type}`);
|
|
14
|
+
}
|
|
15
|
+
return codec;
|
|
16
|
+
};
|
|
17
|
+
exports.findCodec = findCodec;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { TcpSocketConnectOpts } from 'net';
|
|
4
|
+
import { TLSSocketOptions } from 'tls';
|
|
5
|
+
import { Api } from './utils/api';
|
|
6
|
+
type ConnectionOptions = {
|
|
7
|
+
clientId: string | null;
|
|
8
|
+
connection: TcpSocketConnectOpts;
|
|
9
|
+
ssl: TLSSocketOptions | null;
|
|
10
|
+
};
|
|
11
|
+
export declare class Connection {
|
|
12
|
+
private options;
|
|
13
|
+
private socket;
|
|
14
|
+
private queue;
|
|
15
|
+
private lastCorrelationId;
|
|
16
|
+
private chunks;
|
|
17
|
+
constructor(options: ConnectionOptions);
|
|
18
|
+
connect(): Promise<void>;
|
|
19
|
+
disconnect(): Promise<void>;
|
|
20
|
+
sendRequest<Request, Response>(api: Api<Request, Response>, body: Request): Promise<Response>;
|
|
21
|
+
private write;
|
|
22
|
+
private handleData;
|
|
23
|
+
private nextCorrelationId;
|
|
24
|
+
}
|
|
25
|
+
export type SendRequest = typeof Connection.prototype.sendRequest;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
25
|
+
if (mod && mod.__esModule) return mod;
|
|
26
|
+
var result = {};
|
|
27
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
28
|
+
__setModuleDefault(result, mod);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
32
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.Connection = void 0;
|
|
39
|
+
const assert_1 = __importDefault(require("assert"));
|
|
40
|
+
const net_1 = __importStar(require("net"));
|
|
41
|
+
const tls_1 = __importDefault(require("tls"));
|
|
42
|
+
const api_1 = require("./api");
|
|
43
|
+
const decoder_1 = require("./utils/decoder");
|
|
44
|
+
const encoder_1 = require("./utils/encoder");
|
|
45
|
+
const error_1 = require("./utils/error");
|
|
46
|
+
const logger_1 = require("./utils/logger");
|
|
47
|
+
const tracer_1 = require("./utils/tracer");
|
|
48
|
+
const trace = (0, tracer_1.createTracer)('Connection');
|
|
49
|
+
class Connection {
|
|
50
|
+
options;
|
|
51
|
+
socket = new net_1.Socket();
|
|
52
|
+
queue = {};
|
|
53
|
+
lastCorrelationId = 0;
|
|
54
|
+
chunks = [];
|
|
55
|
+
constructor(options) {
|
|
56
|
+
this.options = options;
|
|
57
|
+
}
|
|
58
|
+
async connect() {
|
|
59
|
+
this.queue = {};
|
|
60
|
+
this.chunks = [];
|
|
61
|
+
await new Promise((resolve, reject) => {
|
|
62
|
+
const { ssl, connection } = this.options;
|
|
63
|
+
this.socket = ssl
|
|
64
|
+
? tls_1.default.connect({
|
|
65
|
+
...connection,
|
|
66
|
+
...ssl,
|
|
67
|
+
...(connection.host && !(0, net_1.isIP)(connection.host) && { servername: connection.host }),
|
|
68
|
+
}, resolve)
|
|
69
|
+
: net_1.default.connect(connection, resolve);
|
|
70
|
+
this.socket.once('error', reject);
|
|
71
|
+
});
|
|
72
|
+
this.socket.removeAllListeners('error');
|
|
73
|
+
this.socket.on('data', (data) => this.handleData(data));
|
|
74
|
+
this.socket.once('close', async () => {
|
|
75
|
+
Object.values(this.queue).forEach(({ reject }) => {
|
|
76
|
+
reject(new error_1.ConnectionError('Socket closed unexpectedly'));
|
|
77
|
+
});
|
|
78
|
+
this.queue = {};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
disconnect() {
|
|
82
|
+
this.socket.removeAllListeners();
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
if (this.socket.pending) {
|
|
85
|
+
return resolve();
|
|
86
|
+
}
|
|
87
|
+
this.socket.end(resolve);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async sendRequest(api, body) {
|
|
91
|
+
const correlationId = this.nextCorrelationId();
|
|
92
|
+
const apiName = (0, api_1.getApiName)(api);
|
|
93
|
+
const encoder = new encoder_1.Encoder()
|
|
94
|
+
.writeInt16(api.apiKey)
|
|
95
|
+
.writeInt16(api.apiVersion)
|
|
96
|
+
.writeInt32(correlationId)
|
|
97
|
+
.writeString(this.options.clientId);
|
|
98
|
+
const request = api.request(encoder, body);
|
|
99
|
+
const requestEncoder = new encoder_1.Encoder().writeInt32(request.getByteLength()).writeEncoder(request);
|
|
100
|
+
let timeout;
|
|
101
|
+
const { responseDecoder, responseSize } = await new Promise(async (resolve, reject) => {
|
|
102
|
+
timeout = setTimeout(() => {
|
|
103
|
+
delete this.queue[correlationId];
|
|
104
|
+
reject(new error_1.ConnectionError(`${apiName} timed out`));
|
|
105
|
+
}, 30_000);
|
|
106
|
+
try {
|
|
107
|
+
this.queue[correlationId] = { resolve, reject };
|
|
108
|
+
await this.write(requestEncoder.value());
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
reject(error);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
clearTimeout(timeout);
|
|
115
|
+
const response = await api.response(responseDecoder);
|
|
116
|
+
(0, assert_1.default)(responseDecoder.getOffset() - 4 === responseSize, `Buffer not correctly consumed: ${responseDecoder.getOffset() - 4} !== ${responseSize}`);
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
write(buffer) {
|
|
120
|
+
return new Promise((resolve, reject) => {
|
|
121
|
+
const { stack } = new Error('Write error');
|
|
122
|
+
this.socket.write(buffer, (error) => {
|
|
123
|
+
if (error) {
|
|
124
|
+
const err = new error_1.ConnectionError(error.message);
|
|
125
|
+
err.stack += `\n${stack}`;
|
|
126
|
+
return reject(err);
|
|
127
|
+
}
|
|
128
|
+
resolve();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
handleData(buffer) {
|
|
133
|
+
this.chunks.push(buffer);
|
|
134
|
+
const decoder = new decoder_1.Decoder(Buffer.concat(this.chunks));
|
|
135
|
+
if (decoder.getBufferLength() < 4) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const size = decoder.readInt32();
|
|
139
|
+
if (size !== decoder.getBufferLength() - 4) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const correlationId = decoder.readInt32();
|
|
143
|
+
const context = this.queue[correlationId];
|
|
144
|
+
if (context) {
|
|
145
|
+
delete this.queue[correlationId];
|
|
146
|
+
context.resolve({ responseDecoder: decoder, responseSize: size });
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
logger_1.log.debug('Could not find pending request for correlationId', { correlationId });
|
|
150
|
+
}
|
|
151
|
+
this.chunks = [];
|
|
152
|
+
}
|
|
153
|
+
nextCorrelationId() {
|
|
154
|
+
return this.lastCorrelationId++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.Connection = Connection;
|
|
158
|
+
__decorate([
|
|
159
|
+
trace(),
|
|
160
|
+
__metadata("design:type", Function),
|
|
161
|
+
__metadata("design:paramtypes", []),
|
|
162
|
+
__metadata("design:returntype", Promise)
|
|
163
|
+
], Connection.prototype, "connect", null);
|
|
164
|
+
__decorate([
|
|
165
|
+
trace(),
|
|
166
|
+
__metadata("design:type", Function),
|
|
167
|
+
__metadata("design:paramtypes", []),
|
|
168
|
+
__metadata("design:returntype", void 0)
|
|
169
|
+
], Connection.prototype, "disconnect", null);
|
|
170
|
+
__decorate([
|
|
171
|
+
trace((api, body) => ({ message: (0, api_1.getApiName)(api), body })),
|
|
172
|
+
__metadata("design:type", Function),
|
|
173
|
+
__metadata("design:paramtypes", [Object, Request]),
|
|
174
|
+
__metadata("design:returntype", Promise)
|
|
175
|
+
], Connection.prototype, "sendRequest", null);
|