pulsar-client 1.6.2 → 1.8.0-rc1

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.
Files changed (74) hide show
  1. package/.asf.yaml +8 -1
  2. package/.github/PULL_REQUEST_TEMPLATE.md +65 -0
  3. package/.github/workflows/ci-build-release-napi.yml +195 -0
  4. package/.github/workflows/ci-pr-validation.yml +225 -0
  5. package/README.md +87 -68
  6. package/binding.gyp +41 -39
  7. package/{pulsar-test-service-stop.sh → build-support/dep-version.py} +4 -6
  8. package/build-support/download-release-artifacts.py +74 -0
  9. package/build-support/generate-source-archive.sh +28 -0
  10. package/build-support/install-cpp-client.sh +66 -0
  11. package/{pulsar-test-service-start.sh → build-support/pulsar-test-container-start.sh} +11 -21
  12. package/build-support/pulsar-test-service-start.sh +37 -0
  13. package/build-support/pulsar-test-service-stop.sh +32 -0
  14. package/{.github/workflows/nodejs.yml → build-support/sign-files.sh} +13 -12
  15. package/build-support/stage-release.sh +44 -0
  16. package/dependencies.yaml +28 -0
  17. package/docs/release-process.md +242 -0
  18. package/examples/consumer.js +1 -1
  19. package/examples/consumer_listener.js +1 -1
  20. package/examples/consumer_tls_auth.js +1 -1
  21. package/examples/custom_logger.js +60 -0
  22. package/examples/encryption-consumer.js +1 -1
  23. package/examples/encryption-producer.js +1 -1
  24. package/examples/producer.js +1 -1
  25. package/examples/producer_tls_auth.js +1 -1
  26. package/examples/reader.js +1 -1
  27. package/examples/reader_listener.js +1 -1
  28. package/index.d.ts +12 -4
  29. package/index.js +2 -1
  30. package/package.json +14 -12
  31. package/pkg/build-napi-inside-docker.sh +31 -0
  32. package/pkg/linux_glibc/Dockerfile +33 -0
  33. package/pkg/linux_musl/Dockerfile +32 -0
  34. package/pkg/load_test.js +30 -0
  35. package/pkg/mac/build-cpp-deps-lib.sh +186 -0
  36. package/pkg/mac/build-cpp-lib.sh +51 -0
  37. package/{docker-tests.sh → pkg/mac/common.sh} +13 -13
  38. package/pkg/windows/download-cpp-client.bat +12 -0
  39. package/pulsar-client-cpp.txt +2 -0
  40. package/src/AuthenticationAthenz.js +1 -1
  41. package/src/AuthenticationOauth2.js +1 -1
  42. package/src/AuthenticationTls.js +1 -1
  43. package/src/AuthenticationToken.js +1 -1
  44. package/src/Client.cc +84 -58
  45. package/src/Client.h +6 -4
  46. package/src/Consumer.cc +331 -234
  47. package/src/Consumer.h +11 -9
  48. package/src/ConsumerConfig.cc +54 -32
  49. package/src/ConsumerConfig.h +5 -6
  50. package/src/Message.cc +26 -29
  51. package/src/Message.h +4 -4
  52. package/src/MessageId.cc +19 -22
  53. package/src/MessageId.h +5 -6
  54. package/src/MessageListener.h +3 -8
  55. package/src/Producer.cc +116 -133
  56. package/src/Producer.h +3 -3
  57. package/src/ProducerConfig.cc +39 -22
  58. package/src/ProducerConfig.h +2 -2
  59. package/src/Reader.cc +147 -128
  60. package/src/Reader.h +5 -3
  61. package/src/ReaderConfig.cc +14 -20
  62. package/src/ReaderConfig.h +5 -6
  63. package/src/ReaderListener.h +2 -7
  64. package/src/SchemaInfo.cc +78 -0
  65. package/src/SchemaInfo.h +41 -0
  66. package/src/ThreadSafeDeferred.cc +98 -0
  67. package/src/ThreadSafeDeferred.h +85 -0
  68. package/src/pulsar-binding.js +8 -0
  69. package/tests/conf/standalone.conf +6 -0
  70. package/tests/consumer.test.js +2 -2
  71. package/tests/end_to_end.test.js +214 -2
  72. package/tests/producer.test.js +2 -2
  73. package/{run-unit-tests.sh → tests/run-unit-tests.sh} +5 -14
  74. package/pulsar-version.txt +0 -1
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ source $(dirname $0)/common.sh
22
+
23
+ cd $ROOT_DIR
24
+
25
+ pip3 install pyyaml
26
+
27
+ dep=$ROOT_DIR/build-support/dep-version.py
28
+ ZLIB_VERSION=$($dep zlib)
29
+ OPENSSL_VERSION=$($dep openssl)
30
+ BOOST_VERSION=$($dep boost)
31
+ PROTOBUF_VERSION=$($dep protobuf)
32
+ ZSTD_VERSION=$($dep zstd)
33
+ SNAPPY_VERSION=$($dep snappy)
34
+ CURL_VERSION=$($dep curl)
35
+
36
+ cd $MAC_BUILD_DIR/build
37
+
38
+ ##############################################################################
39
+ if [ ! -f zlib-${ZLIB_VERSION}.done ]; then
40
+ echo "Building ZLib"
41
+ curl -O -L https://zlib.net/fossils/zlib-${ZLIB_VERSION}.tar.gz
42
+ tar xfz zlib-$ZLIB_VERSION.tar.gz
43
+ pushd zlib-$ZLIB_VERSION
44
+ CFLAGS="-fPIC -O3 -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" ./configure --prefix=$PREFIX
45
+ make -j16
46
+ make install
47
+ popd
48
+
49
+ rm -rf zlib-$ZLIB_VERSION.tar.gz zlib-$ZLIB_VERSION
50
+ touch zlib-${ZLIB_VERSION}.done
51
+ else
52
+ echo "Using cached ZLib"
53
+ fi
54
+
55
+ ###############################################################################
56
+ OPENSSL_VERSION_UNDERSCORE=$(echo $OPENSSL_VERSION | sed 's/\./_/g')
57
+ if [ ! -f openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.done ]; then
58
+ echo "Building OpenSSL"
59
+ curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.tar.gz
60
+ tar xfz OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.tar.gz
61
+ pushd openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}
62
+ if [ $ARCH = 'arm64' ]; then
63
+ PLATFORM=darwin64-arm64-cc
64
+ else
65
+ PLATFORM=darwin64-x86_64-cc
66
+ fi
67
+ ./Configure --prefix=$PREFIX no-shared no-unit-test $PLATFORM
68
+ make -j8
69
+ make install_sw
70
+ popd
71
+
72
+ rm -rf OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.tar.gz openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}
73
+ touch openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.done
74
+ else
75
+ echo "Using cached OpenSSL"
76
+ fi
77
+
78
+ ###############################################################################
79
+ BOOST_VERSION_=${BOOST_VERSION//./_}
80
+ DIR=boost-src-${BOOST_VERSION}
81
+ if [ ! -f $DIR.done ]; then
82
+ echo "Building Boost"
83
+ curl -O -L https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_}.tar.gz
84
+ tar xfz boost_${BOOST_VERSION_}.tar.gz
85
+ rm -rf $DIR
86
+ mv boost_${BOOST_VERSION_} $DIR
87
+
88
+ pushd $DIR
89
+ ./bootstrap.sh --prefix=$PREFIX --with-libraries=system
90
+ ./b2 address-model=64 cxxflags="-fPIC -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
91
+ link=static threading=multi \
92
+ variant=release \
93
+ install
94
+ popd
95
+
96
+ rm -rf $DIR boost_${BOOST_VERSION_}.tar.gz
97
+ touch $DIR.done
98
+ else
99
+ echo "Using cached Boost"
100
+ fi
101
+
102
+ ###############################################################################
103
+ if [ ! -f protobuf-${PROTOBUF_VERSION}.done ]; then
104
+ echo "Building Protobuf"
105
+ curl -O -L https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
106
+ tar xfz protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
107
+ pushd protobuf-${PROTOBUF_VERSION}
108
+ CXXFLAGS="-fPIC -arch arm64 -arch x86_64 -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
109
+ ./configure --prefix=$PREFIX
110
+ make -j16 V=1
111
+ make install
112
+ popd
113
+
114
+ pushd install/lib
115
+ echo "Propose target arch static lib" ${ARCH}
116
+ mv libprotobuf.a libprotobuf_universal.a
117
+ lipo libprotobuf_universal.a -thin ${ARCH} -output libprotobuf.a
118
+ popd
119
+
120
+ rm -rf protobuf-${PROTOBUF_VERSION} protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
121
+ touch protobuf-${PROTOBUF_VERSION}.done
122
+ else
123
+ echo "Using cached Protobuf"
124
+ fi
125
+
126
+ ###############################################################################
127
+ if [ ! -f zstd-${ZSTD_VERSION}.done ]; then
128
+ echo "Building ZStd"
129
+ curl -O -L https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}/zstd-${ZSTD_VERSION}.tar.gz
130
+ tar xfz zstd-${ZSTD_VERSION}.tar.gz
131
+ pushd zstd-${ZSTD_VERSION}
132
+ CFLAGS="-fPIC -O3 -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
133
+ PREFIX=$PREFIX \
134
+ make -j16 -C lib install
135
+ popd
136
+
137
+ rm -rf zstd-${ZSTD_VERSION} zstd-${ZSTD_VERSION}.tar.gz
138
+ touch zstd-${ZSTD_VERSION}.done
139
+ else
140
+ echo "Using cached ZStd"
141
+ fi
142
+
143
+ ###############################################################################
144
+ if [ ! -f snappy-${SNAPPY_VERSION}.done ]; then
145
+ echo "Building Snappy"
146
+ curl -O -L https://github.com/google/snappy/archive/refs/tags/${SNAPPY_VERSION}.tar.gz
147
+ tar xfz ${SNAPPY_VERSION}.tar.gz
148
+ pushd snappy-${SNAPPY_VERSION}
149
+ CXXFLAGS="-fPIC -O3 -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
150
+ cmake . -DCMAKE_OSX_ARCHITECTURES=${ARCH} -DCMAKE_INSTALL_PREFIX=$PREFIX -DSNAPPY_BUILD_TESTS=OFF -DSNAPPY_BUILD_BENCHMARKS=OFF
151
+ make -j16
152
+ make install
153
+ touch .done
154
+ popd
155
+
156
+ rm -rf snappy-${SNAPPY_VERSION} ${SNAPPY_VERSION}.tar.gz
157
+ touch snappy-${SNAPPY_VERSION}.done
158
+ else
159
+ echo "Using cached Snappy"
160
+ fi
161
+
162
+ ###############################################################################
163
+ if [ ! -f curl-${CURL_VERSION}.done ]; then
164
+ echo "Building LibCurl"
165
+ CURL_VERSION_=${CURL_VERSION//./_}
166
+ curl -O -L https://github.com/curl/curl/releases/download/curl-${CURL_VERSION_}/curl-${CURL_VERSION}.tar.gz
167
+ tar xfz curl-${CURL_VERSION}.tar.gz
168
+ pushd curl-${CURL_VERSION}
169
+ CFLAGS="-fPIC -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
170
+ ./configure --with-ssl=$PREFIX \
171
+ --without-nghttp2 \
172
+ --without-libidn2 \
173
+ --disable-ldap \
174
+ --without-brotli \
175
+ --without-secure-transport \
176
+ --disable-ipv6 \
177
+ --prefix=$PREFIX \
178
+ --host=$ARCH-apple-darwin
179
+ make -j16 install
180
+ popd
181
+
182
+ rm -rf curl-${CURL_VERSION} curl-${CURL_VERSION}.tar.gz
183
+ touch curl-${CURL_VERSION}.done
184
+ else
185
+ echo "Using cached LibCurl"
186
+ fi
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ source $(dirname $0)/common.sh
22
+
23
+ PULSAR_DIR=${MAC_BUILD_DIR}/build-pulsar
24
+ PULSAR_PREFIX=${PULSAR_DIR}/install
25
+ mkdir -p $PULSAR_PREFIX
26
+ cd $PULSAR_DIR
27
+
28
+ ## Fetch from official release
29
+ curl -O -L "$CPP_CLIENT_BASE_URL"/apache-pulsar-client-cpp-${CPP_CLIENT_VERSION}.tar.gz
30
+ tar xfz apache-pulsar-client-cpp-${CPP_CLIENT_VERSION}.tar.gz
31
+ pushd apache-pulsar-client-cpp-${CPP_CLIENT_VERSION}
32
+ rm -f CMakeCache.txt
33
+ cmake . \
34
+ -DCMAKE_OSX_ARCHITECTURES=${ARCH} \
35
+ -DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET} \
36
+ -DCMAKE_INSTALL_PREFIX=$PULSAR_PREFIX \
37
+ -DCMAKE_BUILD_TYPE=Release \
38
+ -DCMAKE_PREFIX_PATH=$PREFIX \
39
+ -DCMAKE_INSTALL_LIBDIR=$PULSAR_PREFIX/lib \
40
+ -DLINK_STATIC=ON \
41
+ -DBUILD_TESTS=OFF \
42
+ -DBUILD_PYTHON_WRAPPER=OFF \
43
+ -DBUILD_DYNAMIC_LIB=OFF \
44
+ -DPROTOC_PATH=$PREFIX/bin/protoc
45
+ make -j16 install
46
+ mkdir -p $ROOT_DIR/pkg/lib/
47
+ cp -r lib/libpulsarwithdeps.a $ROOT_DIR/pkg/lib/
48
+ popd
49
+
50
+ rm -rf apache-pulsar-client-cpp-${CPP_CLIENT_VERSION}.tar.gz apache-pulsar-client-cpp-${CPP_CLIENT_VERSION}
51
+
@@ -1,4 +1,3 @@
1
- #!/bin/bash
2
1
  #
