kafka-crab-js 0.6.0 → 0.7.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.
@@ -23,7 +23,7 @@ async function produce(topic, messages=1) {
23
23
  const result = await producer.send(
24
24
  {
25
25
  topic,
26
- messages: [{ value: Buffer.from(`{"_id":"${i}","name":"${fakerPT_BR.person.fullName()}","phone":"${fakerPT_BR.phone.number()}"}`) }],
26
+ messages: [{ payload: Buffer.from(`{"_id":"${i}","name":"${fakerPT_BR.person.fullName()}","phone":"${fakerPT_BR.phone.number()}"}`) }],
27
27
  },
28
28
  );
29
29
  console.log('Js message sent. Offset:', result);
@@ -82,11 +82,15 @@ async function startConsumer() {
82
82
  counter++;
83
83
  console.log('>>> Message received:', { payload: message.payload.toString(), offset: message.offset, partition: message.partition, topic: message.topic })
84
84
  if (counter === maxMessages) {
85
- kafkaStreamConsumer.unsubscribe();
86
85
  kafkaStream.destroy();
87
86
  }
88
87
  // streamerConsumer.commit(message.partition, message.offset+1, CommitMode.Sync)
89
88
  })
89
+
90
+ kafkaStream.on('close', () => {
91
+ kafkaStreamConsumer.unsubscribe();
92
+ console.log('Stream ended')
93
+ })
90
94
  }
91
95
 
