pulsar-client 1.6.2 → 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/README.md +50 -7
- package/binding.gyp +23 -5
- package/docker-tests.sh +4 -3
- package/index.d.ts +5 -4
- package/package.json +4 -10
- package/pulsar-test-service-start.sh +1 -1
- package/pulsar-version.txt +1 -1
- package/run-unit-tests.sh +1 -1
- package/src/Client.cc +84 -58
- package/src/Client.h +6 -4
- package/src/Consumer.cc +260 -231
- package/src/Consumer.h +9 -9
- package/src/ConsumerConfig.cc +33 -32
- package/src/ConsumerConfig.h +5 -6
- package/src/Message.cc +26 -29
- package/src/Message.h +4 -4
- package/src/MessageId.cc +19 -22
- package/src/MessageId.h +5 -6
- package/src/MessageListener.h +3 -8
- package/src/Producer.cc +116 -133
- package/src/Producer.h +3 -3
- package/src/ProducerConfig.cc +33 -22
- package/src/ProducerConfig.h +2 -2
- package/src/Reader.cc +98 -129
- package/src/Reader.h +3 -3
- package/src/ReaderConfig.cc +14 -20
- package/src/ReaderConfig.h +5 -6
- package/src/ReaderListener.h +2 -7
- package/src/SchemaInfo.cc +78 -0
- package/src/SchemaInfo.h +41 -0
- package/src/ThreadSafeDeferred.cc +98 -0
- package/src/ThreadSafeDeferred.h +85 -0
- package/tests/consumer.test.js +2 -2
- package/tests/end_to_end.test.js +2 -2
- package/tests/producer.test.js +2 -2
package/src/Consumer.cc
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
#include "ConsumerConfig.h"
|
|
22
22
|
#include "Message.h"
|
|
23
23
|
#include "MessageId.h"
|
|
24
|
+
#include "ThreadSafeDeferred.h"
|
|
24
25
|
#include <pulsar/c/result.h>
|
|
25
26
|
#include <atomic>
|
|
26
27
|
#include <thread>
|
|
@@ -50,10 +51,10 @@ void Consumer::Init(Napi::Env env, Napi::Object exports) {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
struct MessageListenerProxyData {
|
|
53
|
-
pulsar_message_t
|
|
54
|
+
std::shared_ptr<pulsar_message_t> cMessage;
|
|
54
55
|
Consumer *consumer;
|
|
55
56
|
|
|
56
|
-
MessageListenerProxyData(pulsar_message_t
|
|
57
|
+
MessageListenerProxyData(std::shared_ptr<pulsar_message_t> cMessage, Consumer *consumer)
|
|
57
58
|
: cMessage(cMessage), consumer(consumer) {}
|
|
58
59
|
};
|
|
59
60
|
|
|
@@ -62,11 +63,16 @@ void MessageListenerProxy(Napi::Env env, Napi::Function jsCallback, MessageListe
|
|
|
62
63
|
Consumer *consumer = data->consumer;
|
|
63
64
|
delete data;
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
// `consumer` might be null in certain cases, segmentation fault might happend without this null check. We
|
|
67
|
+
// need to handle this rare case in future.
|
|
68
|
+
if (consumer) {
|
|
69
|
+
jsCallback.Call({msg, consumer->Value()});
|
|
70
|
+
}
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
void MessageListener(pulsar_consumer_t *
|
|
69
|
-
|
|
73
|
+
void MessageListener(pulsar_consumer_t *rawConsumer, pulsar_message_t *rawMessage, void *ctx) {
|
|
74
|
+
std::shared_ptr<pulsar_message_t> cMessage(rawMessage, pulsar_message_free);
|
|
75
|
+
MessageListenerCallback *listenerCallback = (MessageListenerCallback *)ctx;
|
|
70
76
|
|
|
71
77
|
Consumer *consumer = (Consumer *)listenerCallback->consumer;
|
|
72
78
|
|
|
@@ -79,144 +85,131 @@ void MessageListener(pulsar_consumer_t *cConsumer, pulsar_message_t *cMessage, v
|
|
|
79
85
|
listenerCallback->callback.Release();
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
void Consumer::SetCConsumer(std::shared_ptr<
|
|
83
|
-
void Consumer::SetListenerCallback(
|
|
84
|
-
if (listener) {
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
void Consumer::SetCConsumer(std::shared_ptr<pulsar_consumer_t> cConsumer) { this->cConsumer = cConsumer; }
|
|
89
|
+
void Consumer::SetListenerCallback(MessageListenerCallback *listener) {
|
|
90
|
+
if (this->listener != nullptr) {
|
|
91
|
+
// It is only safe to set the listener once for the lifecycle of the Consumer
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
88
94
|
|
|
89
|
-
|
|
95
|
+
if (listener != nullptr) {
|
|
90
96
|
listener->consumer = this;
|
|
97
|
+
// If a consumer listener is set, the Consumer instance is kept alive even if it goes out of scope in JS
|
|
98
|
+
// code.
|
|
99
|
+
this->Ref();
|
|
100
|
+
this->listener = listener;
|
|
91
101
|
}
|
|
92
|
-
|
|
93
|
-
this->listener = listener;
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
Consumer::Consumer(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Consumer>(info), listener(nullptr) {}
|
|
97
105
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
SetError(
|
|
114
|
-
std::string("Topic, topics or topicsPattern is required and must be specified as a string when "
|
|
115
|
-
"creating consumer"));
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const std::string &subscription = this->consumerConfig->GetSubscription();
|
|
119
|
-
if (subscription.empty()) {
|
|
120
|
-
SetError(
|
|
121
|
-
std::string("Subscription is required and must be specified as a string when creating consumer"));
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
int32_t ackTimeoutMs = this->consumerConfig->GetAckTimeoutMs();
|
|
125
|
-
if (ackTimeoutMs != 0 && ackTimeoutMs < MIN_ACK_TIMEOUT_MILLIS) {
|
|
126
|
-
std::string msg("Ack timeout should be 0 or greater than or equal to " +
|
|
127
|
-
std::to_string(MIN_ACK_TIMEOUT_MILLIS));
|
|
128
|
-
SetError(msg);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
int32_t nAckRedeliverTimeoutMs = this->consumerConfig->GetNAckRedeliverTimeoutMs();
|
|
132
|
-
if (nAckRedeliverTimeoutMs < 0) {
|
|
133
|
-
std::string msg("NAck timeout should be greater than or equal to zero");
|
|
134
|
-
SetError(msg);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
106
|
+
struct ConsumerNewInstanceContext {
|
|
107
|
+
ConsumerNewInstanceContext(std::shared_ptr<ThreadSafeDeferred> deferred,
|
|
108
|
+
std::shared_ptr<pulsar_client_t> cClient,
|
|
109
|
+
std::shared_ptr<ConsumerConfig> consumerConfig)
|
|
110
|
+
: deferred(deferred), cClient(cClient), consumerConfig(consumerConfig){};
|
|
111
|
+
std::shared_ptr<ThreadSafeDeferred> deferred;
|
|
112
|
+
std::shared_ptr<pulsar_client_t> cClient;
|
|
113
|
+
std::shared_ptr<ConsumerConfig> consumerConfig;
|
|
114
|
+
|
|
115
|
+
static void subscribeCallback(pulsar_result result, pulsar_consumer_t *rawConsumer, void *ctx) {
|
|
116
|
+
auto instanceContext = static_cast<ConsumerNewInstanceContext *>(ctx);
|
|
117
|
+
auto deferred = instanceContext->deferred;
|
|
118
|
+
auto cClient = instanceContext->cClient;
|
|
119
|
+
auto consumerConfig = instanceContext->consumerConfig;
|
|
120
|
+
delete instanceContext;
|
|
137
121
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
pulsar_client_subscribe_pattern_async(this->cClient, topicsPattern.c_str(), subscription.c_str(),
|
|
141
|
-
this->consumerConfig->GetCConsumerConfig(),
|
|
142
|
-
&ConsumerNewInstanceWorker::subscribeCallback, (void *)this);
|
|
143
|
-
} else if (topics.size() > 0) {
|
|
144
|
-
const char **cTopics = new const char *[topics.size()];
|
|
145
|
-
for (size_t i = 0; i < topics.size(); i++) {
|
|
146
|
-
cTopics[i] = topics[i].c_str();
|
|
147
|
-
}
|
|
148
|
-
pulsar_client_subscribe_multi_topics_async(this->cClient, cTopics, topics.size(), subscription.c_str(),
|
|
149
|
-
this->consumerConfig->GetCConsumerConfig(),
|
|
150
|
-
&ConsumerNewInstanceWorker::subscribeCallback, (void *)this);
|
|
151
|
-
delete cTopics;
|
|
152
|
-
} else {
|
|
153
|
-
pulsar_client_subscribe_async(this->cClient, topic.c_str(), subscription.c_str(),
|
|
154
|
-
this->consumerConfig->GetCConsumerConfig(),
|
|
155
|
-
&ConsumerNewInstanceWorker::subscribeCallback, (void *)this);
|
|
156
|
-
}
|
|
157
|
-
while (!done) {
|
|
158
|
-
std::this_thread::yield();
|
|
122
|
+
if (result != pulsar_result_Ok) {
|
|
123
|
+
return deferred->Reject(std::string("Failed to create consumer: ") + pulsar_result_str(result));
|
|
159
124
|
}
|
|
160
|
-
}
|
|
161
|
-
void OnOK() {
|
|
162
|
-
Napi::Object obj = Consumer::constructor.New({});
|
|
163
|
-
Consumer *consumer = Consumer::Unwrap(obj);
|
|
164
125
|
|
|
165
|
-
|
|
166
|
-
|
|
126
|
+
auto cConsumer = std::shared_ptr<pulsar_consumer_t>(rawConsumer, pulsar_consumer_free);
|
|
127
|
+
auto listener = consumerConfig->GetListenerCallback();
|
|
167
128
|
|
|
168
|
-
if (
|
|
169
|
-
// resume to
|
|
170
|
-
|
|
129
|
+
if (listener) {
|
|
130
|
+
// pause, will resume in OnOK, to prevent MessageListener get a nullptr of consumer
|
|
131
|
+
pulsar_consumer_pause_message_listener(cConsumer.get());
|
|
171
132
|
}
|
|
172
133
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
134
|
+
deferred->Resolve([cConsumer, consumerConfig, listener](const Napi::Env env) {
|
|
135
|
+
Napi::Object obj = Consumer::constructor.New({});
|
|
136
|
+
Consumer *consumer = Consumer::Unwrap(obj);
|
|
176
137
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
pulsar_client_t *cClient;
|
|
180
|
-
pulsar_consumer_t *cConsumer;
|
|
181
|
-
ConsumerConfig *consumerConfig;
|
|
182
|
-
ListenerCallback *listener;
|
|
183
|
-
std::shared_ptr<CConsumerWrapper> consumerWrapper;
|
|
184
|
-
std::atomic<bool> done;
|
|
185
|
-
static void subscribeCallback(pulsar_result result, pulsar_consumer_t *consumer, void *ctx) {
|
|
186
|
-
ConsumerNewInstanceWorker *worker = (ConsumerNewInstanceWorker *)ctx;
|
|
187
|
-
if (result != pulsar_result_Ok) {
|
|
188
|
-
worker->SetError(std::string("Failed to create consumer: ") + pulsar_result_str(result));
|
|
189
|
-
} else {
|
|
190
|
-
worker->consumerWrapper->cConsumer = consumer;
|
|
191
|
-
worker->listener = worker->consumerConfig->GetListenerCallback();
|
|
138
|
+
consumer->SetCConsumer(cConsumer);
|
|
139
|
+
consumer->SetListenerCallback(listener);
|
|
192
140
|
|
|
193
|
-
if (
|
|
194
|
-
//
|
|
195
|
-
|
|
141
|
+
if (listener) {
|
|
142
|
+
// resume to enable MessageListener function callback
|
|
143
|
+
resume_message_listener(cConsumer.get());
|
|
196
144
|
}
|
|
197
|
-
}
|
|
198
145
|
|
|
199
|
-
|
|
200
|
-
|
|
146
|
+
return obj;
|
|
147
|
+
});
|
|
201
148
|
}
|
|
202
149
|
};
|
|
203
150
|
|
|
204
|
-
Napi::Value Consumer::NewInstance(const Napi::CallbackInfo &info, pulsar_client_t
|
|
205
|
-
|
|
206
|
-
|
|
151
|
+
Napi::Value Consumer::NewInstance(const Napi::CallbackInfo &info, std::shared_ptr<pulsar_client_t> cClient) {
|
|
152
|
+
auto deferred = ThreadSafeDeferred::New(info.Env());
|
|
153
|
+
auto config = info[0].As<Napi::Object>();
|
|
154
|
+
std::shared_ptr<ConsumerConfig> consumerConfig = std::make_shared<ConsumerConfig>(config, &MessageListener);
|
|
155
|
+
|
|
156
|
+
const std::string &topic = consumerConfig->GetTopic();
|
|
157
|
+
const std::vector<std::string> &topics = consumerConfig->GetTopics();
|
|
158
|
+
const std::string &topicsPattern = consumerConfig->GetTopicsPattern();
|
|
159
|
+
if (topic.empty() && topics.size() == 0 && topicsPattern.empty()) {
|
|
160
|
+
deferred->Reject(
|
|
161
|
+
std::string("Topic, topics or topicsPattern is required and must be specified as a string when "
|
|
162
|
+
"creating consumer"));
|
|
163
|
+
return deferred->Promise();
|
|
164
|
+
}
|
|
165
|
+
const std::string &subscription = consumerConfig->GetSubscription();
|
|
166
|
+
if (subscription.empty()) {
|
|
167
|
+
deferred->Reject(
|
|
168
|
+
std::string("Subscription is required and must be specified as a string when creating consumer"));
|
|
169
|
+
return deferred->Promise();
|
|
170
|
+
}
|
|
171
|
+
int32_t ackTimeoutMs = consumerConfig->GetAckTimeoutMs();
|
|
172
|
+
if (ackTimeoutMs != 0 && ackTimeoutMs < MIN_ACK_TIMEOUT_MILLIS) {
|
|
173
|
+
std::string msg("Ack timeout should be 0 or greater than or equal to " +
|
|
174
|
+
std::to_string(MIN_ACK_TIMEOUT_MILLIS));
|
|
175
|
+
deferred->Reject(msg);
|
|
176
|
+
return deferred->Promise();
|
|
177
|
+
}
|
|
178
|
+
int32_t nAckRedeliverTimeoutMs = consumerConfig->GetNAckRedeliverTimeoutMs();
|
|
179
|
+
if (nAckRedeliverTimeoutMs < 0) {
|
|
180
|
+
std::string msg("NAck timeout should be greater than or equal to zero");
|
|
181
|
+
deferred->Reject(msg);
|
|
182
|
+
return deferred->Promise();
|
|
183
|
+
}
|
|
207
184
|
|
|
208
|
-
|
|
185
|
+
auto ctx = new ConsumerNewInstanceContext(deferred, cClient, consumerConfig);
|
|
209
186
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
187
|
+
if (!topicsPattern.empty()) {
|
|
188
|
+
pulsar_client_subscribe_pattern_async(cClient.get(), topicsPattern.c_str(), subscription.c_str(),
|
|
189
|
+
consumerConfig->GetCConsumerConfig().get(),
|
|
190
|
+
&ConsumerNewInstanceContext::subscribeCallback, ctx);
|
|
191
|
+
} else if (topics.size() > 0) {
|
|
192
|
+
const char **cTopics = new const char *[topics.size()];
|
|
193
|
+
for (size_t i = 0; i < topics.size(); i++) {
|
|
194
|
+
cTopics[i] = topics[i].c_str();
|
|
195
|
+
}
|
|
196
|
+
pulsar_client_subscribe_multi_topics_async(cClient.get(), cTopics, topics.size(), subscription.c_str(),
|
|
197
|
+
consumerConfig->GetCConsumerConfig().get(),
|
|
198
|
+
&ConsumerNewInstanceContext::subscribeCallback, ctx);
|
|
199
|
+
delete[] cTopics;
|
|
200
|
+
} else {
|
|
201
|
+
pulsar_client_subscribe_async(cClient.get(), topic.c_str(), subscription.c_str(),
|
|
202
|
+
consumerConfig->GetCConsumerConfig().get(),
|
|
203
|
+
&ConsumerNewInstanceContext::subscribeCallback, ctx);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return deferred->Promise();
|
|
215
207
|
}
|
|
216
208
|
|
|
209
|
+
// We still need a receive worker because the c api is missing the equivalent async definition
|
|
217
210
|
class ConsumerReceiveWorker : public Napi::AsyncWorker {
|
|
218
211
|
public:
|
|
219
|
-
ConsumerReceiveWorker(const Napi::Promise::Deferred &deferred, pulsar_consumer_t
|
|
212
|
+
ConsumerReceiveWorker(const Napi::Promise::Deferred &deferred, std::shared_ptr<pulsar_consumer_t> cConsumer,
|
|
220
213
|
int64_t timeout = -1)
|
|
221
214
|
: AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
|
|
222
215
|
deferred(deferred),
|
|
@@ -225,14 +218,17 @@ class ConsumerReceiveWorker : public Napi::AsyncWorker {
|
|
|
225
218
|
~ConsumerReceiveWorker() {}
|
|
226
219
|
void Execute() {
|
|
227
220
|
pulsar_result result;
|
|
221
|
+
pulsar_message_t *rawMessage;
|
|
228
222
|
if (timeout > 0) {
|
|
229
|
-
result = pulsar_consumer_receive_with_timeout(this->cConsumer, &
|
|
223
|
+
result = pulsar_consumer_receive_with_timeout(this->cConsumer.get(), &rawMessage, timeout);
|
|
230
224
|
} else {
|
|
231
|
-
result = pulsar_consumer_receive(this->cConsumer, &
|
|
225
|
+
result = pulsar_consumer_receive(this->cConsumer.get(), &rawMessage);
|
|
232
226
|
}
|
|
233
227
|
|
|
234
228
|
if (result != pulsar_result_Ok) {
|
|
235
|
-
SetError(std::string("Failed to
|
|
229
|
+
SetError(std::string("Failed to receive message: ") + pulsar_result_str(result));
|
|
230
|
+
} else {
|
|
231
|
+
this->cMessage = std::shared_ptr<pulsar_message_t>(rawMessage, pulsar_message_free);
|
|
236
232
|
}
|
|
237
233
|
}
|
|
238
234
|
void OnOK() {
|
|
@@ -243,160 +239,193 @@ class ConsumerReceiveWorker : public Napi::AsyncWorker {
|
|
|
243
239
|
|
|
244
240
|
private:
|
|
245
241
|
Napi::Promise::Deferred deferred;
|
|
246
|
-
pulsar_consumer_t
|
|
247
|
-
pulsar_message_t
|
|
242
|
+
std::shared_ptr<pulsar_consumer_t> cConsumer;
|
|
243
|
+
std::shared_ptr<pulsar_message_t> cMessage;
|
|
248
244
|
int64_t timeout;
|
|
249
245
|
};
|
|
250
246
|
|
|
251
247
|
Napi::Value Consumer::Receive(const Napi::CallbackInfo &info) {
|
|
252
248
|
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
|
|
253
249
|
if (info[0].IsUndefined()) {
|
|
254
|
-
ConsumerReceiveWorker *wk = new ConsumerReceiveWorker(deferred, this->
|
|
250
|
+
ConsumerReceiveWorker *wk = new ConsumerReceiveWorker(deferred, this->cConsumer);
|
|
255
251
|
wk->Queue();
|
|
256
252
|
} else {
|
|
257
253
|
Napi::Number timeout = info[0].As<Napi::Object>().ToNumber();
|
|
258
|
-
ConsumerReceiveWorker *wk =
|
|
259
|
-
new ConsumerReceiveWorker(deferred, this->wrapper->cConsumer, timeout.Int64Value());
|
|
254
|
+
ConsumerReceiveWorker *wk = new ConsumerReceiveWorker(deferred, this->cConsumer, timeout.Int64Value());
|
|
260
255
|
wk->Queue();
|
|
261
256
|
}
|
|
262
257
|
return deferred.Promise();
|
|
263
258
|
}
|
|
264
259
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
260
|
+
Napi::Value Consumer::Acknowledge(const Napi::CallbackInfo &info) {
|
|
261
|
+
auto obj = info[0].As<Napi::Object>();
|
|
262
|
+
auto msg = Message::Unwrap(obj);
|
|
263
|
+
auto deferred = ThreadSafeDeferred::New(Env());
|
|
264
|
+
auto ctx = new ExtDeferredContext(deferred);
|
|
265
|
+
|
|
266
|
+
pulsar_consumer_acknowledge_async(
|
|
267
|
+
this->cConsumer.get(), msg->GetCMessage().get(),
|
|
268
|
+
[](pulsar_result result, void *ctx) {
|
|
269
|
+
auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
|
|
270
|
+
auto deferred = deferredContext->deferred;
|
|
271
|
+
delete deferredContext;
|
|
272
|
+
|
|
273
|
+
if (result != pulsar_result_Ok) {
|
|
274
|
+
deferred->Reject(std::string("Failed to acknowledge: ") + pulsar_result_str(result));
|
|
275
|
+
} else {
|
|
276
|
+
deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
ctx);
|
|
280
|
+
|
|
281
|
+
return deferred->Promise();
|
|
269
282
|
}
|
|
270
283
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
284
|
+
Napi::Value Consumer::AcknowledgeId(const Napi::CallbackInfo &info) {
|
|
285
|
+
auto obj = info[0].As<Napi::Object>();
|
|
286
|
+
auto *msgId = MessageId::Unwrap(obj);
|
|
287
|
+
auto deferred = ThreadSafeDeferred::New(Env());
|
|
288
|
+
auto ctx = new ExtDeferredContext(deferred);
|
|
289
|
+
|
|
290
|
+
pulsar_consumer_acknowledge_async_id(
|
|
291
|
+
this->cConsumer.get(), msgId->GetCMessageId().get(),
|
|
292
|
+
[](pulsar_result result, void *ctx) {
|
|
293
|
+
auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
|
|
294
|
+
auto deferred = deferredContext->deferred;
|
|
295
|
+
delete deferredContext;
|
|
296
|
+
|
|
297
|
+
if (result != pulsar_result_Ok) {
|
|
298
|
+
deferred->Reject(std::string("Failed to acknowledge id: ") + pulsar_result_str(result));
|
|
299
|
+
} else {
|
|
300
|
+
deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
ctx);
|
|
304
|
+
|
|
305
|
+
return deferred->Promise();
|
|
275
306
|
}
|
|
276
307
|
|
|
277
308
|
void Consumer::NegativeAcknowledge(const Napi::CallbackInfo &info) {
|
|
278
309
|
Napi::Object obj = info[0].As<Napi::Object>();
|
|
279
310
|
Message *msg = Message::Unwrap(obj);
|
|
280
|
-
|
|
311
|
+
std::shared_ptr<pulsar_message_t> cMessage = msg->GetCMessage();
|
|
312
|
+
pulsar_consumer_negative_acknowledge(this->cConsumer.get(), cMessage.get());
|
|
281
313
|
}
|
|
282
314
|
|
|
283
315
|
void Consumer::NegativeAcknowledgeId(const Napi::CallbackInfo &info) {
|
|
284
316
|
Napi::Object obj = info[0].As<Napi::Object>();
|
|
285
317
|
MessageId *msgId = MessageId::Unwrap(obj);
|
|
286
|
-
|
|
318
|
+
std::shared_ptr<pulsar_message_id_t> cMessageId = msgId->GetCMessageId();
|
|
319
|
+
pulsar_consumer_negative_acknowledge_id(this->cConsumer.get(), cMessageId.get());
|
|
287
320
|
}
|
|
288
321
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
322
|
+
Napi::Value Consumer::AcknowledgeCumulative(const Napi::CallbackInfo &info) {
|
|
323
|
+
auto obj = info[0].As<Napi::Object>();
|
|
324
|
+
auto *msg = Message::Unwrap(obj);
|
|
325
|
+
auto deferred = ThreadSafeDeferred::New(Env());
|
|
326
|
+
auto ctx = new ExtDeferredContext(deferred);
|
|
327
|
+
|
|
328
|
+
pulsar_consumer_acknowledge_cumulative_async(
|
|
329
|
+
this->cConsumer.get(), msg->GetCMessage().get(),
|
|
330
|
+
[](pulsar_result result, void *ctx) {
|
|
331
|
+
auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
|
|
332
|
+
auto deferred = deferredContext->deferred;
|
|
333
|
+
delete deferredContext;
|
|
334
|
+
|
|
335
|
+
if (result != pulsar_result_Ok) {
|
|
336
|
+
deferred->Reject(std::string("Failed to acknowledge cumulatively: ") + pulsar_result_str(result));
|
|
337
|
+
} else {
|
|
338
|
+
deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
ctx);
|
|
342
|
+
|
|
343
|
+
return deferred->Promise();
|
|
293
344
|
}
|
|
294
345
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
346
|
+
Napi::Value Consumer::AcknowledgeCumulativeId(const Napi::CallbackInfo &info) {
|
|
347
|
+
auto obj = info[0].As<Napi::Object>();
|
|
348
|
+
auto *msgId = MessageId::Unwrap(obj);
|
|
349
|
+
auto deferred = ThreadSafeDeferred::New(Env());
|
|
350
|
+
auto ctx = new ExtDeferredContext(deferred);
|
|
351
|
+
|
|
352
|
+
pulsar_consumer_acknowledge_cumulative_async_id(
|
|
353
|
+
this->cConsumer.get(), msgId->GetCMessageId().get(),
|
|
354
|
+
[](pulsar_result result, void *ctx) {
|
|
355
|
+
auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
|
|
356
|
+
auto deferred = deferredContext->deferred;
|
|
357
|
+
delete deferredContext;
|
|
358
|
+
|
|
359
|
+
if (result != pulsar_result_Ok) {
|
|
360
|
+
deferred->Reject(std::string("Failed to acknowledge cumulatively by id: ") +
|
|
361
|
+
pulsar_result_str(result));
|
|
362
|
+
} else {
|
|
363
|
+
deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
ctx);
|
|
367
|
+
|
|
368
|
+
return deferred->Promise();
|
|
300
369
|
}
|
|
301
370
|
|
|
302
371
|
Napi::Value Consumer::IsConnected(const Napi::CallbackInfo &info) {
|
|
303
372
|
Napi::Env env = info.Env();
|
|
304
|
-
return Napi::Boolean::New(env, pulsar_consumer_is_connected(this->
|
|
373
|
+
return Napi::Boolean::New(env, pulsar_consumer_is_connected(this->cConsumer.get()));
|
|
305
374
|
}
|
|
306
375
|
|
|
307
|
-
class ConsumerCloseWorker : public Napi::AsyncWorker {
|
|
308
|
-
public:
|
|
309
|
-
ConsumerCloseWorker(const Napi::Promise::Deferred &deferred, pulsar_consumer_t *cConsumer,
|
|
310
|
-
Consumer *consumer)
|
|
311
|
-
: AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
|
|
312
|
-
deferred(deferred),
|
|
313
|
-
cConsumer(cConsumer),
|
|
314
|
-
consumer(consumer) {}
|
|
315
|
-
|
|
316
|
-
~ConsumerCloseWorker() {}
|
|
317
|
-
void Execute() {
|
|
318
|
-
pulsar_consumer_pause_message_listener(this->cConsumer);
|
|
319
|
-
pulsar_result result = pulsar_consumer_close(this->cConsumer);
|
|
320
|
-
if (result != pulsar_result_Ok) {
|
|
321
|
-
SetError(pulsar_result_str(result));
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
void OnOK() {
|
|
325
|
-
this->consumer->Cleanup();
|
|
326
|
-
this->deferred.Resolve(Env().Null());
|
|
327
|
-
}
|
|
328
|
-
void OnError(const Napi::Error &e) {
|
|
329
|
-
this->deferred.Reject(
|
|
330
|
-
Napi::Error::New(Env(), std::string("Failed to close consumer: ") + e.Message()).Value());
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
private:
|
|
334
|
-
Napi::Promise::Deferred deferred;
|
|
335
|
-
pulsar_consumer_t *cConsumer;
|
|
336
|
-
Consumer *consumer;
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
class ConsumerUnsubscribeWorker : public Napi::AsyncWorker {
|
|
340
|
-
public:
|
|
341
|
-
ConsumerUnsubscribeWorker(const Napi::Promise::Deferred &deferred, pulsar_consumer_t *cConsumer,
|
|
342
|
-
Consumer *consumer)
|
|
343
|
-
: AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
|
|
344
|
-
deferred(deferred),
|
|
345
|
-
cConsumer(cConsumer),
|
|
346
|
-
consumer(consumer) {}
|
|
347
|
-
|
|
348
|
-
~ConsumerUnsubscribeWorker() {}
|
|
349
|
-
void Execute() {
|
|
350
|
-
pulsar_consumer_pause_message_listener(this->cConsumer);
|
|
351
|
-
pulsar_result result = pulsar_consumer_unsubscribe(this->cConsumer);
|
|
352
|
-
if (result != pulsar_result_Ok) {
|
|
353
|
-
SetError(pulsar_result_str(result));
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
void OnOK() {
|
|
357
|
-
this->consumer->Cleanup();
|
|
358
|
-
this->deferred.Resolve(Env().Null());
|
|
359
|
-
}
|
|
360
|
-
void OnError(const Napi::Error &e) {
|
|
361
|
-
this->deferred.Reject(
|
|
362
|
-
Napi::Error::New(Env(), std::string("Failed to unsubscribe consumer: ") + e.Message()).Value());
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
private:
|
|
366
|
-
Napi::Promise::Deferred deferred;
|
|
367
|
-
pulsar_consumer_t *cConsumer;
|
|
368
|
-
Consumer *consumer;
|
|
369
|
-
};
|
|
370
|
-
|
|
371
376
|
void Consumer::Cleanup() {
|
|
372
|
-
if (this->listener) {
|
|
373
|
-
this->
|
|
377
|
+
if (this->listener != nullptr) {
|
|
378
|
+
pulsar_consumer_pause_message_listener(this->cConsumer.get());
|
|
379
|
+
this->listener->callback.Release();
|
|
380
|
+
this->listener = nullptr;
|
|
381
|
+
this->Unref();
|
|
374
382
|
}
|
|
375
383
|
}
|
|
376
384
|
|
|
377
|
-
void Consumer::CleanupListener() {
|
|
378
|
-
pulsar_consumer_pause_message_listener(this->wrapper->cConsumer);
|
|
379
|
-
this->Unref();
|
|
380
|
-
this->listener->callback.Release();
|
|
381
|
-
this->listener = nullptr;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
385
|
Napi::Value Consumer::Close(const Napi::CallbackInfo &info) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
386
|
+
auto deferred = ThreadSafeDeferred::New(Env());
|
|
387
|
+
auto ctx = new ExtDeferredContext(deferred);
|
|
388
|
+
this->Cleanup();
|
|
389
|
+
|
|
390
|
+
pulsar_consumer_close_async(
|
|
391
|
+
this->cConsumer.get(),
|
|
392
|
+
[](pulsar_result result, void *ctx) {
|
|
393
|
+
auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
|
|
394
|
+
auto deferred = deferredContext->deferred;
|
|
395
|
+
delete deferredContext;
|
|
396
|
+
|
|
397
|
+
if (result != pulsar_result_Ok) {
|
|
398
|
+
deferred->Reject(std::string("Failed to close consumer: ") + pulsar_result_str(result));
|
|
399
|
+
} else {
|
|
400
|
+
deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
ctx);
|
|
404
|
+
|
|
405
|
+
return deferred->Promise();
|
|
389
406
|
}
|
|
390
407
|
|
|
391
408
|
Napi::Value Consumer::Unsubscribe(const Napi::CallbackInfo &info) {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
409
|
+
auto deferred = ThreadSafeDeferred::New(Env());
|
|
410
|
+
auto ctx = new ExtDeferredContext(deferred);
|
|
411
|
+
|
|
412
|
+
pulsar_consumer_pause_message_listener(this->cConsumer.get());
|
|
413
|
+
pulsar_consumer_unsubscribe_async(
|
|
414
|
+
this->cConsumer.get(),
|
|
415
|
+
[](pulsar_result result, void *ctx) {
|
|
416
|
+
auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
|
|
417
|
+
auto deferred = deferredContext->deferred;
|
|
418
|
+
delete deferredContext;
|
|
419
|
+
|
|
420
|
+
if (result != pulsar_result_Ok) {
|
|
421
|
+
deferred->Reject(std::string("Failed to unsubscribe consumer: ") + pulsar_result_str(result));
|
|
422
|
+
} else {
|
|
423
|
+
deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
ctx);
|
|
427
|
+
|
|
428
|
+
return deferred->Promise();
|
|
396
429
|
}
|
|
397
430
|
|
|
398
|
-
Consumer::~Consumer() {
|
|
399
|
-
if (this->listener) {
|
|
400
|
-
this->CleanupListener();
|
|
401
|
-
}
|
|
402
|
-
}
|
|
431
|
+
Consumer::~Consumer() { this->Cleanup(); }
|
package/src/Consumer.h
CHANGED
|
@@ -28,26 +28,26 @@
|
|
|
28
28
|
class Consumer : public Napi::ObjectWrap<Consumer> {
|
|
29
29
|
public:
|
|
30
30
|
static void Init(Napi::Env env, Napi::Object exports);
|
|
31
|
-
static Napi::Value NewInstance(const Napi::CallbackInfo &info, pulsar_client_t
|
|
31
|
+
static Napi::Value NewInstance(const Napi::CallbackInfo &info, std::shared_ptr<pulsar_client_t> cClient);
|
|
32
32
|
static Napi::FunctionReference constructor;
|
|
33
33
|
Consumer(const Napi::CallbackInfo &info);
|
|
34
34
|
~Consumer();
|
|
35
|
-
void SetCConsumer(std::shared_ptr<
|
|
36
|
-
void SetListenerCallback(
|
|
35
|
+
void SetCConsumer(std::shared_ptr<pulsar_consumer_t> cConsumer);
|
|
36
|
+
void SetListenerCallback(MessageListenerCallback *listener);
|
|
37
37
|
void Cleanup();
|
|
38
38
|
void CleanupListener();
|
|
39
39
|
|
|
40
40
|
private:
|
|
41
|
-
std::shared_ptr<
|
|
42
|
-
|
|
41
|
+
std::shared_ptr<pulsar_consumer_t> cConsumer;
|
|
42
|
+
MessageListenerCallback *listener;
|
|
43
43
|
|
|
44
44
|
Napi::Value Receive(const Napi::CallbackInfo &info);
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
Napi::Value Acknowledge(const Napi::CallbackInfo &info);
|
|
46
|
+
Napi::Value AcknowledgeId(const Napi::CallbackInfo &info);
|
|
47
47
|
void NegativeAcknowledge(const Napi::CallbackInfo &info);
|
|
48
48
|
void NegativeAcknowledgeId(const Napi::CallbackInfo &info);
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
Napi::Value AcknowledgeCumulative(const Napi::CallbackInfo &info);
|
|
50
|
+
Napi::Value AcknowledgeCumulativeId(const Napi::CallbackInfo &info);
|
|
51
51
|
Napi::Value IsConnected(const Napi::CallbackInfo &info);
|
|
52
52
|
Napi::Value Close(const Napi::CallbackInfo &info);
|
|
53
53
|
Napi::Value Unsubscribe(const Napi::CallbackInfo &info);
|