3
2
  # Licensed to the Apache Software Foundation (ASF) under one
4
3
  # or more contributor license agreements. See the NOTICE file
@@ -18,20 +17,21 @@
18
17
  # under the License.
19
18
  #
20
19
 
21
- ROOT_DIR=$(git rev-parse --show-toplevel)
22
- cd $ROOT_DIR
23
-
24
- BUILD_IMAGE_NAME="${BUILD_IMAGE_NAME:-apachepulsar/pulsar-build}"
25
- BUILD_IMAGE_VERSION="${BUILD_IMAGE_VERSION:-ubuntu-16.04}"
20
+ set -e -x
26
21
 
27
- IMAGE="$BUILD_IMAGE_NAME:$BUILD_IMAGE_VERSION"
22
+ if [ -z "$ARCH" ]; then
23
+ export ARCH=$(uname -m)
24
+ fi
28
25
 
29
- echo "---- Testing Pulsar node client using image $IMAGE"
26
+ export MACOSX_DEPLOYMENT_TARGET=11.0
30
27
 
31
- docker pull $IMAGE
28
+ MAC_BUILD_DIR=`cd $(dirname $0); pwd`
29
+ ROOT_DIR=$(git rev-parse --show-toplevel)
30
+ source $ROOT_DIR/pulsar-client-cpp.txt
32
31
 