92
96
  if (process.argv[2] === 'send') {
package/index.d.ts CHANGED
@@ -27,8 +27,8 @@ export interface RetryStrategy {
27
27
  configuration?: Record<string, string>
28
28
  }
29
29
  export const enum CommitMode {
30
- Sync = 'Sync',
31
- Async = 'Async'
30
+ Sync = 0,
31
+ Async = 1
32
32
  }
33
33
  export interface ConsumerConfiguration {
34
34
  groupId: string
@@ -37,29 +37,6 @@ export interface ConsumerConfiguration {
37
37
  configuration?: Record<string, string>
38
38
  fecthMetadataTimeout?: number
39
39
  }
40
- export const enum SecurityProtocol {
41
- Plaintext = 'Plaintext',
42
- Ssl = 'Ssl',
43
- SaslPlaintext = 'SaslPlaintext',
44
- SaslSsl = 'SaslSsl'
45
- }
46
- export interface KafkaConfiguration {
47
- brokers: string
48
- clientId: string
49
- securityProtocol?: SecurityProtocol
50
- configuration?: Record<string, string>
51
- logLevel?: string
52
- brokerAddressFamily?: string
53
- }
54
- export const enum AutoOffsetReset {
55
- Smallest = 'Smallest',
56
- Earliest = 'Earliest',
57
- Beginning = 'Beginning',
58
- Largest = 'Largest',
59
- Latest = 'Latest',
60
- End = 'End',
61
- Error = 'Error'
62
- }
63
40
  export const enum PartitionPosition {
64
41
  Beginning = 'Beginning',
65
42
  End = 'End',
@@ -78,26 +55,25 @@ export interface TopicPartitionConfig {
78
55
  allOffsets?: OffsetModel
79
56
  partitionOffset?: Array<PartitionOffset>
80
57
  }
81
- export interface RecordMetadata {
82
- topic: string
83
- partition: number
84
- offset: number
85
- error?: KafkaCrabError
58
+ export const enum SecurityProtocol {
59
+ Plaintext = 'Plaintext',
60
+ Ssl = 'Ssl',
61
+ SaslPlaintext = 'SaslPlaintext',
62
+ SaslSsl = 'SaslSsl'
86
63
  }
87
- export interface MessageProducer {
88
- value: Buffer
89
- key?: Buffer
90
- headers?: Record<string, Buffer>
64
+ export interface KafkaConfiguration {
65
+ brokers: string
66
+ clientId: string
67
+ securityProtocol?: SecurityProtocol
68
+ configuration?: Record<string, string>
69
+ logLevel?: string
70
+ brokerAddressFamily?: string
91
71
  }
92
72
  export interface ProducerConfiguration {
93
73
  queueTimeout?: number
94
74
  thrownOnError?: boolean
95
75
  configuration?: Record<string, string>
96
76
  }
97
- export interface ProducerRecord {
98
- topic: string
99
- messages: Array<MessageProducer>
100
- }
101
77
  export interface Payload {
102
78
  value: Buffer
103
79
  key?: Buffer
@@ -114,6 +90,21 @@ export interface Message {
114
90
  partition: number
115
91
  offset: number
116
92
  }
93
+ export interface RecordMetadata {
94
+ topic: string
95
+ partition: number
96
+ offset: number
97
+ error?: KafkaCrabError
98
+ }
99
+ export interface MessageProducer {
100
+ payload: Buffer
101
+ key?: Buffer
102
+ headers?: Record<string, Buffer>
103
+ }
104
+ export interface ProducerRecord {
105
+ topic: string
106
+ messages: Array<MessageProducer>
107
+ }
117
108
  export interface KafkaCrabError {
118
109
  code: number
119
110
  message: string
package/index.js CHANGED
@@ -310,14 +310,13 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { ConsumerResult, KafkaConsumer, KafkaStreamConsumer, CommitMode, SecurityProtocol, KafkaClient, AutoOffsetReset, PartitionPosition, KafkaProducer } = nativeBinding
313
+ const { ConsumerResult, KafkaConsumer, KafkaStreamConsumer, CommitMode, PartitionPosition, SecurityProtocol, KafkaClient, KafkaProducer } = nativeBinding
314
314
 
315
315
  module.exports.ConsumerResult = ConsumerResult
316
316
  module.exports.KafkaConsumer = KafkaConsumer
317
317
  module.exports.KafkaStreamConsumer = KafkaStreamConsumer
318
318
  module.exports.CommitMode = CommitMode
319
+ module.exports.PartitionPosition = PartitionPosition
319
320
  module.exports.SecurityProtocol = SecurityProtocol
320
321
  module.exports.KafkaClient = KafkaClient
321
- module.exports.AutoOffsetReset = AutoOffsetReset
322
- module.exports.PartitionPosition = PartitionPosition
323
322
  module.exports.KafkaProducer = KafkaProducer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kafka-crab-js",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "napi": {
@@ -61,8 +61,8 @@
61
61
  },
62
62
  "packageManager": "pnpm@9.1.1",
63
63
  "optionalDependencies": {
64
- "kafka-crab-js-darwin-arm64": "0.6.0",
65
- "kafka-crab-js-darwin-x64": "0.6.0",
66
- "kafka-crab-js-linux-x64-gnu": "0.6.0"
64
+ "kafka-crab-js-darwin-arm64": "0.7.0",
65
+ "kafka-crab-js-darwin-x64": "0.7.0",
66
+ "kafka-crab-js-linux-x64-gnu": "0.7.0"
67
67
  }
68
68
  }
@@ -3,18 +3,27 @@ use std::{collections::HashMap, time::Duration};
3
3
  use rdkafka::{
4
4
  config::RDKafkaLogLevel,
5
5
  consumer::{Consumer, StreamConsumer},
6
- ClientConfig, TopicPartitionList,
6
+ ClientConfig, Offset, TopicPartitionList,
7
7
  };
8
8
  use tracing::{debug, error, info, warn};
9
9
 
10
- use crate::kafka::{
11
- consumer::model::LoggingConsumer,
12
- kafka_admin::KafkaAdmin,
13
- kafka_util::convert_to_rdkafka_offset,
14
- model::{OffsetModel, PartitionOffset},
10
+ use crate::kafka::{consumer::model::LoggingConsumer, kafka_admin::KafkaAdmin};
11
+
12
+ use super::model::{
13
+ ConsumerConfiguration, CustomContext, OffsetModel, PartitionOffset, PartitionPosition,
15
14
  };
16
15
 
17
- use super::{model::ConsumerConfiguration, model::CustomContext};
16
+ pub fn convert_to_rdkafka_offset(offset_model: &OffsetModel) -> Offset {
17
+ match offset_model.position {
18
+ Some(PartitionPosition::Beginning) => Offset::Beginning,
19
+ Some(PartitionPosition::End) => Offset::End,
20
+ Some(PartitionPosition::Stored) => Offset::Stored,
21
+ None => match offset_model.offset {
22
+ Some(value) => Offset::Offset(value),
23
+ None => Offset::Stored, // Default to stored
24
+ },
25
+ }
26
+ }
18
27
 
19
28
  pub async fn create_stream_consumer_and_setup_everything(
20
29
  client_config: &ClientConfig,
@@ -27,14 +36,14 @@ pub async fn create_stream_consumer_and_setup_everything(
27
36
  let consumer = create_stream_consumer(client_config, consumer_configuration, configuration)?;
28
37
 
29
38
  if consumer_configuration.create_topic.unwrap_or(true) {
30
- try_create_topic(topic, client_config).await?;
39
+ try_create_topic(&vec![topic.to_owned()], client_config, timeout).await?;
31
40
  }
32
41
 
33
42
  if let Some(offset_model) = offset {
34
43
  set_offset_of_all_partitions(offset_model, &consumer, topic, timeout)?;
35
44
  }
36
45
 
37
- try_subscribe(&consumer, topic)?;
46
+ try_subscribe(&consumer, &vec![topic.to_owned()])?;
38
47
 
39
48
  Ok(consumer)
40
49
  }
@@ -77,28 +86,30 @@ pub fn create_stream_consumer(
77
86
  Ok(consumer)
78
87
  }
79
88
 
80
- pub fn try_subscribe(consumer: &LoggingConsumer, topic: &str) -> anyhow::Result<()> {
81
- consumer
82
- .subscribe(vec![&*topic.to_string()].as_slice())
83
- .map_err(|e| {
84
- anyhow::Error::msg(format!(
85
- "Can't subscribe to specified topics. Error: {:?}",
86
- e
87
- ))
88
- })?;
89
- debug!("Subscribed to topic: {:?}", topic);
89
+ pub fn try_subscribe(consumer: &LoggingConsumer, topics: &Vec<String>) -> anyhow::Result<()> {
90
+ let topics_ref = topics.iter().map(|x| x.as_str()).collect::<Vec<&str>>();
91
+ consumer.subscribe(topics_ref.as_slice()).map_err(|e| {
92
+ anyhow::Error::msg(format!(
93
+ "Can't subscribe to specified topic(s): {:?}. Error: {:?}",
94
+ topics_ref, e
95
+ ))
96
+ })?;
97
+ debug!("Subscribed to topic(s): {:?}", topics_ref);
90
98
  Ok(())
91
99
  }
92
100
 
93
- pub async fn try_create_topic(topic: &str, client_config: &ClientConfig) -> anyhow::Result<()> {
94
- info!("Creating topic: {:?}", topic);
95
- let admin = KafkaAdmin::new(client_config, None);
96
- let result = admin.create_topic(topic).await;
101
+ pub async fn try_create_topic(
102
+ topics: &Vec<String>,
103
+ client_config: &ClientConfig,
104
+ fetch_metadata_timeout: Duration,
105
+ ) -> anyhow::Result<()> {
106
+ let admin = KafkaAdmin::new(client_config, Some(fetch_metadata_timeout));
107
+ let result = admin.create_topic(topics).await;
97
108
  if let Err(e) = result {
98
109
  warn!("Fail to create topic {:?}", e);
99
110
  return Err(anyhow::Error::msg(format!("Fail to create topic: {:?}", e)));
100
111
  }
101
- info!("Topic created: {:?}", topic);
112
+ info!("Topic(s) created: {:?}", topics);
102
113
  Ok(())
103
114
  }
104
115
 
@@ -12,7 +12,9 @@ use tracing::{debug, error, info, warn};
12
12
 
13
13
  use crate::kafka::{
14
14
  consumer::kafka_consumer::RETRY_COUNTER_NAME,
15
- kafka_util::{create_payload, kakfa_headers_to_hashmap, ExtractValueOnKafkaHashMap},
15
+ kafka_util::{
16
+ kakfa_headers_to_hashmap, kakfa_headers_to_hashmap_buffer, ExtractValueOnKafkaHashMap,
17
+ },
16
18
  producer::model::Payload,
17
19
  };
18
20
 
@@ -179,3 +181,17 @@ impl ConsumerThread {
179
181
  }
180
182
  }
181
183
  }
184
+
185
+ pub fn create_payload(message: &BorrowedMessage<'_>, payload: &[u8]) -> Payload {
186
+ let key: Option<Buffer> = message.key().map(|bytes| bytes.into());
187
+ let headers = Some(kakfa_headers_to_hashmap_buffer(message.headers()));
188
+ let payload_js = Payload::new(
189
+ payload.into(),
190
+ key,
191
+ headers,
192
+ message.topic().to_owned(),
193
+ message.partition(),
194
+ message.offset(),
195
+ );
196
+ payload_js
197
+ }
@@ -5,16 +5,16 @@ use rdkafka::{consumer::CommitMode as RdKfafkaCommitMode, producer::FutureProduc
5
5
  use std::{collections::HashMap, time::Duration};
6
6
 
7
7
  use crate::kafka::{
8
- kafka_client::KafkaClient,
9
- kafka_util::AnyhowToNapiError,
10
- model::{OffsetModel, PartitionPosition},
11
- producer::model::Payload,
8
+ kafka_client::KafkaClient, kafka_util::AnyhowToNapiError, producer::model::Payload,
12
9
  };
13
10
 
14
11
  use super::{
15
12
  consumer_helper::create_stream_consumer_and_setup_everything,
16
13
  consumer_thread::ConsumerThread,
17
- model::{CommitMode, ConsumerConfiguration, RetryStrategy, DEFAULT_FECTH_METADATA_TIMEOUT},
14
+ model::{
15
+ CommitMode, ConsumerConfiguration, OffsetModel, PartitionPosition, RetryStrategy,
16
+ DEFAULT_FECTH_METADATA_TIMEOUT,
17
+ },
18
18
  };
19
19
 
20
20
  pub const RETRY_COUNTER_NAME: &str = "kafka-crab-js-retry-counter";
@@ -103,7 +103,7 @@ impl KafkaConsumer {
103
103
  commit_mode,
104
104
  topic,
105
105
  fetch_metadata_timeout: Duration::from_millis(
106
- fecth_metadata_timeout.unwrap_or(DEFAULT_FECTH_METADATA_TIMEOUT) as u64,
106
+ fecth_metadata_timeout.unwrap_or(DEFAULT_FECTH_METADATA_TIMEOUT.as_millis() as i64) as u64,
107
107
  ),
108
108
  })
109
109
  }
@@ -229,6 +229,6 @@ fn convert_to_consumer_configuration(config: &KafkaConsumerConfiguration) -> Con
229
229
  create_topic: config.create_topic,
230
230
  enable_auto_commit: config.enable_auto_commit,
231
231
  configuration: config.configuration.clone(),
232
- fecth_metadata_timeout: Some(DEFAULT_FECTH_METADATA_TIMEOUT),
232
+ fecth_metadata_timeout: config.fecth_metadata_timeout,
233
233
  }
234
234
  }
@@ -11,16 +11,20 @@ use rdkafka::{
11
11
  use tracing::{debug, error, info};
12
12
 
13
13
  use crate::kafka::{
14
- consumer::consumer_helper::{assign_offset_or_use_metadata, try_create_topic},
14
+ consumer::consumer_helper::{
15
+ assign_offset_or_use_metadata, convert_to_rdkafka_offset, try_create_topic, try_subscribe,
16
+ },
15
17
  kafka_client::KafkaClient,
16
- kafka_util::{convert_to_rdkafka_offset, create_message, AnyhowToNapiError},
17
- model::{OffsetModel, TopicPartitionConfig},
18
+ kafka_util::{create_message, AnyhowToNapiError},
18
19
  producer::model::Message,
19
20
  };
20
21
 
21
22
  use super::{
22
23
  consumer_helper::{create_stream_consumer, set_offset_of_all_partitions},
23
- model::{CommitMode, ConsumerConfiguration, CustomContext, DEFAULT_FECTH_METADATA_TIMEOUT},
24
+ model::{
25
+ CommitMode, ConsumerConfiguration, CustomContext, OffsetModel, TopicPartitionConfig,
26
+ DEFAULT_FECTH_METADATA_TIMEOUT,
27
+ },
24
28
  };
25
29
 
26
30
  pub const DEFAULT_SEEK_TIMEOUT: i64 = 1500;
@@ -51,7 +55,7 @@ impl KafkaStreamConsumer {
51
55
  fecth_metadata_timeout: Duration::from_millis(
52
56
  consumer_configuration
53
57
  .fecth_metadata_timeout
54
- .unwrap_or(DEFAULT_FECTH_METADATA_TIMEOUT) as u64,
58
+ .unwrap_or(DEFAULT_FECTH_METADATA_TIMEOUT.as_millis() as i64) as u64,
55
59
  ),
56
60
  })
57
61
  }
@@ -63,7 +67,7 @@ impl KafkaStreamConsumer {
63
67
  ) -> Result<()> {
64
68
  let topics = match topic_configs {
65
69
  Either::A(config) => {
66
- info!("1.Subscribing to topic: {:#?}", &config);
70
+ debug!("Subscribing to topic: {:#?}", &config);
67
71
  vec![TopicPartitionConfig {
68
72
  topic: config,
69
73
  all_offsets: None,
@@ -71,7 +75,7 @@ impl KafkaStreamConsumer {
71
75
  }]
72
76
  }
73
77
  Either::B(config) => {
74
- info!("2.Subscribing to topics: {:#?}", &config);
78
+ debug!("Subscribing to topic config: {:#?}", &config);
75
79
  config
76
80
  }
77
81
  };
@@ -80,28 +84,17 @@ impl KafkaStreamConsumer {
80
84
  .iter()
81
85
  .map(|x| x.topic.clone())
82
86
  .collect::<Vec<String>>();
83
- let topics_ref = topics_name
84
- .iter()
85
- .map(|x| x.as_str())
86
- .collect::<Vec<&str>>();
87
87
 
88
- info!("Creating topics if not exists: {:?}", &topics_ref);
89
- for topic in &topics_ref {
90
- try_create_topic(&topic, &self.client_config)
91
- .await
92
- .map_err(|e| e.convert_to_napi())?;
93
- }
88
+ debug!("Creating topics if not exists: {:?}", &topics_name);
89
+ try_create_topic(
90
+ &topics_name,
91
+ &self.client_config,
92
+ self.fecth_metadata_timeout,
93
+ )
94
+ .await
95
+ .map_err(|e| e.convert_to_napi())?;
94
96
 
95
- info!("Subscribing to topics: {:?}", topics_name);
96
- self
97
- .stream_consumer
98
- .subscribe(&topics_ref.as_slice())
99
- .map_err(|e| {
100
- napi::Error::new(
101
- napi::Status::GenericFailure,
102
- format!("Error while subscribing to topic: {:?}", e),
103
- )
104
- })?;
97
+ try_subscribe(&self.stream_consumer, &topics_name).map_err(|e| e.convert_to_napi())?;
105
98
 
106
99
  topics.iter().for_each(|item| {
107
100
  if let Some(all_offsets) = item.all_offsets.clone() {
@@ -1,4 +1,4 @@
1
- use std::collections::HashMap;
1
+ use std::{collections::HashMap, time::Duration};
2
2
 
3
3
  use rdkafka::{
4
4
  consumer::{ConsumerContext, Rebalance, StreamConsumer},
@@ -7,12 +7,10 @@ use rdkafka::{
7
7
  };
8
8
  use tracing::info;
9
9
 
10
- use crate::kafka::model::OffsetModel;
10
+ pub const DEFAULT_FECTH_METADATA_TIMEOUT: Duration = Duration::from_millis(2000);
11
11
 
12
12
  pub type LoggingConsumer = StreamConsumer<CustomContext>;
13
13
 
14
- pub const DEFAULT_FECTH_METADATA_TIMEOUT: i64 = 2000;
15
-
16
14
  pub struct CustomContext;
17
15
 
18
16
  impl ClientContext for CustomContext {}
@@ -42,11 +40,11 @@ pub struct RetryStrategy {
42
40
  pub configuration: Option<HashMap<String, String>>,
43
41
  }
44
42
 
45
- #[napi(string_enum)]
43
+ #[napi]
46
44
  #[derive(Debug, PartialEq)]
47
45
  pub enum CommitMode {
48
- Sync,
49
- Async,
46
+ Sync = 0,
47
+ Async = 1,
50
48
  }
51
49
 
52
50
  #[napi(object)]
@@ -58,3 +56,32 @@ pub struct ConsumerConfiguration {
58
56
  pub configuration: Option<HashMap<String, String>>,
59
57
  pub fecth_metadata_timeout: Option<i64>,
60
58
  }
59
+
60
+ #[napi(string_enum)]
61
+ #[derive(Debug)]
62
+ pub enum PartitionPosition {
63
+ Beginning,
64
+ End,
65
+ Stored,
66
+ }
67
+ #[napi(object)]
68
+ #[derive(Clone, Debug)]
69
+ pub struct OffsetModel {
70
+ pub offset: Option<i64>,
71
+ pub position: Option<PartitionPosition>,
72
+ }
73
+
74
+ #[napi(object)]
75
+ #[derive(Clone, Debug)]
76
+ pub struct PartitionOffset {
77
+ pub partition: i32,
78
+ pub offset: OffsetModel,
79
+ }
80
+
81
+ #[napi(object)]
82
+ #[derive(Clone, Debug)]
83
+ pub struct TopicPartitionConfig {
84
+ pub topic: String,
85
+ pub all_offsets: Option<OffsetModel>,
86
+ pub partition_offset: Option<Vec<PartitionOffset>>,
87
+ }
@@ -12,7 +12,7 @@ use tracing::{debug, info, trace};
12
12
 
13
13
  use std::{collections::HashMap, str::FromStr, time::Duration};
14
14
 
15
- use super::consumer::model::DEFAULT_FECTH_METADATA_TIMEOUT;
15
+ const DEFAULT_FECTH_METADATA_TIMEOUT: Duration = Duration::from_millis(2000);
16
16
 
17
17
  const DEFAULT_NUM_PARTITIONS: i32 = 3;
18
18
  const DEFAULT_REPLICATION: i32 = 3;
@@ -24,7 +24,7 @@ pub struct KafkaAdmin<'a> {
24
24
  }
25
25
 
26
26
  impl<'a> KafkaAdmin<'a> {
27
- pub fn new(client_config: &'a ClientConfig, fetch_metadata_timeout: Option<i64>) -> Self {
27
+ pub fn new(client_config: &'a ClientConfig, fetch_metadata_timeout: Option<Duration>) -> Self {
28
28
  let admin_client: AdminClient<DefaultClientContext> = client_config
29
29
  .create()
30
30
  .expect("admin client creation failed");
@@ -32,9 +32,7 @@ impl<'a> KafkaAdmin<'a> {
32
32
  KafkaAdmin {
33
33
  client_config,
34
34
  admin_client,
35
- fetch_metadata_timeout: Duration::from_millis(
36
- fetch_metadata_timeout.unwrap_or(DEFAULT_FECTH_METADATA_TIMEOUT) as u64,
37
- ),
35
+ fetch_metadata_timeout: fetch_metadata_timeout.unwrap_or(DEFAULT_FECTH_METADATA_TIMEOUT),
38
36
  }
39
37
  }
40
38
 
@@ -63,31 +61,33 @@ impl<'a> KafkaAdmin<'a> {
63
61
  Ok(extract_config_resource(config_resource))
64
62
  }
65
63
 
66
- pub async fn create_topic(&self, topic_name: &str) -> anyhow::Result<()> {
64
+ pub async fn create_topic(&self, topics: &Vec<String>) -> anyhow::Result<()> {
67
65
  let broker_properties = self.fetch_config_resource().await?.clone();
68
66
  trace!("Broker properties: {:?}", broker_properties);
69
67
 
68
+ let new_topics: Vec<NewTopic> = topics
69
+ .iter()
70
+ .map(|topic| NewTopic {
71
+ name: topic,
72
+ num_partitions: broker_properties
73
+ .get("num.partitions")
74
+ .get_parsed_or_default_value(DEFAULT_NUM_PARTITIONS),
75
+ replication: TopicReplication::Fixed(
76
+ broker_properties
77
+ .get("default.replication.factor")
78
+ .get_parsed_or_default_value(DEFAULT_REPLICATION),
79
+ ),
80
+ config: vec![],
81
+ })
82
+ .collect();
83
+
70
84
  self
71
85
  .admin_client
72
- .create_topics(
73
- &[NewTopic {
74
- name: topic_name,
75
- num_partitions: broker_properties
76
- .get("num.partitions")
77
- .get_parsed_or_default_value(DEFAULT_NUM_PARTITIONS),
78
- replication: TopicReplication::Fixed(
79
- broker_properties
80
- .get("default.replication.factor")
81
- .get_parsed_or_default_value(DEFAULT_REPLICATION),
82
- ),
83
- config: vec![],
84
- }],
85
- &AdminOptions::default(),
86
- )
86
+ .create_topics(&new_topics, &AdminOptions::default())
87
87
  .await
88
88
  .map_err(anyhow::Error::new)?;
89
89
 
90
- info!("Topic {} was created successfully", topic_name);
90
+ info!("Topic(s) {:?} was created successfully", topics);
91
91
  Ok(())
92
92
  }
93
93
  }
@@ -1,15 +1,9 @@
1
1
  use std::{collections::HashMap, fmt, str::FromStr};
2
2
 
3
3
  use napi::{bindgen_prelude::*, Result};
4
- use rdkafka::{
5
- client::ClientContext,
6
- config::{ClientConfig, RDKafkaLogLevel},
7
- consumer::{ConsumerContext, Rebalance},
8
- error::KafkaResult,
9
- topic_partition_list::TopicPartitionList,
10
- };
4
+ use rdkafka::config::{ClientConfig, RDKafkaLogLevel};
11
5
 
12
- use tracing::{info, Level};
6
+ use tracing::Level;
13
7
 
14
8
  use super::{
15
9
  consumer::{
@@ -20,24 +14,6 @@ use super::{
20
14
  producer::kafka_producer::{KafkaProducer, ProducerConfiguration},
21
15
  };
22
16
 
23
- struct CustomContext;
24
-
25
- impl ClientContext for CustomContext {}
26
-
27
- impl ConsumerContext for CustomContext {
28
- fn pre_rebalance(&self, rebalance: &Rebalance) {
29
- info!("Pre rebalance {:?}", rebalance);
30
- }
31
-
32
- fn post_rebalance(&self, rebalance: &Rebalance) {
33
- info!("Post rebalance {:?}", rebalance);
34
- }
35
-
36
- fn commit_callback(&self, result: KafkaResult<()>, _offsets: &TopicPartitionList) {
37
- info!("Committing offsets: {:?}. Offset: {:?}", result, _offsets);
38
- }
39
- }
40
-
41
17
  #[derive(Debug)]
42
18
  #[napi(string_enum)]
43
19
  pub enum SecurityProtocol {
@@ -3,13 +3,10 @@ use std::collections::HashMap;
3
3
  use napi::{bindgen_prelude::Buffer, Status};
4
4
  use rdkafka::{
5
5
  message::{BorrowedHeaders, BorrowedMessage, Header, Headers, OwnedHeaders},
6
- Message as RdMessage, Offset,
6
+ Message as RdMessage,
7
7
  };
8
8
 
9
- use super::{
10
- model::{OffsetModel, PartitionPosition},
11
- producer::model::{Message, Payload},
12
- };
9
+ use super::producer::model::Message;
13
10
 
14
11
  pub trait AnyhowToNapiError {
15
12
  fn convert_to_napi(&self) -> napi::Error;
@@ -21,18 +18,6 @@ impl AnyhowToNapiError for anyhow::Error {
21
18
  }
22
19
  }
23
20
 
24
- pub fn convert_to_rdkafka_offset(offset_model: &OffsetModel) -> Offset {
25
- match offset_model.position {
26
- Some(PartitionPosition::Beginning) => Offset::Beginning,
27
- Some(PartitionPosition::End) => Offset::End,
28
- Some(PartitionPosition::Stored) => Offset::Stored,
29
- None => match offset_model.offset {
30
- Some(value) => Offset::Offset(value),
31
- None => Offset::Stored, // Default to stored
32
- },
33
- }
34
- }
35
-
36
21
  pub fn hashmap_to_kafka_headers(map: &HashMap<String, Buffer>) -> OwnedHeaders {
37
22
  map.iter().fold(OwnedHeaders::new(), |acc, (key, value)| {
38
23
  let value: &[u8] = value.as_ref();
@@ -89,20 +74,6 @@ impl ExtractValueOnKafkaHashMap<usize> for HashMap<&str, &[u8]> {
89
74
  }
90
75
  }
91
76
 
92
- pub fn create_payload(message: &BorrowedMessage<'_>, payload: &[u8]) -> Payload {
93
- let key: Option<Buffer> = message.key().map(|bytes| bytes.into());
94
- let headers = Some(kakfa_headers_to_hashmap_buffer(message.headers()));
95
- let payload_js = Payload::new(
96
- payload.into(),
97
- key,
98
- headers,
99
- message.topic().to_owned(),
100
- message.partition(),
101
- message.offset(),
102
- );
103
- payload_js
104
- }
105
-
106
77
  pub fn create_message(message: &BorrowedMessage<'_>, payload: &[u8]) -> Message {
107
78
  let key: Option<Buffer> = message.key().map(|bytes| bytes.into());
108
79
  let headers = Some(kakfa_headers_to_hashmap_buffer(message.headers()));
package/src/kafka/mod.rs CHANGED
@@ -2,5 +2,4 @@ pub mod consumer;
2
2
  pub mod kafka_admin;
3
3
  pub mod kafka_client;
4
4
  pub mod kafka_util;
5
- pub mod model;
6
5
  pub mod producer;
@@ -16,11 +16,9 @@ use rdkafka::{
16
16
  ClientConfig, ClientContext, Message, Statistics,
17
17
  };
18
18
 
19
- use napi::bindgen_prelude::Buffer;
20
-
21
19
  use crate::kafka::kafka_util::hashmap_to_kafka_headers;
22
20
 
23
- use super::model::KafkaCrabError;
21
+ use super::model::{KafkaCrabError, MessageProducer, ProducerRecord, RecordMetadata};
24
22
 
25
23
  const DEFAULT_QUEUE_TIMEOUT: i64 = 5000;
26
24
 
@@ -82,23 +80,6 @@ where
82
80
  .unwrap()
83
81
  }
84
82
 
85
- #[napi(object)]
86
- #[derive(Clone)]
87
- pub struct RecordMetadata {
88
- pub topic: String,
89
- pub partition: i32,
90
- pub offset: i64,
91
- pub error: Option<KafkaCrabError>,
92
- }
93
-
94
- #[napi(object)]
95
- #[derive(Clone)]
96
- pub struct MessageProducer {
97
- pub value: Buffer,
98
- pub key: Option<Buffer>,
99
- pub headers: Option<HashMap<String, Buffer>>,
100
- }
101
-
102
83
  #[napi(object)]
103
84
  #[derive(Clone, Debug)]
104
85
  pub struct ProducerConfiguration {
@@ -107,13 +88,6 @@ pub struct ProducerConfiguration {
107
88
  pub configuration: Option<HashMap<String, String>>,
108
89
  }
109
90
 
110
- #[napi(object)]
111
- #[derive(Clone)]
112
- pub struct ProducerRecord {
113
- pub topic: String,
114
- pub messages: Vec<MessageProducer>,
115
- }
116
-
117
91
  #[napi]
118
92
  pub struct KafkaProducer {
119
93
  queue_timeout: Duration,
@@ -153,7 +127,9 @@ impl KafkaProducer {
153
127
  let producer = threaded_producer_with_context(context.clone(), self.client_config.clone());
154
128
 
155
129
  for message in producer_record.messages {
156
- let MessageProducer { value, headers, .. } = message;
130
+ let MessageProducer {
131
+ payload, headers, ..
132
+ } = message;
157
133
  let headers = match headers {
158
134
  Some(v) => hashmap_to_kafka_headers(&v),
159
135
  None => OwnedHeaders::new(),
@@ -167,7 +143,7 @@ impl KafkaProducer {
167
143
  producer
168
144
  .send(
169
145
  BaseRecord::to(topic)
170
- .payload(value.to_bytes())
146
+ .payload(payload.to_bytes())
171
147
  .headers(headers)
172
148
  .key(rd_key),
173
149
  )
@@ -65,6 +65,30 @@ impl Message {
65
65
  }
66
66
  }
67
67
 
68
+ #[napi(object)]
69
+ #[derive(Clone)]
70
+ pub struct RecordMetadata {
71
+ pub topic: String,
72
+ pub partition: i32,
73
+ pub offset: i64,
74
+ pub error: Option<KafkaCrabError>,
75
+ }
76
+
77
+ #[napi(object)]
78
+ #[derive(Clone)]
79
+ pub struct MessageProducer {
80
+ pub payload: Buffer,
81
+ pub key: Option<Buffer>,
82
+ pub headers: Option<HashMap<String, Buffer>>,
83
+ }
84
+
85
+ #[napi(object)]
86
+ #[derive(Clone)]
87
+ pub struct ProducerRecord {
88
+ pub topic: String,
89
+ pub messages: Vec<MessageProducer>,
90
+ }
91
+
68
92
  #[napi(object)]
69
93
  #[derive(Clone)]
70
94
  pub struct KafkaCrabError {
@@ -1,48 +0,0 @@
1
- use std::fmt;
2
-
3
- #[derive(Debug)]
4
- #[napi(string_enum)]
5
- pub enum AutoOffsetReset {
6
- Smallest,
7
- Earliest,
8
- Beginning,
9
- Largest,
10
- Latest,
11
- End,
12
- Error,
13
- }
14
-
15
- impl fmt::Display for AutoOffsetReset {
16
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17
- write!(f, "{}", format!("{:?}", self).to_lowercase())
18
- }
19
- }
20
-
21
- #[napi(string_enum)]
22
- #[derive(Debug)]
23
- pub enum PartitionPosition {
24
- Beginning,
25
- End,
26
- Stored,
27
- }
28
- #[napi(object)]
29
- #[derive(Clone, Debug)]
30
- pub struct OffsetModel {
31
- pub offset: Option<i64>,
32
- pub position: Option<PartitionPosition>,
33
- }
34
-
35
- #[napi(object)]
36
- #[derive(Clone, Debug)]
37
- pub struct PartitionOffset {
38
- pub partition: i32,
39
- pub offset: OffsetModel,
40
- }
41
-
42
- #[napi(object)]
43
- #[derive(Clone, Debug)]
44
- pub struct TopicPartitionConfig {
45
- pub topic: String,
46
- pub all_offsets: Option<OffsetModel>,
47
- pub partition_offset: Option<Vec<PartitionOffset>>,
48
- }