kafka-crab-js 0.0.3 → 0.0.10

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/Cargo.toml CHANGED
@@ -8,16 +8,24 @@ crate-type = ["cdylib"]
8
8
 
9
9
  [dependencies]
10
10
  # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
11
- napi = { version = "2.13", default-features = false, features = ["napi4", "tokio_rt"] }
11
+ napi = { version = "2.13", default-features = false, features = [
12
+ "napi4",
13
+ "tokio_rt",
14
+ ] }
12
15
  napi-derive = "2.13"
13
16
 
14
- anyhow = { version= "1.0", features = ["backtrace"]}
17
+ anyhow = { version = "1.0", features = ["backtrace"] }
15
18
 
16
- rdkafka = { version = "0.32", features = ["libz-static", "cmake-build", "tokio", "ssl-vendored"] }
19
+ rdkafka = { version = "0.32", features = [
20
+ "libz-static",
21
+ "cmake-build",
22
+ "tokio",
23
+ "ssl-vendored",
24
+ ] }
17
25
  tokio = { version = "1", features = ["full"] }
18
26
 
19
- tracing = "0.1"
20
- tracing-subscriber = "0.3"
27
+ tracing = "0.1"
28
+ tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
21
29
 
22
30
  [build-dependencies]
23
31
  napi-build = "2.0.1"
package/README.md CHANGED
@@ -1,16 +1,77 @@
1
- Kafka Crab Js
2
- -------------
1
+ # Kafka Crab Js
3
2
 
4
3
  **Blazingly Fast Kafka Client for NodeJs**
5
4
 
6
5
  Kafka-Crab-JS is a powerful Node.js library that allows developers to interact with Apache Kafka using Rust programming language, seamlessly integrated with Node.js applications. This documentation provides an overview of the Kafka-Crab-JS library, including installation instructions, usage guidelines, and examples.
7
6
 