33
- DOCKER_CMD="docker run -i -v $ROOT_DIR:/pulsar-client-node $IMAGE"
32
+ cd $MAC_BUILD_DIR
33
+ mkdir -p build
34
+ cd build
35
+ mkdir -p install
36
+ export PREFIX=`pwd`/install
34
37
 
35
- # Start Pulsar standalone instance
36
- # and execute the tests
37
- $DOCKER_CMD bash -c "cd /pulsar-client-node && ./run-unit-tests.sh"
@@ -0,0 +1,12 @@
1
+ cd %~dp0
2
+ set arch=%1
3
+ if "%arch%" == "" (
4
+ reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set arch=x86 || set arch=x64
5
+ )
6
+ for /F "delims== tokens=1,2" %%a in (..\..\pulsar-client-cpp.txt) do set "%%a=%%b"
7
+ curl -O -L %CPP_CLIENT_BASE_URL%/%arch%-windows-static.tar.gz
8
+ tar -xvzf %arch%-windows-static.tar.gz
9
+ move %arch%-windows-static pulsar-cpp
10
+ dir
11
+
12
+
@@ -0,0 +1,2 @@
1
+ CPP_CLIENT_BASE_URL=https://archive.apache.org/dist/pulsar/pulsar-client-cpp-3.1.0/
2
+ CPP_CLIENT_VERSION=3.1.0
@@ -17,7 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
 
