pulsar-client 1.6.2-rc.1 → 1.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.
package/src/Reader.cc CHANGED
@@ -20,6 +20,7 @@
20
20
  #include "Message.h"
21
21
  #include "Reader.h"
22
22
  #include "ReaderConfig.h"
23
+ #include "ThreadSafeDeferred.h"
23
24
  #include <pulsar/c/result.h>
24
25
  #include <pulsar/c/reader.h>
25
26
  #include <atomic>
@@ -43,10 +44,11 @@ void Reader::Init(Napi::Env env, Napi::Object exports) {
43
44
  }
44
45
 
45
46
  struct ReaderListenerProxyData {
46
- pulsar_message_t *cMessage;
47
+ std::shared_ptr<pulsar_message_t> cMessage;
47
48
  Reader *reader;
48
49
 
49
- ReaderListenerProxyData(pulsar_message_t *cMessage, Reader *reader) : cMessage(cMessage), reader(reader) {}
50
+ ReaderListenerProxyData(std::shared_ptr<pulsar_message_t> cMessage, Reader *reader)
51
+ : cMessage(cMessage), reader(reader) {}
50
52
  };
51
53
 
52
54
  void ReaderListenerProxy(Napi::Env env, Napi::Function jsCallback, ReaderListenerProxyData *data) {
@@ -57,7 +59,8 @@ void ReaderListenerProxy(Napi::Env env, Napi::Function jsCallback, ReaderListene
57
59
  jsCallback.Call({msg, reader->Value()});
58
60
  }
59
61
 
60
- void ReaderListener(pulsar_reader_t *cReader, pulsar_message_t *cMessage, void *ctx) {
62
+ void ReaderListener(pulsar_reader_t *rawReader, pulsar_message_t *rawMessage, void *ctx) {
63
+ std::shared_ptr<pulsar_message_t> cMessage(rawMessage, pulsar_message_free);
61
64
  ReaderListenerCallback *readerListenerCallback = (ReaderListenerCallback *)ctx;
62
65
  Reader *reader = (Reader *)readerListenerCallback->reader;
63
66
  if (readerListenerCallback->callback.Acquire() != napi_ok) {
@@ -68,101 +71,85 @@ void ReaderListener(pulsar_reader_t *cReader, pulsar_message_t *cMessage, void *
68
71
  readerListenerCallback->callback.Release();
69
72
  }
70
73
 
71
- void Reader::SetCReader(std::shared_ptr<CReaderWrapper> cReader) { this->wrapper = cReader; }
74
+ void Reader::SetCReader(std::shared_ptr<pulsar_reader_t> cReader) { this->cReader = cReader; }
72
75
  void Reader::SetListenerCallback(ReaderListenerCallback *listener) {
73
- if (listener) {
74
- // Maintain reference to reader, so it won't get garbage collected
75
- // since, when we have a listener, we don't have to maintain reference to reader (in js code)
76
- this->Ref();
76
+ if (this->listener != nullptr) {
77
+ // It is only safe to set the listener once for the lifecycle of the Reader
78
+ return;
79
+ }
77
80
 
78
- // Pass reader as argument
81
+ if (listener != nullptr) {
79
82
  listener->reader = this;
83
+ // If a reader listener is set, the Reader instance is kept alive even if it goes out of scope in JS code.
84
+ this->Ref();
85
+ this->listener = listener;
80
86
  }
81
-
82
- this->listener = listener;
83
87
  }
84
88
 
85
89
  Reader::Reader(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Reader>(info), listener(nullptr) {}
86
90
 
87
- class ReaderNewInstanceWorker : public Napi::AsyncWorker {
88
- public:
89
- ReaderNewInstanceWorker(const Napi::Promise::Deferred &deferred, pulsar_client_t *cClient,
90
- ReaderConfig *readerConfig, std::shared_ptr<CReaderWrapper> readerWrapper)
91
- : AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
92
- deferred(deferred),
93
- cClient(cClient),
94
- readerConfig(readerConfig),
95
- readerWrapper(readerWrapper),
96
- done(false) {}
97
- ~ReaderNewInstanceWorker() {}
98
- void Execute() {
99
- const std::string &topic = this->readerConfig->GetTopic();
100
- if (topic.empty()) {
101
- std::string msg("Topic is required and must be specified as a string when creating reader");
102
- SetError(msg);
103
- return;
104
- }
105
- if (this->readerConfig->GetCStartMessageId() == nullptr) {
106
- std::string msg(
107
- "StartMessageId is required and must be specified as a MessageId object when creating reader");
108
- SetError(msg);
109
- return;
110
- }
111
-
112
- pulsar_client_create_reader_async(this->cClient, topic.c_str(), this->readerConfig->GetCStartMessageId(),
113
- this->readerConfig->GetCReaderConfig(),
114
- &ReaderNewInstanceWorker::createReaderCallback, (void *)this);
115
-
116
- while (!done) {
117
- std::this_thread::yield();
118
- }
119
- }
120
- void OnOK() {
121
- Napi::Object obj = Reader::constructor.New({});
122
- Reader *reader = Reader::Unwrap(obj);
123
- reader->SetCReader(this->readerWrapper);
124
- reader->SetListenerCallback(this->listener);
125
- this->deferred.Resolve(obj);
126
- }
127
- void OnError(const Napi::Error &e) { this->deferred.Reject(Napi::Error::New(Env(), e.Message()).Value()); }
91
+ struct ReaderNewInstanceContext {
92
+ ReaderNewInstanceContext(std::shared_ptr<ThreadSafeDeferred> deferred,
93
+ std::shared_ptr<pulsar_client_t> cClient,
94
+ std::shared_ptr<ReaderConfig> readerConfig)
95
+ : deferred(deferred), cClient(cClient), readerConfig(readerConfig){};
96
+ std::shared_ptr<ThreadSafeDeferred> deferred;
97
+ std::shared_ptr<pulsar_client_t> cClient;
98
+ std::shared_ptr<ReaderConfig> readerConfig;
99
+
100
+ static void createReaderCallback(pulsar_result result, pulsar_reader_t *rawReader, void *ctx) {
101
+ auto instanceContext = static_cast<ReaderNewInstanceContext *>(ctx);
102
+ auto deferred = instanceContext->deferred;
103
+ auto cClient = instanceContext->cClient;
104
+ auto readerConfig = instanceContext->readerConfig;
105
+ delete instanceContext;
128
106
 
129
- private:
130
- Napi::Promise::Deferred deferred;
131
- pulsar_client_t *cClient;
132
- pulsar_reader_t *cReader;
133
- ReaderConfig *readerConfig;
134
- ReaderListenerCallback *listener;
135
- std::shared_ptr<CReaderWrapper> readerWrapper;
136
- std::atomic<bool> done;
137
- static void createReaderCallback(pulsar_result result, pulsar_reader_t *reader, void *ctx) {
138
- ReaderNewInstanceWorker *worker = (ReaderNewInstanceWorker *)ctx;
139
107
  if (result != pulsar_result_Ok) {
140
- worker->SetError(std::string("Failed to create reader: ") + pulsar_result_str(result));
141
- } else {
142
- worker->readerWrapper->cReader = reader;
143
- worker->listener = worker->readerConfig->GetListenerCallback();
108
+ return deferred->Reject(std::string("Failed to create reader: ") + pulsar_result_str(result));
144
109
  }
145
110
 
146
- delete worker->readerConfig;
147
- worker->done = true;
111
+ auto cReader = std::shared_ptr<pulsar_reader_t>(rawReader, pulsar_reader_free);
112
+
113
+ deferred->Resolve([cReader, readerConfig](const Napi::Env env) {
114
+ Napi::Object obj = Reader::constructor.New({});
115
+ Reader *reader = Reader::Unwrap(obj);
116
+ reader->SetCReader(cReader);
117
+ reader->SetListenerCallback(readerConfig->GetListenerCallback());
118
+ return obj;
119
+ });
148
120
  }
149
121
  };
150
122
 
151
- Napi::Value Reader::NewInstance(const Napi::CallbackInfo &info, pulsar_client_t *cClient) {
152
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
123
+ Napi::Value Reader::NewInstance(const Napi::CallbackInfo &info, std::shared_ptr<pulsar_client_t> cClient) {
124
+ auto deferred = ThreadSafeDeferred::New(info.Env());
153
125
  Napi::Object config = info[0].As<Napi::Object>();
154
126
 
155
- std::shared_ptr<CReaderWrapper> readerWrapper = std::make_shared<CReaderWrapper>();
127
+ auto readerConfig = std::make_shared<ReaderConfig>(config, &ReaderListener);
156
128
 
157
- ReaderConfig *readerConfig = new ReaderConfig(config, readerWrapper, &ReaderListener);
158
- ReaderNewInstanceWorker *wk = new ReaderNewInstanceWorker(deferred, cClient, readerConfig, readerWrapper);
159
- wk->Queue();
160
- return deferred.Promise();
129
+ const std::string &topic = readerConfig->GetTopic();
130
+ if (topic.empty()) {
131
+ deferred->Reject(std::string("Topic is required and must be specified as a string when creating reader"));
132
+ return deferred->Promise();
133
+ }
134
+ if (readerConfig->GetCStartMessageId().get() == nullptr) {
135
+ deferred->Reject(std::string(
136
+ "StartMessageId is required and must be specified as a MessageId object when creating reader"));
137
+ return deferred->Promise();
138
+ }
139
+
140
+ auto ctx = new ReaderNewInstanceContext(deferred, cClient, readerConfig);
141
+
142
+ pulsar_client_create_reader_async(cClient.get(), topic.c_str(), readerConfig->GetCStartMessageId().get(),
143
+ readerConfig->GetCReaderConfig().get(),
144
+ &ReaderNewInstanceContext::createReaderCallback, ctx);
145
+
146
+ return deferred->Promise();
161
147
  }
162
148
 
149
+ // We still need a read worker because the c api is missing the equivalent async definition
163
150
  class ReaderReadNextWorker : public Napi::AsyncWorker {
164
151
  public:
165
- ReaderReadNextWorker(const Napi::Promise::Deferred &deferred, pulsar_reader_t *cReader,
152
+ ReaderReadNextWorker(const Napi::Promise::Deferred &deferred, std::shared_ptr<pulsar_reader_t> cReader,
166
153
  int64_t timeout = -1)
167
154
  : AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
168
155
  deferred(deferred),
@@ -171,14 +158,16 @@ class ReaderReadNextWorker : public Napi::AsyncWorker {
171
158
  ~ReaderReadNextWorker() {}
172
159
  void Execute() {
173
160
  pulsar_result result;
161
+ pulsar_message_t *rawMessage;
174
162
  if (timeout > 0) {
175
- result = pulsar_reader_read_next_with_timeout(this->cReader, &(this->cMessage), timeout);
163
+ result = pulsar_reader_read_next_with_timeout(this->cReader.get(), &rawMessage, timeout);
176
164
  } else {
177
- result = pulsar_reader_read_next(this->cReader, &(this->cMessage));
165
+ result = pulsar_reader_read_next(this->cReader.get(), &rawMessage);
178
166
  }
179
167
  if (result != pulsar_result_Ok) {
180
168
  SetError(std::string("Failed to received message ") + pulsar_result_str(result));
181
169
  }
170
+ this->cMessage = std::shared_ptr<pulsar_message_t>(rawMessage, pulsar_message_free);
182
171
  }
183
172
  void OnOK() {
184
173
  Napi::Object obj = Message::NewInstance({}, this->cMessage);
@@ -188,20 +177,19 @@ class ReaderReadNextWorker : public Napi::AsyncWorker {
188
177
 
189
178
  private:
190
179
  Napi::Promise::Deferred deferred;
191
- pulsar_reader_t *cReader;
192
- pulsar_message_t *cMessage;
180
+ std::shared_ptr<pulsar_reader_t> cReader;
181
+ std::shared_ptr<pulsar_message_t> cMessage;
193
182
  int64_t timeout;
194
183
  };
195
184
 
196
185
  Napi::Value Reader::ReadNext(const Napi::CallbackInfo &info) {
197
186
  Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
198
187
  if (info[0].IsUndefined()) {
199
- ReaderReadNextWorker *wk = new ReaderReadNextWorker(deferred, this->wrapper->cReader);
188
+ ReaderReadNextWorker *wk = new ReaderReadNextWorker(deferred, this->cReader);
200
189
  wk->Queue();
201
190
  } else {
202
191
  Napi::Number timeout = info[0].As<Napi::Object>().ToNumber();
203
- ReaderReadNextWorker *wk =
204
- new ReaderReadNextWorker(deferred, this->wrapper->cReader, timeout.Int64Value());
192
+ ReaderReadNextWorker *wk = new ReaderReadNextWorker(deferred, this->cReader, timeout.Int64Value());
205
193
  wk->Queue();
206
194
  }
207
195
  return deferred.Promise();
@@ -209,7 +197,7 @@ Napi::Value Reader::ReadNext(const Napi::CallbackInfo &info) {
209
197
 
210
198
  Napi::Value Reader::HasNext(const Napi::CallbackInfo &info) {
211
199
  int value = 0;
212
- pulsar_result result = pulsar_reader_has_message_available(this->wrapper->cReader, &value);
200
+ pulsar_result result = pulsar_reader_has_message_available(this->cReader.get(), &value);
213
201
  if (result != pulsar_result_Ok) {
214
202
  Napi::Error::New(info.Env(), "Failed to check if next message is available").ThrowAsJavaScriptException();
215
203
  return Napi::Boolean::New(info.Env(), false);
@@ -222,57 +210,38 @@ Napi::Value Reader::HasNext(const Napi::CallbackInfo &info) {
222
210
 
223
211
  Napi::Value Reader::IsConnected(const Napi::CallbackInfo &info) {
224
212
  Napi::Env env = info.Env();
225
- return Napi::Boolean::New(env, pulsar_reader_is_connected(this->wrapper->cReader));
213
+ return Napi::Boolean::New(env, pulsar_reader_is_connected(this->cReader.get()));
226
214
  }
227
215
 
228
- class ReaderCloseWorker : public Napi::AsyncWorker {
229
- public:
230
- ReaderCloseWorker(const Napi::Promise::Deferred &deferred, pulsar_reader_t *cReader, Reader *reader)
231
- : AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
232
- deferred(deferred),
233
- cReader(cReader),
234
- reader(reader) {}
235
- ~ReaderCloseWorker() {}
236
- void Execute() {
237
- pulsar_result result = pulsar_reader_close(this->cReader);
238
- if (result != pulsar_result_Ok) SetError(pulsar_result_str(result));
239
- }
240
- void OnOK() {
241
- this->reader->Cleanup();
242
- this->deferred.Resolve(Env().Null());
243
- }
244
- void OnError(const Napi::Error &e) {
245
- this->deferred.Reject(
246
- Napi::Error::New(Env(), std::string("Failed to close reader: ") + e.Message()).Value());
247
- }
248
-
249
- private:
250
- Napi::Promise::Deferred deferred;
251
- pulsar_reader_t *cReader;
252
- Reader *reader;
253
- };
254
-
255
216
  Napi::Value Reader::Close(const Napi::CallbackInfo &info) {
256
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
257
- ReaderCloseWorker *wk = new ReaderCloseWorker(deferred, this->wrapper->cReader, this);
258
- wk->Queue();
259
- return deferred.Promise();
217
+ auto deferred = ThreadSafeDeferred::New(Env());
218
+ auto ctx = new ExtDeferredContext(deferred);
219
+ this->Cleanup();
220
+
221
+ pulsar_reader_close_async(
222
+ this->cReader.get(),
223
+ [](pulsar_result result, void *ctx) {
224
+ auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
225
+ auto deferred = deferredContext->deferred;
226
+ delete deferredContext;
227
+
228
+ if (result != pulsar_result_Ok) {
229
+ deferred->Reject(std::string("Failed to close reader: ") + pulsar_result_str(result));
230
+ } else {
231
+ deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
232
+ }
233
+ },
234
+ ctx);
235
+
236
+ return deferred->Promise();
260
237
  }
261
238
 
262
239
  void Reader::Cleanup() {
263
- if (this->listener) {
264
- this->CleanupListener();
240
+ if (this->listener != nullptr) {
241
+ this->listener->callback.Release();
242
+ this->Unref();
243
+ this->listener = nullptr;
265
244
  }
266
245
  }
267
246
 
268
- void Reader::CleanupListener() {
269
- this->Unref();
270
- this->listener->callback.Release();
271
- this->listener = nullptr;
272
- }
273
-
274
- Reader::~Reader() {
275
- if (this->listener) {
276
- this->CleanupListener();
277
- }
278
- }
247
+ Reader::~Reader() { this->Cleanup(); }
package/src/Reader.h CHANGED
@@ -27,16 +27,16 @@
27
27
  class Reader : public Napi::ObjectWrap<Reader> {
28
28
  public:
29
29
  static void Init(Napi::Env env, Napi::Object exports);
30
- static Napi::Value NewInstance(const Napi::CallbackInfo &info, pulsar_client_t *cClient);
30
+ static Napi::Value NewInstance(const Napi::CallbackInfo &info, std::shared_ptr<pulsar_client_t> cClient);
31
31
  static Napi::FunctionReference constructor;
32
32
  Reader(const Napi::CallbackInfo &info);
33
33
  ~Reader();
34
- void SetCReader(std::shared_ptr<CReaderWrapper> cReader);
34
+ void SetCReader(std::shared_ptr<pulsar_reader_t> cReader);
35
35
  void SetListenerCallback(ReaderListenerCallback *listener);
36
36
  void Cleanup();
37
37
 
38
38
  private:
39
- std::shared_ptr<CReaderWrapper> wrapper;
39
+ std::shared_ptr<pulsar_reader_t> cReader;
40
40
  ReaderListenerCallback *listener;
41
41
 
42
42
  Napi::Value ReadNext(const Napi::CallbackInfo &info);
@@ -31,10 +31,10 @@ static const std::string CFG_LISTENER = "listener";
31
31
 
32
32
  void FinalizeListenerCallback(Napi::Env env, ReaderListenerCallback *cb, void *) { delete cb; }
33
33
 
34
- ReaderConfig::ReaderConfig(const Napi::Object &readerConfig, std::shared_ptr<CReaderWrapper> readerWrapper,
35
- pulsar_reader_listener readerListener)
34
+ ReaderConfig::ReaderConfig(const Napi::Object &readerConfig, pulsar_reader_listener readerListener)
36
35
  : topic(""), cStartMessageId(NULL), listener(nullptr) {
37
- this->cReaderConfig = pulsar_reader_configuration_create();
36
+ this->cReaderConfig = std::shared_ptr<pulsar_reader_configuration_t>(pulsar_reader_configuration_create(),
37
+ pulsar_reader_configuration_free);
38
38
 
39
39
  if (readerConfig.Has(CFG_TOPIC) && readerConfig.Get(CFG_TOPIC).IsString()) {
40
40
  this->topic = readerConfig.Get(CFG_TOPIC).ToString().Utf8Value();
@@ -48,14 +48,14 @@ ReaderConfig::ReaderConfig(const Napi::Object &readerConfig, std::shared_ptr<CRe
48
48
  if (readerConfig.Has(CFG_RECV_QUEUE) && readerConfig.Get(CFG_RECV_QUEUE).IsNumber()) {
49
49
  int32_t receiverQueueSize = readerConfig.Get(CFG_RECV_QUEUE).ToNumber().Int32Value();
50
50
  if (receiverQueueSize >= 0) {
51
- pulsar_reader_configuration_set_receiver_queue_size(this->cReaderConfig, receiverQueueSize);
51
+ pulsar_reader_configuration_set_receiver_queue_size(this->cReaderConfig.get(), receiverQueueSize);
52
52
  }
53
53
  }
54
54
 
55
55
  if (readerConfig.Has(CFG_READER_NAME) && readerConfig.Get(CFG_READER_NAME).IsString()) {
56
56
  std::string readerName = readerConfig.Get(CFG_READER_NAME).ToString().Utf8Value();
57
57
  if (!readerName.empty())
58
- pulsar_reader_configuration_set_reader_name(this->cReaderConfig, readerName.c_str());
58
+ pulsar_reader_configuration_set_reader_name(this->cReaderConfig.get(), readerName.c_str());
59
59
  }
60
60
 
61
61
  if (readerConfig.Has(CFG_SUBSCRIPTION_ROLE_PREFIX) &&
@@ -63,13 +63,13 @@ ReaderConfig::ReaderConfig(const Napi::Object &readerConfig, std::shared_ptr<CRe
63
63
  std::string subscriptionRolePrefix =
64
64
  readerConfig.Get(CFG_SUBSCRIPTION_ROLE_PREFIX).ToString().Utf8Value();
65
65
  if (!subscriptionRolePrefix.empty())
66
- pulsar_reader_configuration_set_reader_name(this->cReaderConfig, subscriptionRolePrefix.c_str());
66
+ pulsar_reader_configuration_set_reader_name(this->cReaderConfig.get(), subscriptionRolePrefix.c_str());
67
67
  }
68
68
 
69
69
  if (readerConfig.Has(CFG_READ_COMPACTED) && readerConfig.Get(CFG_READ_COMPACTED).IsBoolean()) {
70
70
  bool readCompacted = readerConfig.Get(CFG_READ_COMPACTED).ToBoolean();
71
71
  if (readCompacted) {
72
- pulsar_reader_configuration_set_read_compacted(this->cReaderConfig, 1);
72
+ pulsar_reader_configuration_set_read_compacted(this->cReaderConfig.get(), 1);
73
73
  }
74
74
  }
75
75
 
@@ -79,33 +79,27 @@ ReaderConfig::ReaderConfig(const Napi::Object &readerConfig, std::shared_ptr<CRe
79
79
  readerConfig.Env(), readerConfig.Get(CFG_LISTENER).As<Napi::Function>(), "Reader Listener Callback",
80
80
  1, 1, (void *)NULL, FinalizeListenerCallback, listener);
81
81
  this->listener->callback = std::move(callback);
82
- pulsar_reader_configuration_set_reader_listener(this->cReaderConfig, readerListener, this->listener);
82
+ pulsar_reader_configuration_set_reader_listener(this->cReaderConfig.get(), readerListener,
83
+ this->listener);
83
84
  }
84
85
  }
85
86
 
86
87
  ReaderConfig::~ReaderConfig() {
87
- pulsar_reader_configuration_free(this->cReaderConfig);
88
- if (this->listener) {
88
+ if (this->listener != nullptr) {
89
89
  this->listener->callback.Release();
90
90
  }
91
91
  }
92
92
 
93
- pulsar_reader_configuration_t *ReaderConfig::GetCReaderConfig() { return this->cReaderConfig; }
93
+ std::shared_ptr<pulsar_reader_configuration_t> ReaderConfig::GetCReaderConfig() {
94
+ return this->cReaderConfig;
95
+ }
94
96
 
95
97
  std::string ReaderConfig::GetTopic() { return this->topic; }
96
98
 
97
- pulsar_message_id_t *ReaderConfig::GetCStartMessageId() { return this->cStartMessageId; }
99
+ std::shared_ptr<pulsar_message_id_t> ReaderConfig::GetCStartMessageId() { return this->cStartMessageId; }
98
100
 
99
101
  ReaderListenerCallback *ReaderConfig::GetListenerCallback() {
100
102
  ReaderListenerCallback *cb = this->listener;
101
103
  this->listener = nullptr;
102
104
  return cb;
103
105
  }
104
-
105
- CReaderWrapper::CReaderWrapper() : cReader(nullptr) {}
106
-
107
- CReaderWrapper::~CReaderWrapper() {
108
- if (this->cReader) {
109
- pulsar_reader_free(this->cReader);
110
- }
111
- }
@@ -28,18 +28,17 @@
28
28
 
29
29
  class ReaderConfig {
30
30
  public:
31
- ReaderConfig(const Napi::Object &readerConfig, std::shared_ptr<CReaderWrapper> readerWrapper,
32
- pulsar_reader_listener readerListener);
31
+ ReaderConfig(const Napi::Object &readerConfig, pulsar_reader_listener readerListener);
33
32
  ~ReaderConfig();
34
- pulsar_reader_configuration_t *GetCReaderConfig();
35
- pulsar_message_id_t *GetCStartMessageId();
33
+ std::shared_ptr<pulsar_reader_configuration_t> GetCReaderConfig();
34
+ std::shared_ptr<pulsar_message_id_t> GetCStartMessageId();
36
35
  std::string GetTopic();
37
36
  ReaderListenerCallback *GetListenerCallback();
38
37
 
39
38
  private:
40
39
  std::string topic;
41
- pulsar_message_id_t *cStartMessageId;
42
- pulsar_reader_configuration_t *cReaderConfig;
40
+ std::shared_ptr<pulsar_message_id_t> cStartMessageId;
41
+ std::shared_ptr<pulsar_reader_configuration_t> cReaderConfig;
43
42
  ReaderListenerCallback *listener;
44
43
  };
45
44
 
@@ -21,19 +21,14 @@
21
21
  #define READER_LISTENER_H
22
22
 
23
23
  #include <napi.h>
24
- #include <pulsar/c/client.h>
25
-
26
- struct CReaderWrapper {
27
- pulsar_reader_t *cReader;
28
- CReaderWrapper();
29
- ~CReaderWrapper();
30
- };
31
24
 
32
25
  struct ReaderListenerCallback {
33
26
  Napi::ThreadSafeFunction callback;
34
27
 
35
28
  // Using reader as void* since the ReaderListenerCallback is shared between Config and Reader.
36
29
  void *reader;
30
+
31
+ ReaderListenerCallback() : reader(nullptr) {}
37
32
  };
38
33
 
39
34
  #endif
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ #include "SchemaInfo.h"
20
+ #include <map>
21
+
22
+ static const std::string CFG_SCHEMA_TYPE = "schemaType";
23
+ static const std::string CFG_NAME = "name";
24
+ static const std::string CFG_SCHEMA = "schema";
25
+ static const std::string CFG_PROPS = "properties";
26
+
27
+ static const std::map<std::string, pulsar_schema_type> SCHEMA_TYPE = {{"None", pulsar_None},
28
+ {"String", pulsar_String},
29
+ {"Json", pulsar_Json},
30
+ {"Protobuf", pulsar_Protobuf},
31
+ {"Avro", pulsar_Avro},
32
+ {"Boolean", pulsar_Boolean},
33
+ {"Int8", pulsar_Int8},
34
+ {"Int16", pulsar_Int16},
35
+ {"Int32", pulsar_Int32},
36
+ {"Int64", pulsar_Int64},
37
+ {"Float32", pulsar_Float32},
38
+ {"Float64", pulsar_Float64},
39
+ {"KeyValue", pulsar_KeyValue},
40
+ {"Bytes", pulsar_Bytes},
41
+ {"AutoConsume", pulsar_AutoConsume},
42
+ {"AutoPublish", pulsar_AutoPublish}};
43
+
44
+ SchemaInfo::SchemaInfo(const Napi::Object &schemaInfo) : cSchemaType(pulsar_Bytes), name("BYTES"), schema() {
45
+ this->cProperties = pulsar_string_map_create();
46
+ if (schemaInfo.Has(CFG_SCHEMA_TYPE) && schemaInfo.Get(CFG_SCHEMA_TYPE).IsString()) {
47
+ this->name = schemaInfo.Get(CFG_SCHEMA_TYPE).ToString().Utf8Value();
48
+ this->cSchemaType = SCHEMA_TYPE.at(schemaInfo.Get(CFG_SCHEMA_TYPE).ToString().Utf8Value());
49
+ }
50
+ if (schemaInfo.Has(CFG_NAME) && schemaInfo.Get(CFG_NAME).IsString()) {
51
+ this->name = schemaInfo.Get(CFG_NAME).ToString().Utf8Value();
52
+ }
53
+ if (schemaInfo.Has(CFG_SCHEMA) && schemaInfo.Get(CFG_SCHEMA).IsString()) {
54
+ this->schema = schemaInfo.Get(CFG_SCHEMA).ToString().Utf8Value();
55
+ }
56
+ if (schemaInfo.Has(CFG_PROPS) && schemaInfo.Get(CFG_PROPS).IsObject()) {
57
+ Napi::Object propObj = schemaInfo.Get(CFG_PROPS).ToObject();
58
+ Napi::Array arr = propObj.GetPropertyNames();
59
+ int size = arr.Length();
60
+ for (int i = 0; i < size; i++) {
61
+ Napi::String key = arr.Get(i).ToString();
62
+ Napi::String value = propObj.Get(key).ToString();
63
+ pulsar_string_map_put(this->cProperties, key.Utf8Value().c_str(), value.Utf8Value().c_str());
64
+ }
65
+ }
66
+ }
67
+
68
+ void SchemaInfo::SetProducerSchema(std::shared_ptr<pulsar_producer_configuration_t> cProducerConfiguration) {
69
+ pulsar_producer_configuration_set_schema_info(cProducerConfiguration.get(), this->cSchemaType,
70
+ this->name.c_str(), this->schema.c_str(), this->cProperties);
71
+ }
72
+
73
+ void SchemaInfo::SetConsumerSchema(std::shared_ptr<pulsar_consumer_configuration_t> cConsumerConfiguration) {
74
+ pulsar_consumer_configuration_set_schema_info(cConsumerConfiguration.get(), this->cSchemaType,
75
+ this->name.c_str(), this->schema.c_str(), this->cProperties);
76
+ }
77
+
78
+ SchemaInfo::~SchemaInfo() { pulsar_string_map_free(this->cProperties); }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ #ifndef SCHEMA_INFO_H
21
+ #define SCHEMA_INFO_H
22
+
23
+ #include <napi.h>
24
+ #include <pulsar/c/producer_configuration.h>
25
+ #include <pulsar/c/consumer_configuration.h>
26
+
27
+ class SchemaInfo {
28
+ public:
29
+ SchemaInfo(const Napi::Object &schemaInfo);
30
+ ~SchemaInfo();
31
+ void SetProducerSchema(std::shared_ptr<pulsar_producer_configuration_t> cProducerConfiguration);
32
+ void SetConsumerSchema(std::shared_ptr<pulsar_consumer_configuration_t> cConsumerConfiguration);
33
+
34
+ private:
35
+ pulsar_schema_type cSchemaType;
36
+ std::string name;
37
+ std::string schema;
38
+ pulsar_string_map_t *cProperties;
39
+ };
40
+
41
+ #endif