7
+ The plugin can be found on [npm](https://www.npmjs.com/package/kafka-crab-js) and the source code is available on [GitHub](https://github.com/inaiat/kafka-crab-js).
8
8
 
9
- # Installation
9
+ ## Table of Contents
10
+ 1. [Installation](#installation)
11
+ 2. [Usage](#usage)
12
+ - [Client](#client)
13
+ - [Producer](#producer)
14
+ - [Consumer](#consumer)
15
+ 3. [Examples](#examples)
10
16
 
11
- To use Kafka-Crab-JS in your Node.js project, follow the steps below:
12
17
 
13
- todo
18
+ ## Installation
19
+ To use Kafka Crab JS, you need to have Node.js and npm (Node Package Manager) installed on your system. Once you have them set up, you can install the plugin by running the following command:
14
20
 
15
- # Examples
16
- todo
21
+ ```shell
22
+ npm install kafka-crab-js
23
+ ```
24
+ ## Usage
25
+ ### Client
26
+ Creating a Client Instance
27
+ Next, you can create a client instance by specifying the Kafka broker(s) and other optional configurations:
28
+
29
+ ```javascript
30
+ import { KafkaClient }
31
+
32
+ const kafkaClient = new KafkaClient({
33
+ brokers: 'localhost:29092',
34
+ clientId: 'my-id'});
35
+ ```
36
+ ### Producer
37
+ The producer component allows you to send messages to Kafka topics.
38
+
39
+ ```javascript
40
+ const result = await producer.send({
41
+ topic: 'my-js-topic',
42
+ key: Buffer.from('abc'),
43
+ value: Buffer.from(`{"name":"Elizeu Drummond","phone":"55219123456"}`),
44
+ headers: {key: Buffer.from('value1')},
45
+ });
46
+ console.log('Message sent with offset:', result);
47
+ ```
48
+
49
+
50
+ ### Consumer
51
+
52
+ **Creating a Consumer Instance**
53
+
54
+ Create a consumer instance by specifying the Kafka broker(s), group ID, and other optional configurations:
55
+
56
+ ```javascript
57
+ const consumer = kafkaClient.createConsumer({
58
+ topic: 'my-js-topic',
59
+ groupId: 'my-js-group',
60
+ retryStrategy: {
61
+ retries: 3,
62
+ },
63
+ });
64
+ ```
65
+
66
+ You can consume messages using the run startConsumer:
67
+
68
+ ```javascript
69
+ consumer.startConsumer(async (error, value) => {
70
+ const message = JSON.parse(value.toString());
71
+ const content = await process_my_message(message);
72
+ return ConsumerResult.Ok;
73
+ });
74
+ ```
75
+ ## Examples
76
+
77
+ You can find examples of using Kafka Crab JS in the [GitHub repository](https://github.com/inaiat/kafka-crab-js).
@@ -3,14 +3,17 @@ import timersPromises from 'node:timers/promises';
3
3
  import {Buffer} from 'node:buffer';
4
4
  import {ConsumerResult, KafkaClient, KafkaCommitMode, PartitionPosition} from '../index.js';
5
5
 
6
- const kafkaClient = new KafkaClient('localhost:29092', 'my-id');
6
+ const kafkaClient = new KafkaClient({
7
+ brokers: 'localhost:29092',
8
+ clientId: 'my-id',
9
+ enableAnsiLogger: false});
7
10
  const topic = 'my-js-topic';
8
11
 
9
12
  let counter = 0;
10
13
 
11
14
  async function process(message) {
12
15
  await timersPromises.setTimeout(1);
13
- return 'message received: ' + message;
16
+ return 'message received: ' + JSON.stringify(message);
14
17
  }
15
18
 
16
19
  const consumer = kafkaClient.createConsumer({
@@ -27,7 +30,7 @@ console.time('consumer');
27
30
 
28
31
  consumer.startConsumer(async (error, value) => {
29
32
  if (error) {
30
- console.error('Consumer error', error);
33
+ console.error('Js Consumer error', error);
31
34
  return;
32
35
  }
33
36
 
@@ -36,19 +39,20 @@ consumer.startConsumer(async (error, value) => {
36
39
  counter++;
37
40
  if (counter >= 0) {
38
41
  console.timeEnd('consumer');
39
- console.log('Counter:', counter, 'Content:', JSON.stringify(content));
42
+ console.log('Js Counter:', counter, 'Content:', JSON.stringify(content));
40
43
  console.time('consumer');
41
44
  }
42
45
 
43
46
  if (message._id === '3') {
44
- console.error('Error on process message, let\'s retry', message);
47
+ console.error('Js Error on process message, let\'s retry', JSON.stringify(content));
45
48
  return ConsumerResult.Retry;
46
49
  }
47
50
 
51
+
48
52
  return ConsumerResult.Ok;
49
53
  });
50
54
 
51
- const producer = kafkaClient.createProducer({topic, configuration: {'message.timeout.ms': '2'}});
55
+ const producer = kafkaClient.createProducer({topic, configuration: {'message.timeout.ms': '5000'}});
52
56
  console.log('Sending message');
53
57
 
54
58
  for (let i = 0; i < 5; i++) {
@@ -61,9 +65,9 @@ for (let i = 0; i < 5; i++) {
61
65
  headers: {key: Buffer.from('value1')},
62
66
  },
63
67
  );
64
- console.log(result);
68
+ console.log("Js message sent. Offset: ", result);
65
69
  await timersPromises.setTimeout(1200);
66
70
  } catch (error) {
67
- console.error('Error on send', error);
71
+ console.error('Js Error on send', error);
68
72
  }
69
73
  }
package/index.d.ts CHANGED
@@ -9,6 +9,13 @@ export const enum SecurityProtocol {
9
9
  SaslPlaintext = 'SaslPlaintext',
10
10
  SaslSsl = 'SaslSsl'
11
11
  }
12
+ export interface KafkaConfiguration {
13
+ brokers: string
14
+ clientId: string
15
+ securityProtocol?: SecurityProtocol
16
+ configuration?: Record<string, string>
17
+ enableAnsiLogger?: boolean
18
+ }
12
19
  export interface ConsumerConfiguration {
13
20
  topic: string
14
21
  groupId: string
@@ -70,20 +77,14 @@ export const enum ConsumerResult {
70
77
  Ok = 'Ok',
71
78
  Retry = 'Retry'
72
79
  }
73
- export class KafkaConfiguration {
74
- brokers: string
75
- clientId: string
76
- securityProtocol?: SecurityProtocol
77
- configuration?: Record<string, string>
78
- }
79
80
  export class KafkaClient {
80
81
  readonly kafkaConfiguration: KafkaConfiguration
81
- constructor(brokers: string, clientId: string, securityProtocol?: SecurityProtocol | undefined | null, configuration?: Record<string, string> | undefined | null)
82
+ constructor(kafkaConfiguration: KafkaConfiguration)
82
83
  createProducer(producerConfiguration: ProducerConfiguration): KafkaProducer
83
84
  createConsumer(consumerConfiguration: ConsumerConfiguration): KafkaConsumer
84
85
  }
85
86
  export class KafkaConsumer {
86
- startConsumer(callback: (err: Error | null, result: Buffer) => Promise<ConsumerResult>): Promise<void>
87
+ startConsumer(callback: (err: Error | null, result: Buffer) => Promise<ConsumerResult | undefined>): Promise<void>
87
88
  }
88
89
  export class KafkaProducer {
89
90
  send(message: MessageModel): Promise<OwnedDelivery>
package/index.js CHANGED
@@ -252,10 +252,9 @@ if (!nativeBinding) {
252
252
  throw new Error(`Failed to load native binding`)
253
253
  }
254
254
 
255
- const { SecurityProtocol, KafkaConfiguration, KafkaClient, KafkaConsumer, KafkaProducer, AutoOffsetReset, KafkaCommitMode, PartitionPosition, ConsumerResult } = nativeBinding
255
+ const { SecurityProtocol, KafkaClient, KafkaConsumer, KafkaProducer, AutoOffsetReset, KafkaCommitMode, PartitionPosition, ConsumerResult } = nativeBinding
256
256
 
257
257
  module.exports.SecurityProtocol = SecurityProtocol
258
- module.exports.KafkaConfiguration = KafkaConfiguration
259
258
  module.exports.KafkaClient = KafkaClient
260
259
  module.exports.KafkaConsumer = KafkaConsumer
261
260
  module.exports.KafkaProducer = KafkaProducer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kafka-crab-js",
3
- "version": "0.0.3",
3
+ "version": "0.0.10",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "napi": {
@@ -15,6 +15,15 @@
15
15
  }
16
16
  },
17
17
  "license": "MIT",
18
+ "keywords": [
19
+ "kafka",
20
+ "napi-rs",
21
+ "librdkafka",
22
+ "typescript",
23
+ "rust"
24
+ ],
25
+ "author": "inaiat@gmail.com",
26
+ "homepage": "https://github.com/inaiat/kafka-crab-js.git",
18
27
  "devDependencies": {
19
28
  "@napi-rs/cli": "^2.16.1",
20
29
  "ava": "^5.3.1",
@@ -41,8 +50,8 @@
41
50
  },
42
51
  "packageManager": "yarn@3.6.0",
43
52
  "optionalDependencies": {
44
- "kafka-crab-js-darwin-arm64": "0.0.3",
45
- "kafka-crab-js-darwin-x64": "0.0.3",
46
- "kafka-crab-js-linux-x64-gnu": "0.0.3"
53
+ "kafka-crab-js-darwin-arm64": "0.0.10",
54
+ "kafka-crab-js-darwin-x64": "0.0.10",
55
+ "kafka-crab-js-linux-x64-gnu": "0.0.10"
47
56
  }
48
57
  }
@@ -55,12 +55,13 @@ impl fmt::Display for SecurityProtocol {
55
55
  }
56
56
 
57
57
  #[derive(Clone, Debug)]
58
- #[napi]
58
+ #[napi(object)]
59
59
  pub struct KafkaConfiguration {
60
60
  pub brokers: String,
61
61
  pub client_id: String,
62
62
  pub security_protocol: Option<SecurityProtocol>,
63
63
  pub configuration: Option<HashMap<String, String>>,
64
+ pub enable_ansi_logger: Option<bool>,
64
65
  }
65
66
 
66
67
  #[derive(Clone, Debug)]
@@ -74,23 +75,18 @@ pub struct KafkaClient {
74
75
  #[napi]
75
76
  impl KafkaClient {
76
77
  #[napi(constructor)]
77
- pub fn new(
78
- brokers: String,
79
- client_id: String,
80
- security_protocol: Option<SecurityProtocol>,
81
- configuration: Option<HashMap<String, String>>,
82
- ) -> Self {
83
- match tracing_subscriber::fmt::try_init() {
78
+ pub fn new(kafka_configuration: KafkaConfiguration) -> Self {
79
+ match tracing_subscriber::fmt()
80
+ .with_ansi(kafka_configuration.enable_ansi_logger.unwrap_or(false))
81
+ .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
82
+ .try_init()
83
+ {
84
84
  Ok(_) => {}
85
- Err(e) => println!("Failed to initialize tracing: {:?}", e),
86
- }
87
-
88
- KafkaClient::with_kafka_configuration(KafkaConfiguration {
89
- brokers,
90
- client_id,
91
- security_protocol,
92
- configuration,
93
- })
85
+ Err(e) => {
86
+ eprintln!("Failed to initialize tracing: {:?}", e);
87
+ }
88
+ };
89
+ KafkaClient::with_kafka_configuration(kafka_configuration)
94
90
  }
95
91
 
96
92
  pub fn get_client_config(&self) -> &ClientConfig {
@@ -103,11 +99,12 @@ impl KafkaClient {
103
99
  security_protocol,
104
100
  client_id,
105
101
  configuration,
102
+ ..
106
103
  } = kafka_configuration.clone();
107
104
 
108
105
  let mut rdkafka_client_config = ClientConfig::new();
109
106
 
110
- rdkafka_client_config.set_log_level(RDKafkaLogLevel::Info);
107
+ rdkafka_client_config.set_log_level(RDKafkaLogLevel::Debug);
111
108
  rdkafka_client_config.set("bootstrap.servers", brokers);
112
109
  rdkafka_client_config.set("client.id", client_id);
113
110
  if let Some(security_protocol) = security_protocol {
@@ -92,7 +92,9 @@ impl KafkaConsumer {
92
92
  })
93
93
  }
94
94
 
95
- #[napi(ts_args_type = "callback: (err: Error | null, result: Buffer) => Promise<ConsumerResult>")]
95
+ #[napi(
96
+ ts_args_type = "callback: (err: Error | null, result: Buffer) => Promise<ConsumerResult | undefined>"
97
+ )]
96
98
  pub async fn start_consumer(&self, func: ThreadsafeFunction<Buffer>) -> Result<()> {
97
99
  let ConsumerConfiguration {
98
100
  commit_mode,
@@ -304,22 +306,22 @@ async fn process_message(
304
306
  match message.payload_view::<[u8]>() {
305
307
  None => Ok(None),
306
308
  Some(Ok(payload)) => match func
307
- .call_async::<Promise<ConsumerResult>>(Ok(payload.into()))
309
+ .call_async::<Promise<Option<ConsumerResult>>>(Ok(payload.into()))
308
310
  .await
309
311
  {
310
312
  Ok(js_result) => match js_result.await {
311
313
  Ok(value) => match value {
312
- ConsumerResult::Ok => {
314
+ None | Some(ConsumerResult::Ok) => {
313
315
  if let Some(commit_mode) = commit_mode {
314
316
  match stream_consumer.commit_message(message, *commit_mode) {
315
- Ok(_) => Ok(Some(value)),
317
+ Ok(_) => Ok(Some(ConsumerResult::Ok)),
316
318
  Err(e) => Err(anyhow::Error::new(e)),
317
319
  }
318
320
  } else {
319
- Ok(Some(value))
321
+ Ok(Some(ConsumerResult::Ok))
320
322
  }
321
323
  }
322
- ConsumerResult::Retry => Ok(Some(value)),
324
+ Some(ConsumerResult::Retry) => Ok(Some(ConsumerResult::Retry)),
323
325
  },
324
326
  Err(e) => Err(anyhow::Error::new(e)),
325
327
  },