Skip to content

Commit 2e2d8ab

Browse files
committed
Fix worker_threads support
Signed-off-by: Stephen Belanger <[email protected]>
1 parent a950a56 commit 2e2d8ab

25 files changed

+834
-328
lines changed

binding.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
'src/connection.cc',
1616
'src/errors.cc',
1717
'src/kafka-consumer.cc',
18+
'src/per-isolate-data.cc',
1819
'src/producer.cc',
1920
'src/topic.cc',
2021
'src/workers.cc',

package-lock.json

+496-270
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/admin.cc

+8-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <vector>
1212
#include <math.h>
1313

14+
#include "src/per-isolate-data.h"
1415
#include "src/workers.h"
1516
#include "src/admin.h"
1617

@@ -33,6 +34,10 @@ AdminClient::AdminClient(Conf* gconfig):
3334
rkqu = NULL;
3435
}
3536

37+
void AdminClient::delete_instance(void* arg) {
38+
delete (static_cast<AdminClient*>(arg));
39+
}
40+
3641
AdminClient::~AdminClient() {
3742
Disconnect();
3843
}
@@ -90,8 +95,6 @@ Baton AdminClient::Disconnect() {
9095
return Baton(RdKafka::ERR_NO_ERROR);
9196
}
9297

93-
Nan::Persistent<v8::Function> AdminClient::constructor;
94-
9598
void AdminClient::Init(v8::Local<v8::Object> exports) {
9699
Nan::HandleScope scope;
97100

@@ -108,7 +111,7 @@ void AdminClient::Init(v8::Local<v8::Object> exports) {
108111
Nan::SetPrototypeMethod(tpl, "disconnect", NodeDisconnect);
109112
Nan::SetPrototypeMethod(tpl, "setToken", NodeSetToken);
110113

111-
constructor.Reset(
114+
PerIsolateData::For(v8::Isolate::GetCurrent())->AdminClientConstructor().Reset(
112115
(tpl->GetFunction(Nan::GetCurrentContext())).ToLocalChecked());
113116
Nan::Set(exports, Nan::New("AdminClient").ToLocalChecked(),
114117
tpl->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());
@@ -155,7 +158,8 @@ v8::Local<v8::Object> AdminClient::NewInstance(v8::Local<v8::Value> arg) {
155158
const unsigned argc = 1;
156159

157160
v8::Local<v8::Value> argv[argc] = { arg };
158-
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
161+
v8::Local<v8::Function> cons = Nan::New<v8::Function>(
162+
PerIsolateData::For(v8::Isolate::GetCurrent())->AdminClientConstructor());
159163
v8::Local<v8::Object> instance =
160164
Nan::NewInstance(cons, argc, argv).ToLocalChecked();
161165

src/admin.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
#include <nan.h>
1414
#include <uv.h>
15-
#include <iostream>
1615
#include <string>
1716
#include <vector>
1817

@@ -59,6 +58,8 @@ class AdminClient : public Connection {
5958
explicit AdminClient(Conf* globalConfig);
6059
~AdminClient();
6160

61+
static void delete_instance(void* arg);
62+
6263
rd_kafka_queue_t* rkqu;
6364

6465
private:

src/binding.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
* of the MIT license. See the LICENSE.txt file for details.
88
*/
99

10-
#include <iostream>
1110
#include "src/binding.h"
1211

1312
using NodeKafka::Producer;
@@ -71,4 +70,4 @@ void Init(v8::Local<v8::Object> exports, v8::Local<v8::Value> m_, void* v_) {
7170
Nan::New(RdKafka::version_str().c_str()).ToLocalChecked());
7271
}
7372

74-
NODE_MODULE(kafka, Init)
73+
NODE_MODULE_CONTEXT_AWARE(kafka, Init)

src/callbacks.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ Dispatcher::~Dispatcher() {
6060
callbacks[i].Reset();
6161
}
6262

63+
Deactivate();
64+
6365
uv_mutex_destroy(&async_lock);
6466
}
6567

6668
// Only run this if we aren't already listening
6769
void Dispatcher::Activate() {
6870
if (!async) {
6971
async = new uv_async_t;
70-
uv_async_init(uv_default_loop(), async, AsyncMessage_);
72+
uv_async_init(Nan::GetCurrentEventLoop(), async, AsyncMessage_);
7173

7274
async->data = this;
7375
}

src/config.cc

+13-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* of the MIT license. See the LICENSE.txt file for details.
88
*/
99

10+
#include <iostream>
1011
#include <string>
1112
#include <vector>
1213
#include <list>
@@ -36,7 +37,14 @@ void Conf::DumpConfig(std::list<std::string> *dump) {
3637

3738
Conf * Conf::create(RdKafka::Conf::ConfType type, v8::Local<v8::Object> object, std::string &errstr) { // NOLINT
3839
v8::Local<v8::Context> context = Nan::GetCurrentContext();
39-
Conf* rdconf = static_cast<Conf*>(RdKafka::Conf::create(type));
40+
Conf* rdconf = new Conf(type);
41+
42+
if (type == CONF_GLOBAL)
43+
rdconf->rk_conf_ = rd_kafka_conf_new();
44+
else
45+
rdconf->rkt_conf_ = rd_kafka_topic_conf_new();
46+
47+
// Conf* rdconf = static_cast<Conf*>(RdKafka::Conf::create(type));
4048

4149
v8::MaybeLocal<v8::Array> _property_names = object->GetOwnPropertyNames(
4250
Nan::GetCurrentContext());
@@ -150,6 +158,10 @@ Conf::~Conf() {
150158
if (m_rebalance_cb) {
151159
delete m_rebalance_cb;
152160
}
161+
162+
if (m_offset_commit_cb) {
163+
delete m_offset_commit_cb;
164+
}
153165
}
154166

155167
} // namespace NodeKafka

src/config.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,20 @@
1111
#define SRC_CONFIG_H_
1212

1313
#include <nan.h>
14-
#include <iostream>
1514
#include <vector>
1615
#include <list>
1716
#include <string>
1817

1918
#include "rdkafkacpp.h"
19+
#include "rdkafkacpp_int.h"
2020
#include "src/common.h"
2121
#include "src/callbacks.h"
2222

2323
namespace NodeKafka {
2424

25-
class Conf : public RdKafka::Conf {
25+
class Conf : public RdKafka::ConfImpl {
26+
private:
27+
Conf(RdKafka::Conf::ConfType type) : RdKafka::ConfImpl(type) {} // NOLINT
2628
public:
2729
~Conf();
2830

src/connection.cc

+7
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,16 @@ Connection::Connection(Conf* gconfig, Conf* tconfig):
5454
// Perhaps node new methods should report this as an error? But there
5555
// isn't anything the user can do about it.
5656
m_gconfig->set("event_cb", &m_event_cb, errstr);
57+
58+
node::AddEnvironmentCleanupHook(v8::Isolate::GetCurrent(), delete_instance, this);
5759
}
5860

61+
void Connection::delete_instance(void* arg) {
62+
delete (static_cast<Connection*>(arg));
63+
}
64+
5965
Connection::~Connection() {
66+
node::RemoveEnvironmentCleanupHook(v8::Isolate::GetCurrent(), delete_instance, this);
6067
uv_rwlock_destroy(&m_connection_lock);
6168

6269
if (m_tconfig) {

src/connection.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#define SRC_CONNECTION_H_
1212

1313
#include <nan.h>
14-
#include <iostream>
1514
#include <string>
1615
#include <vector>
1716

@@ -78,6 +77,8 @@ class Connection : public Nan::ObjectWrap {
7877
Connection(Conf*, Conf*);
7978
~Connection();
8079

80+
static void delete_instance(void* arg);
81+
8182
static Nan::Persistent<v8::Function> constructor;
8283
static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
8384
static Baton rdkafkaErrorToBaton(RdKafka::Error* error);

src/errors.h

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#define SRC_ERRORS_H_
1212

1313
#include <nan.h>
14-
#include <iostream>
1514
#include <string>
1615

1716
#include "rdkafkacpp.h"

src/kafka-consumer.cc

+10-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <vector>
1212

1313
#include "src/kafka-consumer.h"
14+
#include "src/per-isolate-data.h"
1415
#include "src/workers.h"
1516

1617
using Nan::FunctionCallbackInfo;
@@ -36,6 +37,10 @@ KafkaConsumer::KafkaConsumer(Conf* gconfig, Conf* tconfig):
3637
m_consume_loop = nullptr;
3738
}
3839

40+
void KafkaConsumer::delete_instance(void* arg) {
41+
delete (static_cast<KafkaConsumer*>(arg));
42+
}
43+
3944
KafkaConsumer::~KafkaConsumer() {
4045
// We only want to run this if it hasn't been run already
4146
Disconnect();
@@ -558,8 +563,6 @@ std::string KafkaConsumer::RebalanceProtocol() {
558563
return consumer->rebalance_protocol();
559564
}
560565

561-
Nan::Persistent<v8::Function> KafkaConsumer::constructor;
562-
563566
void KafkaConsumer::Init(v8::Local<v8::Object> exports) {
564567
Nan::HandleScope scope;
565568

@@ -620,7 +623,8 @@ void KafkaConsumer::Init(v8::Local<v8::Object> exports) {
620623
Nan::SetPrototypeMethod(tpl, "commitSync", NodeCommitSync);
621624
Nan::SetPrototypeMethod(tpl, "offsetsStore", NodeOffsetsStore);
622625

623-
constructor.Reset((tpl->GetFunction(Nan::GetCurrentContext()))
626+
PerIsolateData::For(v8::Isolate::GetCurrent())->KafkaConsumerConstructor()
627+
.Reset((tpl->GetFunction(Nan::GetCurrentContext()))
624628
.ToLocalChecked());
625629
Nan::Set(exports, Nan::New("KafkaConsumer").ToLocalChecked(),
626630
(tpl->GetFunction(Nan::GetCurrentContext())).ToLocalChecked());
@@ -680,7 +684,8 @@ v8::Local<v8::Object> KafkaConsumer::NewInstance(v8::Local<v8::Value> arg) {
680684
const unsigned argc = 1;
681685

682686
v8::Local<v8::Value> argv[argc] = { arg };
683-
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
687+
v8::Local<v8::Function> cons = Nan::New<v8::Function>(
688+
PerIsolateData::For(v8::Isolate::GetCurrent())->KafkaConsumerConstructor());
684689
v8::Local<v8::Object> instance =
685690
Nan::NewInstance(cons, argc, argv).ToLocalChecked();
686691

@@ -1395,7 +1400,7 @@ NAN_METHOD(KafkaConsumer::NodeDisconnect) {
13951400
// cleanup the async worker
13961401
consumeLoop->WorkComplete();
13971402
consumeLoop->Destroy();
1398-
1403+
13991404
consumer->m_consume_loop = nullptr;
14001405
}
14011406

src/kafka-consumer.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
#include <nan.h>
1414
#include <uv.h>
15-
#include <iostream>
1615
#include <string>
1716
#include <vector>
1817

@@ -95,6 +94,8 @@ class KafkaConsumer : public Connection {
9594
KafkaConsumer(Conf *, Conf *);
9695
~KafkaConsumer();
9796

97+
static void delete_instance(void* arg);
98+
9899
private:
99100
static void part_list_print(const std::vector<RdKafka::TopicPartition*>&);
100101

@@ -103,7 +104,7 @@ class KafkaConsumer : public Connection {
103104
bool m_is_subscribed = false;
104105

105106
void* m_consume_loop = nullptr;
106-
107+
107108
// Node methods
108109
static NAN_METHOD(NodeConnect);
109110
static NAN_METHOD(NodeSubscribe);

src/per-isolate-data.cc

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* node-rdkafka - Node.js wrapper for RdKafka C/C++ library
3+
*
4+
* Copyright (c) 2016 Blizzard Entertainment
5+
*
6+
* This software may be modified and distributed under the terms
7+
* of the MIT license. See the LICENSE.txt file for details.
8+
*/
9+
10+
#include <mutex>
11+
#include <unordered_map>
12+
#include <utility>
13+
14+
#include "per-isolate-data.h"
15+
16+
namespace NodeKafka {
17+
18+
static std::unordered_map<v8::Isolate*, PerIsolateData> per_isolate_data_;
19+
static std::mutex mutex;
20+
21+
PerIsolateData* PerIsolateData::For(v8::Isolate* isolate) {
22+
const std::lock_guard<std::mutex> lock(mutex);
23+
auto maybe = per_isolate_data_.find(isolate);
24+
if (maybe != per_isolate_data_.end()) {
25+
return &maybe->second;
26+
}
27+
28+
per_isolate_data_.emplace(std::make_pair(isolate, PerIsolateData()));
29+
30+
auto pair = per_isolate_data_.find(isolate);
31+
auto perIsolateData = &pair->second;
32+
33+
node::AddEnvironmentCleanupHook(isolate, [](void* data) {
34+
const std::lock_guard<std::mutex> lock(mutex);
35+
per_isolate_data_.erase(static_cast<v8::Isolate*>(data));
36+
}, isolate);
37+
38+
return perIsolateData;
39+
}
40+
41+
Nan::Global<v8::Function>& PerIsolateData::AdminClientConstructor() {
42+
return admin_client_constructor;
43+
}
44+
45+
Nan::Global<v8::Function>& PerIsolateData::KafkaConsumerConstructor() {
46+
return kafka_consumer_constructor;
47+
}
48+
49+
Nan::Global<v8::Function>& PerIsolateData::KafkaProducerConstructor() {
50+
return kafka_producer_constructor;
51+
}
52+
53+
Nan::Global<v8::Function>& PerIsolateData::TopicConstructor() {
54+
return topic_constructor;
55+
}
56+
57+
} // namespace dd

src/per-isolate-data.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* node-rdkafka - Node.js wrapper for RdKafka C/C++ library
3+
*
4+
* Copyright (c) 2016 Blizzard Entertainment
5+
*
6+
* This software may be modified and distributed under the terms
7+
* of the MIT license. See the LICENSE.txt file for details.
8+
*/
9+
10+
#ifndef SRC_PER_ISOLATE_DATA_H_
11+
#define SRC_PER_ISOLATE_DATA_H_
12+
13+
#include <node.h>
14+
#include <nan.h>
15+
#include <v8.h>
16+
17+
namespace NodeKafka {
18+
19+
class PerIsolateData {
20+
private:
21+
Nan::Global<v8::Function> admin_client_constructor;
22+
Nan::Global<v8::Function> kafka_consumer_constructor;
23+
Nan::Global<v8::Function> kafka_producer_constructor;
24+
Nan::Global<v8::Function> topic_constructor;
25+
26+
PerIsolateData() {}
27+
28+
public:
29+
static PerIsolateData* For(v8::Isolate* isolate);
30+
31+
Nan::Global<v8::Function>& AdminClientConstructor();
32+
Nan::Global<v8::Function>& KafkaConsumerConstructor();
33+
Nan::Global<v8::Function>& KafkaProducerConstructor();
34+
Nan::Global<v8::Function>& TopicConstructor();
35+
};
36+
37+
} // namespace NodeKafka
38+
39+
#endif // SRC_PER_ISOLATE_DATA_H_

0 commit comments

Comments
 (0)