kafka-crab-js 1.0.2 → 1.0.3
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 +113 -6
- package/js-binding.d.ts +3 -3
- package/js-binding.js +14 -15
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# 🦀 Kafka Crab JS 🦀
|
|
4
4
|
|
|
5
|
-
A lightweight and
|
|
5
|
+
A lightweight, flexible, and reliable Kafka client for JavaScript/TypeScript. It is built using Rust and librdkafka, providing a high-performance and feature-rich Kafka client.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/kafka-crab-js)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -205,12 +205,124 @@ async function produceWithMetadata() {
|
|
|
205
205
|
}
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
### Reconnecting Kafka Consumer
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
import { KafkaClient } from 'kafka-crab-js'
|
|
212
|
+
|
|
213
|
+
const kafkaClient = new KafkaClient({
|
|
214
|
+
brokers: 'localhost:29092',
|
|
215
|
+
clientId: 'reconnect-test',
|
|
216
|
+
logLevel: 'debug',
|
|
217
|
+
brokerAddressFamily: 'v4',
|
|
218
|
+
configuration: {
|
|
219
|
+
'auto.offset.reset': 'earliest',
|
|
220
|
+
},
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Creates and configures a new Kafka stream consumer
|
|
225
|
+
*/
|
|
226
|
+
async function createConsumer() {
|
|
227
|
+
const kafkaStream = kafkaClient.createStreamConsumer({
|
|
228
|
+
groupId: 'reconnect-test',
|
|
229
|
+
enableAutoCommit: true,
|
|
230
|
+
})
|
|
231
|
+
await kafkaStream.subscribe([
|
|
232
|
+
{ topic: 'foo' },
|
|
233
|
+
{ topic: 'bar' },
|
|
234
|
+
])
|
|
235
|
+
return kafkaStream
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Starts a Kafka consumer with auto-restart capability
|
|
240
|
+
*/
|
|
241
|
+
async function startConsumer() {
|
|
242
|
+
let counter = 0
|
|
243
|
+
let retryCount = 0
|
|
244
|
+
const MAX_RETRIES = 5
|
|
245
|
+
const RETRY_DELAY = 5000 // 5 seconds
|
|
246
|
+
|
|
247
|
+
async function handleRetry() {
|
|
248
|
+
if (retryCount < MAX_RETRIES) {
|
|
249
|
+
retryCount++
|
|
250
|
+
console.log(
|
|
251
|
+
`Attempting to restart consumer (attempt ${retryCount}/${MAX_RETRIES}) in ${RETRY_DELAY / 1000} seconds...`,
|
|
252
|
+
)
|
|
253
|
+
setTimeout(setupConsumerWithRetry, RETRY_DELAY)
|
|
254
|
+
} else {
|
|
255
|
+
console.error(`Maximum retry attempts (${MAX_RETRIES}) reached. Stopping consumer.`)
|
|
256
|
+
process.exit(1)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function setupConsumerWithRetry() {
|
|
261
|
+
try {
|
|
262
|
+
const kafkaStream = await createConsumer()
|
|
263
|
+
retryCount = 0 // Reset retry count on successful connection
|
|
264
|
+
|
|
265
|
+
console.log('Starting consumer')
|
|
266
|
+
|
|
267
|
+
kafkaStream.on('data', (message) => {
|
|
268
|
+
counter++
|
|
269
|
+
console.log('>>> Message received:', {
|
|
270
|
+
counter,
|
|
271
|
+
payload: message.payload.toString(),
|
|
272
|
+
offset: message.offset,
|
|
273
|
+
partition: message.partition,
|
|
274
|
+
topic: message.topic,
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
kafkaStream.on('error', async (error) => {
|
|
279
|
+
console.error('Stream error:', error)
|
|
280
|
+
handleRetry()
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
kafkaStream.on('close', () => {
|
|
284
|
+
console.log('Stream ended')
|
|
285
|
+
try {
|
|
286
|
+
kafkaStream.unsubscribe()
|
|
287
|
+
} catch (unsubError) {
|
|
288
|
+
console.error('Error unsubscribing:', unsubError)
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error('Error setting up consumer:', error)
|
|
293
|
+
handleRetry()
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
await setupConsumerWithRetry()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
await startConsumer()
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Examples
|
|
304
|
+
|
|
305
|
+
You can find some examples on the [example](https://github.com/mthssdrbrg/kafka-crab-js/tree/main/example) folder of this project.
|
|
306
|
+
|
|
208
307
|
## Configuration
|
|
209
308
|
|
|
210
309
|
### Configuration properties
|
|
211
310
|
|
|
311
|
+
### KafkaConfiguration
|
|
312
|
+
|
|
313
|
+
| Property | Type | Default | Description |
|
|
314
|
+
| --- | --- | --- | --- |
|
|
315
|
+
| `brokers` | `string` || List of brokers to connect to |
|
|
316
|
+
| `clientId` | `string` || Client id to use for the connection |
|
|
317
|
+
| `securityProtocol` | `SecurityProtocol` || Security protocol to use (PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL) |
|
|
318
|
+
| `logLevel` | `string` | `info` | Client id to use for the connection |
|
|
319
|
+
| `brokerAddressFamily` | `string` | `"v4"` | Address family to use for the connection (v4, v6) |
|
|
320
|
+
| `configuration` | `Map<string, string>` | `{}` | Additional configuration options for the client. See [librdkafka](https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md) |
|
|
321
|
+
|
|
212
322
|
You can see the available options here: [librdkafka](https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md).
|
|
213
323
|
|
|
324
|
+
|
|
325
|
+
|
|
214
326
|
## Best Practices
|
|
215
327
|
|
|
216
328
|
### Error Handling
|
|
@@ -223,11 +335,6 @@ You can see the available options here: [librdkafka](https://github.com/edenhill
|
|
|
223
335
|
- Configure appropriate batch sizes and compression
|
|
224
336
|
- Monitor and tune consumer group performance
|
|
225
337
|
|
|
226
|
-
### Resource Management
|
|
227
|
-
- Implement proper shutdown procedures
|
|
228
|
-
- Clean up resources (disconnect producers/consumers)
|
|
229
|
-
- Handle process signals (SIGTERM, SIGINT)
|
|
230
|
-
|
|
231
338
|
### Message Processing
|
|
232
339
|
- Validate message formats before processing
|
|
233
340
|
- Implement proper serialization/deserialization
|
package/js-binding.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface RetryStrategy {
|
|
|
13
13
|
}
|
|
14
14
|
export enum CommitMode {
|
|
15
15
|
Sync = 0,
|
|
16
|
-
Async = 1
|
|
16
|
+
Async = 1
|
|
17
17
|
}
|
|
18
18
|
export interface ConsumerConfiguration {
|
|
19
19
|
groupId: string
|
|
@@ -25,7 +25,7 @@ export interface ConsumerConfiguration {
|
|
|
25
25
|
export enum PartitionPosition {
|
|
26
26
|
Beginning = 'Beginning',
|
|
27
27
|
End = 'End',
|
|
28
|
-
Stored = 'Stored'
|
|
28
|
+
Stored = 'Stored'
|
|
29
29
|
}
|
|
30
30
|
export interface OffsetModel {
|
|
31
31
|
offset?: number
|
|
@@ -44,7 +44,7 @@ export enum SecurityProtocol {
|
|
|
44
44
|
Plaintext = 'Plaintext',
|
|
45
45
|
Ssl = 'Ssl',
|
|
46
46
|
SaslPlaintext = 'SaslPlaintext',
|
|
47
|
-
SaslSsl = 'SaslSsl'
|
|
47
|
+
SaslSsl = 'SaslSsl'
|
|
48
48
|
}
|
|
49
49
|
export interface KafkaConfiguration {
|
|
50
50
|
brokers: string
|
package/js-binding.js
CHANGED
|
@@ -63,7 +63,7 @@ switch (platform) {
|
|
|
63
63
|
switch (arch) {
|
|
64
64
|
case 'x64':
|
|
65
65
|
localFileExisted = existsSync(
|
|
66
|
-
join(__dirname, 'kafka-crab-js.win32-x64-msvc.node')
|
|
66
|
+
join(__dirname, 'kafka-crab-js.win32-x64-msvc.node')
|
|
67
67
|
)
|
|
68
68
|
try {
|
|
69
69
|
if (localFileExisted) {
|
|
@@ -77,7 +77,7 @@ switch (platform) {
|
|
|
77
77
|
break
|
|
78
78
|
case 'ia32':
|
|
79
79
|
localFileExisted = existsSync(
|
|
80
|
-
join(__dirname, 'kafka-crab-js.win32-ia32-msvc.node')
|
|
80
|
+
join(__dirname, 'kafka-crab-js.win32-ia32-msvc.node')
|
|
81
81
|
)
|
|
82
82
|
try {
|
|
83
83
|
if (localFileExisted) {
|
|
@@ -91,7 +91,7 @@ switch (platform) {
|
|
|
91
91
|
break
|
|
92
92
|
case 'arm64':
|
|
93
93
|
localFileExisted = existsSync(
|
|
94
|
-
join(__dirname, 'kafka-crab-js.win32-arm64-msvc.node')
|
|
94
|
+
join(__dirname, 'kafka-crab-js.win32-arm64-msvc.node')
|
|
95
95
|
)
|
|
96
96
|
try {
|
|
97
97
|
if (localFileExisted) {
|
|
@@ -132,7 +132,7 @@ switch (platform) {
|
|
|
132
132
|
break
|
|
133
133
|
case 'arm64':
|
|
134
134
|
localFileExisted = existsSync(
|
|
135
|
-
join(__dirname, 'kafka-crab-js.darwin-arm64.node')
|
|
135
|
+
join(__dirname, 'kafka-crab-js.darwin-arm64.node')
|
|
136
136
|
)
|
|
137
137
|
try {
|
|
138
138
|
if (localFileExisted) {
|
|
@@ -168,7 +168,7 @@ switch (platform) {
|
|
|
168
168
|
case 'x64':
|
|
169
169
|
if (isMusl()) {
|
|
170
170
|
localFileExisted = existsSync(
|
|
171
|
-
join(__dirname, 'kafka-crab-js.linux-x64-musl.node')
|
|
171
|
+
join(__dirname, 'kafka-crab-js.linux-x64-musl.node')
|
|
172
172
|
)
|
|
173
173
|
try {
|
|
174
174
|
if (localFileExisted) {
|
|
@@ -181,7 +181,7 @@ switch (platform) {
|
|
|
181
181
|
}
|
|
182
182
|
} else {
|
|
183
183
|
localFileExisted = existsSync(
|
|
184
|
-
join(__dirname, 'kafka-crab-js.linux-x64-gnu.node')
|
|
184
|
+
join(__dirname, 'kafka-crab-js.linux-x64-gnu.node')
|
|
185
185
|
)
|
|
186
186
|
try {
|
|
187
187
|
if (localFileExisted) {
|
|
@@ -197,7 +197,7 @@ switch (platform) {
|
|
|
197
197
|
case 'arm64':
|
|
198
198
|
if (isMusl()) {
|
|
199
199
|
localFileExisted = existsSync(
|
|
200
|
-
join(__dirname, 'kafka-crab-js.linux-arm64-musl.node')
|
|
200
|
+
join(__dirname, 'kafka-crab-js.linux-arm64-musl.node')
|
|
201
201
|
)
|
|
202
202
|
try {
|
|
203
203
|
if (localFileExisted) {
|
|
@@ -210,7 +210,7 @@ switch (platform) {
|
|
|
210
210
|
}
|
|
211
211
|
} else {
|
|
212
212
|
localFileExisted = existsSync(
|
|
213
|
-
join(__dirname, 'kafka-crab-js.linux-arm64-gnu.node')
|
|
213
|
+
join(__dirname, 'kafka-crab-js.linux-arm64-gnu.node')
|
|
214
214
|
)
|
|
215
215
|
try {
|
|
216
216
|
if (localFileExisted) {
|
|
@@ -226,7 +226,7 @@ switch (platform) {
|
|
|
226
226
|
case 'arm':
|
|
227
227
|
if (isMusl()) {
|
|
228
228
|
localFileExisted = existsSync(
|
|
229
|
-
join(__dirname, 'kafka-crab-js.linux-arm-musleabihf.node')
|
|
229
|
+
join(__dirname, 'kafka-crab-js.linux-arm-musleabihf.node')
|
|
230
230
|
)
|
|
231
231
|
try {
|
|
232
232
|
if (localFileExisted) {
|
|
@@ -239,7 +239,7 @@ switch (platform) {
|
|
|
239
239
|
}
|
|
240
240
|
} else {
|
|
241
241
|
localFileExisted = existsSync(
|
|
242
|
-
join(__dirname, 'kafka-crab-js.linux-arm-gnueabihf.node')
|
|
242
|
+
join(__dirname, 'kafka-crab-js.linux-arm-gnueabihf.node')
|
|
243
243
|
)
|
|
244
244
|
try {
|
|
245
245
|
if (localFileExisted) {
|
|
@@ -255,7 +255,7 @@ switch (platform) {
|
|
|
255
255
|
case 'riscv64':
|
|
256
256
|
if (isMusl()) {
|
|
257
257
|
localFileExisted = existsSync(
|
|
258
|
-
join(__dirname, 'kafka-crab-js.linux-riscv64-musl.node')
|
|
258
|
+
join(__dirname, 'kafka-crab-js.linux-riscv64-musl.node')
|
|
259
259
|
)
|
|
260
260
|
try {
|
|
261
261
|
if (localFileExisted) {
|
|
@@ -268,7 +268,7 @@ switch (platform) {
|
|
|
268
268
|
}
|
|
269
269
|
} else {
|
|
270
270
|
localFileExisted = existsSync(
|
|
271
|
-
join(__dirname, 'kafka-crab-js.linux-riscv64-gnu.node')
|
|
271
|
+
join(__dirname, 'kafka-crab-js.linux-riscv64-gnu.node')
|
|
272
272
|
)
|
|
273
273
|
try {
|
|
274
274
|
if (localFileExisted) {
|
|
@@ -283,7 +283,7 @@ switch (platform) {
|
|
|
283
283
|
break
|
|
284
284
|
case 's390x':
|
|
285
285
|
localFileExisted = existsSync(
|
|
286
|
-
join(__dirname, 'kafka-crab-js.linux-s390x-gnu.node')
|
|
286
|
+
join(__dirname, 'kafka-crab-js.linux-s390x-gnu.node')
|
|
287
287
|
)
|
|
288
288
|
try {
|
|
289
289
|
if (localFileExisted) {
|
|
@@ -310,8 +310,7 @@ if (!nativeBinding) {
|
|
|
310
310
|
throw new Error(`Failed to load native binding`)
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
const { KafkaConsumer, CommitMode, PartitionPosition, SecurityProtocol, KafkaClientConfig, KafkaProducer } =
|
|
314
|
-
nativeBinding
|
|
313
|
+
const { KafkaConsumer, CommitMode, PartitionPosition, SecurityProtocol, KafkaClientConfig, KafkaProducer } = nativeBinding
|
|
315
314
|
|
|
316
315
|
module.exports.KafkaConsumer = KafkaConsumer
|
|
317
316
|
module.exports.CommitMode = CommitMode
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kafka-crab-js",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"module": "commonjs",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
},
|
|
68
68
|
"packageManager": "pnpm@9.14.2",
|
|
69
69
|
"optionalDependencies": {
|
|
70
|
-
"kafka-crab-js-darwin-arm64": "1.0.
|
|
71
|
-
"kafka-crab-js-darwin-x64": "1.0.
|
|
72
|
-
"kafka-crab-js-linux-x64-gnu": "1.0.
|
|
70
|
+
"kafka-crab-js-darwin-arm64": "1.0.3",
|
|
71
|
+
"kafka-crab-js-darwin-x64": "1.0.3",
|
|
72
|
+
"kafka-crab-js-linux-x64-gnu": "1.0.3"
|
|
73
73
|
}
|
|
74
74
|
}
|