20
- const PulsarBinding = require('bindings')('Pulsar');
20
+ const PulsarBinding = require('./pulsar-binding');
21
21
 
22
22
  class AuthenticationAthenz {
23
23
  constructor(params) {
@@ -16,7 +16,7 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
- const PulsarBinding = require('bindings')('Pulsar');
19
+ const PulsarBinding = require('./pulsar-binding');
20
20
 
21
21
  class AuthenticationOauth2 {
22
22
  constructor(params) {
@@ -17,7 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
 
20
- const PulsarBinding = require('bindings')('Pulsar');
20
+ const PulsarBinding = require('./pulsar-binding');
21
21
 
22
22
  class AuthenticationTls {
23
23
  constructor(params) {
@@ -17,7 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
 
20
- const PulsarBinding = require('bindings')('Pulsar');
20
+ const PulsarBinding = require('./pulsar-binding');
21
21
 
22
22
  class AuthenticationToken {
23
23
  constructor(params) {
package/src/Client.cc CHANGED
@@ -17,11 +17,12 @@
17
17
  * under the License.
18
18
  */
19
19
 
20
+ #include "Authentication.h"
20
21
  #include "Client.h"
21
22
  #include "Consumer.h"
22
23
  #include "Producer.h"
23
24
  #include "Reader.h"
24
- #include "Authentication.h"
25
+ #include "ThreadSafeDeferred.h"
25
26
  #include <pulsar/c/client.h>
26
27
  #include <pulsar/c/client_configuration.h>
27
28
  #include <pulsar/c/result.h>
@@ -40,6 +41,34 @@ static const std::string CFG_TLS_ALLOW_INSECURE = "tlsAllowInsecureConnection";
40
41
  static const std::string CFG_STATS_INTERVAL = "statsIntervalInSeconds";
41
42
  static const std::string CFG_LOG = "log";
42
43
 
44
+ LogCallback *Client::logCallback = nullptr;
45
+
46
+ void Client::SetLogHandler(const Napi::CallbackInfo &info) {
47
+ Napi::Env env = info.Env();
48
+ Napi::HandleScope scope(env);
49
+ Napi::Value jsFunction = info[0];
50
+
51
+ if (jsFunction.IsNull()) {
52
+ if (Client::logCallback != nullptr) {
53
+ Client::logCallback->callback.Release();
54
+ delete Client::logCallback;
55
+ Client::logCallback = nullptr;
56
+ }
57
+ } else if (jsFunction.IsFunction()) {
58
+ Napi::ThreadSafeFunction logFunction =
59
+ Napi::ThreadSafeFunction::New(env, jsFunction.As<Napi::Function>(), "Pulsar Logging", 0, 1);
60
+ logFunction.Unref(env);
61
+ if (Client::logCallback != nullptr) {
62
+ Client::logCallback->callback.Release();
63
+ } else {
64
+ Client::logCallback = new LogCallback();
65
+ }
66
+ Client::logCallback->callback = std::move(logFunction);
67
+ } else {
68
+ Napi::Error::New(env, "Client log handler must be a function or null").ThrowAsJavaScriptException();
69
+ }
70
+ }
71
+
43
72
  Napi::FunctionReference Client::constructor;
44
73
 
45
74
  Napi::Object Client::Init(Napi::Env env, Napi::Object exports) {
@@ -47,7 +76,8 @@ Napi::Object Client::Init(Napi::Env env, Napi::Object exports) {
47
76
 
48
77
  Napi::Function func = DefineClass(
49
78
  env, "Client",
50
- {InstanceMethod("createProducer", &Client::CreateProducer),
79
+ {StaticMethod("setLogHandler", &Client::SetLogHandler),
80
+ InstanceMethod("createProducer", &Client::CreateProducer),
51
81
  InstanceMethod("subscribe", &Client::Subscribe), InstanceMethod("createReader", &Client::CreateReader),
52
82
  InstanceMethod("close", &Client::Close)});
53
83
 
@@ -72,95 +102,95 @@ Client::Client(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Client>(info)
72
102
  }
73
103
  Napi::String serviceUrl = clientConfig.Get(CFG_SERVICE_URL).ToString();
74
104
 
75
- pulsar_client_configuration_t *cClientConfig = pulsar_client_configuration_create();
105
+ this->cClientConfig = std::shared_ptr<pulsar_client_configuration_t>(pulsar_client_configuration_create(),
106
+ pulsar_client_configuration_free);
107
+
108
+ // The logger can only be set once per process, so we will take control of it
109
+ pulsar_client_configuration_set_logger(cClientConfig.get(), &LogMessage, nullptr);
76
110
 
111
+ // log config option should be deprecated in favour of static setLogHandler method
77
112
  if (clientConfig.Has(CFG_LOG) && clientConfig.Get(CFG_LOG).IsFunction()) {
78
113
  Napi::ThreadSafeFunction logFunction = Napi::ThreadSafeFunction::New(
79
114
  env, clientConfig.Get(CFG_LOG).As<Napi::Function>(), "Pulsar Logging", 0, 1);
80
- this->logCallback = new LogCallback();
81
- this->logCallback->callback = logFunction;
115
+ logFunction.Unref(env);
82
116
 
83
- pulsar_client_configuration_set_logger(cClientConfig, &LogMessage, this->logCallback);
84
- } else {
85
- this->logCallback = nullptr;
117
+ if (Client::logCallback != nullptr) {
118
+ Client::logCallback->callback.Release();
119
+ } else {
120
+ Client::logCallback = new LogCallback();
121
+ }
122
+ Client::logCallback->callback = std::move(logFunction);
86
123
  }
87
124
 
88
125
  if (clientConfig.Has(CFG_AUTH) && clientConfig.Get(CFG_AUTH).IsObject()) {
89
126
  Napi::Object obj = clientConfig.Get(CFG_AUTH).ToObject();
90
127
  if (obj.Has(CFG_AUTH_PROP) && obj.Get(CFG_AUTH_PROP).IsObject()) {
91
128
  Authentication *auth = Authentication::Unwrap(obj.Get(CFG_AUTH_PROP).ToObject());
92
- pulsar_client_configuration_set_auth(cClientConfig, auth->GetCAuthentication());
129
+ pulsar_client_configuration_set_auth(cClientConfig.get(), auth->GetCAuthentication());
93
130
  }
94
131
  }
95
132
 
96
133
  if (clientConfig.Has(CFG_OP_TIMEOUT) && clientConfig.Get(CFG_OP_TIMEOUT).IsNumber()) {
97
134
  int32_t operationTimeoutSeconds = clientConfig.Get(CFG_OP_TIMEOUT).ToNumber().Int32Value();
98
135
  if (operationTimeoutSeconds > 0) {
99
- pulsar_client_configuration_set_operation_timeout_seconds(cClientConfig, operationTimeoutSeconds);
136
+ pulsar_client_configuration_set_operation_timeout_seconds(cClientConfig.get(), operationTimeoutSeconds);
100
137
  }
101
138
  }
102
139
 
103
140
  if (clientConfig.Has(CFG_IO_THREADS) && clientConfig.Get(CFG_IO_THREADS).IsNumber()) {
104
141
  int32_t ioThreads = clientConfig.Get(CFG_IO_THREADS).ToNumber().Int32Value();
105
142
  if (ioThreads > 0) {
106
- pulsar_client_configuration_set_io_threads(cClientConfig, ioThreads);
143
+ pulsar_client_configuration_set_io_threads(cClientConfig.get(), ioThreads);
107
144
  }
108
145
  }
109
146
 
110
147
  if (clientConfig.Has(CFG_LISTENER_THREADS) && clientConfig.Get(CFG_LISTENER_THREADS).IsNumber()) {
111
148
  int32_t messageListenerThreads = clientConfig.Get(CFG_LISTENER_THREADS).ToNumber().Int32Value();
112
149
  if (messageListenerThreads > 0) {
113
- pulsar_client_configuration_set_message_listener_threads(cClientConfig, messageListenerThreads);
150
+ pulsar_client_configuration_set_message_listener_threads(cClientConfig.get(), messageListenerThreads);
114
151
  }
115
152
  }
116
153
 
117
154
  if (clientConfig.Has(CFG_CONCURRENT_LOOKUP) && clientConfig.Get(CFG_CONCURRENT_LOOKUP).IsNumber()) {
118
155
  int32_t concurrentLookupRequest = clientConfig.Get(CFG_CONCURRENT_LOOKUP).ToNumber().Int32Value();
119
156
  if (concurrentLookupRequest > 0) {
120
- pulsar_client_configuration_set_concurrent_lookup_request(cClientConfig, concurrentLookupRequest);
157
+ pulsar_client_configuration_set_concurrent_lookup_request(cClientConfig.get(), concurrentLookupRequest);
121
158
  }
122
159
  }
123
160
 
124
161
  if (clientConfig.Has(CFG_USE_TLS) && clientConfig.Get(CFG_USE_TLS).IsBoolean()) {
125
162
  Napi::Boolean useTls = clientConfig.Get(CFG_USE_TLS).ToBoolean();
126
- pulsar_client_configuration_set_use_tls(cClientConfig, useTls.Value());
163
+ pulsar_client_configuration_set_use_tls(cClientConfig.get(), useTls.Value());
127
164
  }
128
165
 
129
166
  if (clientConfig.Has(CFG_TLS_TRUST_CERT) && clientConfig.Get(CFG_TLS_TRUST_CERT).IsString()) {
130
167
  Napi::String tlsTrustCertsFilePath = clientConfig.Get(CFG_TLS_TRUST_CERT).ToString();
131
- pulsar_client_configuration_set_tls_trust_certs_file_path(cClientConfig,
168
+ pulsar_client_configuration_set_tls_trust_certs_file_path(cClientConfig.get(),
132
169
  tlsTrustCertsFilePath.Utf8Value().c_str());
133
170
  }
134
171
 
135
172
  if (clientConfig.Has(CFG_TLS_VALIDATE_HOSTNAME) &&
136
173
  clientConfig.Get(CFG_TLS_VALIDATE_HOSTNAME).IsBoolean()) {
137
174
  Napi::Boolean tlsValidateHostname = clientConfig.Get(CFG_TLS_VALIDATE_HOSTNAME).ToBoolean();
138
- pulsar_client_configuration_set_validate_hostname(cClientConfig, tlsValidateHostname.Value());
175
+ pulsar_client_configuration_set_validate_hostname(cClientConfig.get(), tlsValidateHostname.Value());
139
176
  }
140
177
 
141
178
  if (clientConfig.Has(CFG_TLS_ALLOW_INSECURE) && clientConfig.Get(CFG_TLS_ALLOW_INSECURE).IsBoolean()) {
142
179
  Napi::Boolean tlsAllowInsecureConnection = clientConfig.Get(CFG_TLS_ALLOW_INSECURE).ToBoolean();
143
- pulsar_client_configuration_set_tls_allow_insecure_connection(cClientConfig,
180
+ pulsar_client_configuration_set_tls_allow_insecure_connection(cClientConfig.get(),
144
181
  tlsAllowInsecureConnection.Value());
145
182
  }
146
183
 
147
184
  if (clientConfig.Has(CFG_STATS_INTERVAL) && clientConfig.Get(CFG_STATS_INTERVAL).IsNumber()) {
148
185
  uint32_t statsIntervalInSeconds = clientConfig.Get(CFG_STATS_INTERVAL).ToNumber().Uint32Value();
149
- pulsar_client_configuration_set_stats_interval_in_seconds(cClientConfig, statsIntervalInSeconds);
186
+ pulsar_client_configuration_set_stats_interval_in_seconds(cClientConfig.get(), statsIntervalInSeconds);
150
187
  }
151
188
 
152
- this->cClient = pulsar_client_create(serviceUrl.Utf8Value().c_str(), cClientConfig);
153
- pulsar_client_configuration_free(cClientConfig);
154
- this->Ref();
189
+ this->cClient = std::shared_ptr<pulsar_client_t>(
190
+ pulsar_client_create(serviceUrl.Utf8Value().c_str(), cClientConfig.get()), pulsar_client_free);
155
191
  }
156
192
 
157
- Client::~Client() {
158
- pulsar_client_free(this->cClient);
159
- if (this->logCallback != nullptr) {
160
- this->logCallback->callback.Release();
161
- this->logCallback = nullptr;
162
- }
163
- }
193
+ Client::~Client() {}
164
194
 
165
195
  Napi::Value Client::CreateProducer(const Napi::CallbackInfo &info) {
166
196
  return Producer::NewInstance(info, this->cClient);
@@ -183,8 +213,13 @@ void LogMessageProxy(Napi::Env env, Napi::Function jsCallback, struct LogMessage
183
213
  jsCallback.Call({logLevel, file, line, message});
184
214
  }
185
215
 
186
- void LogMessage(pulsar_logger_level_t level, const char *file, int line, const char *message, void *ctx) {
187
- LogCallback *logCallback = (LogCallback *)ctx;
216
+ void Client::LogMessage(pulsar_logger_level_t level, const char *file, int line, const char *message,
217
+ void *ctx) {
218
+ LogCallback *logCallback = Client::logCallback;
219
+
220
+ if (logCallback == nullptr) {
221
+ return;
222
+ }
188
223
 
189
224
  if (logCallback->callback.Acquire() != napi_ok) {
190
225
  return;
@@ -196,33 +231,24 @@ void LogMessage(pulsar_logger_level_t level, const char *file, int line, const c
196
231
  logCallback->callback.Release();
197
232
  }
198
233
 
199
- class ClientCloseWorker : public Napi::AsyncWorker {
200
- public:
201
- ClientCloseWorker(const Napi::Promise::Deferred &deferred, pulsar_client_t *cClient)
202
- : AsyncWorker(Napi::Function::New(deferred.Promise().Env(), [](const Napi::CallbackInfo &info) {})),
203
- deferred(deferred),
204
- cClient(cClient) {}
205
- ~ClientCloseWorker() {}
206
- void Execute() {
207
- pulsar_result result = pulsar_client_close(this->cClient);
208
- if (result != pulsar_result_Ok) SetError(pulsar_result_str(result));
209
- }
210
- void OnOK() { this->deferred.Resolve(Env().Null()); }
211
- void OnError(const Napi::Error &e) {
212
- this->deferred.Reject(
213
- Napi::Error::New(Env(), std::string("Failed to close client: ") + e.Message()).Value());
214
- }
215
-
216
- private:
217
- Napi::Promise::Deferred deferred;
218
- pulsar_client_t *cClient;
219
- };
220
-
221
234
  Napi::Value Client::Close(const Napi::CallbackInfo &info) {
222
- this->Unref();
223
-
224
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
225
- ClientCloseWorker *wk = new ClientCloseWorker(deferred, this->cClient);
226
- wk->Queue();
227
- return deferred.Promise();
235
+ auto deferred = ThreadSafeDeferred::New(Env());
236
+ auto ctx = new ExtDeferredContext(deferred);
237
+
238
+ pulsar_client_close_async(
239
+ this->cClient.get(),
240
+ [](pulsar_result result, void *ctx) {
241
+ auto deferredContext = static_cast<ExtDeferredContext *>(ctx);
242
+ auto deferred = deferredContext->deferred;
243
+ delete deferredContext;
244
+
245
+ if (result != pulsar_result_Ok) {
246
+ deferred->Reject(std::string("Failed to close client: ") + pulsar_result_str(result));
247
+ } else {
248
+ deferred->Resolve(THREADSAFE_DEFERRED_RESOLVER(env.Null()));
249
+ }
250
+ },
251
+ ctx);
252
+
253
+ return deferred->Promise();
228
254
  }
package/src/Client.h CHANGED
@@ -37,20 +37,22 @@ struct LogCallback {
37
37
  Napi::ThreadSafeFunction callback;
38
38
  };
39
39
 
40
- void LogMessage(pulsar_logger_level_t level, const char *file, int line, const char *message, void *ctx);
41
-
42
40
  class Client : public Napi::ObjectWrap<Client> {
43
41
  public:
44
42
  static Napi::Object Init(Napi::Env env, Napi::Object exports);
43
+ static void SetLogHandler(const Napi::CallbackInfo &info);
45
44
 
46
45
  Client(const Napi::CallbackInfo &info);
47
46
  ~Client();
48
47
 
49
48
  private:
49
+ static LogCallback *logCallback;
50
50
  static Napi::FunctionReference constructor;
51
- pulsar_client_t *cClient;
52
- LogCallback *logCallback;
51
+ std::shared_ptr<pulsar_client_t> cClient;
52
+ std::shared_ptr<pulsar_client_configuration_t> cClientConfig;
53
53
 
54
+ static void LogMessage(pulsar_logger_level_t level, const char *file, int line, const char *message,
55
+ void *ctx);
54
56
  Napi::Value CreateProducer(const Napi::CallbackInfo &info);
55
57
  Napi::Value Subscribe(const Napi::CallbackInfo &info);
56
58
  Napi::Value CreateReader(const Napi::CallbackInfo &info);