@ohos-ports/confluentinc-kafka-javascript 1.10.0-beta.1
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/CHANGELOG.md +457 -0
- package/LICENSE.kafkajs +31 -0
- package/LICENSE.node-rdkafka +25 -0
- package/LICENSE.txt +20 -0
- package/README.md +133 -0
- package/binding.gyp +184 -0
- package/build/Release/confluent-kafka-javascript.node +0 -0
- package/build/deps/librdkafka++.so.1 +0 -0
- package/build/deps/librdkafka.Makefile +6 -0
- package/build/deps/librdkafka.so.1 +0 -0
- package/build/deps/librdkafka.target.mk +55 -0
- package/deps/librdkafka/.clang-format +136 -0
- package/deps/librdkafka/.clang-format-cpp +103 -0
- package/deps/librdkafka/.dir-locals.el +10 -0
- package/deps/librdkafka/.formatignore +35 -0
- package/deps/librdkafka/.gdbmacros +19 -0
- package/deps/librdkafka/CHANGELOG.md +2477 -0
- package/deps/librdkafka/CMakeLists.txt +291 -0
- package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
- package/deps/librdkafka/CONFIGURATION.md +212 -0
- package/deps/librdkafka/CONTRIBUTING.md +431 -0
- package/deps/librdkafka/Doxyfile +2375 -0
- package/deps/librdkafka/INTRODUCTION.md +2752 -0
- package/deps/librdkafka/LICENSE +26 -0
- package/deps/librdkafka/LICENSE.cjson +22 -0
- package/deps/librdkafka/LICENSE.crc32c +28 -0
- package/deps/librdkafka/LICENSE.fnv1a +18 -0
- package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
- package/deps/librdkafka/LICENSE.lz4 +26 -0
- package/deps/librdkafka/LICENSE.murmur2 +25 -0
- package/deps/librdkafka/LICENSE.nanopb +22 -0
- package/deps/librdkafka/LICENSE.opentelemetry +203 -0
- package/deps/librdkafka/LICENSE.pycrc +23 -0
- package/deps/librdkafka/LICENSE.queue +31 -0
- package/deps/librdkafka/LICENSE.regexp +5 -0
- package/deps/librdkafka/LICENSE.snappy +36 -0
- package/deps/librdkafka/LICENSE.tinycthread +26 -0
- package/deps/librdkafka/LICENSE.wingetopt +49 -0
- package/deps/librdkafka/LICENSES.txt +625 -0
- package/deps/librdkafka/Makefile +125 -0
- package/deps/librdkafka/README.md +201 -0
- package/deps/librdkafka/README.win32 +26 -0
- package/deps/librdkafka/STATISTICS.md +624 -0
- package/deps/librdkafka/configure +214 -0
- package/deps/librdkafka/configure.self +341 -0
- package/deps/librdkafka/dev-conf.sh +123 -0
- package/deps/librdkafka/lds-gen.py +73 -0
- package/deps/librdkafka/mainpage.doxy +40 -0
- package/deps/librdkafka/mklove/Makefile.base +329 -0
- package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
- package/deps/librdkafka/mklove/modules/configure.base +2484 -0
- package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
- package/deps/librdkafka/mklove/modules/configure.cc +186 -0
- package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
- package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
- package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
- package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
- package/deps/librdkafka/mklove/modules/configure.host +132 -0
- package/deps/librdkafka/mklove/modules/configure.lib +49 -0
- package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
- package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
- package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
- package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
- package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
- package/deps/librdkafka/mklove/modules/configure.pic +16 -0
- package/deps/librdkafka/mklove/modules/configure.socket +20 -0
- package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
- package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
- package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
- package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
- package/deps/librdkafka/service.yml +182 -0
- package/deps/librdkafka/src/CMakeLists.txt +379 -0
- package/deps/librdkafka/src/Makefile +105 -0
- package/deps/librdkafka/src/README.lz4.md +30 -0
- package/deps/librdkafka/src/cJSON.c +3191 -0
- package/deps/librdkafka/src/cJSON.h +306 -0
- package/deps/librdkafka/src/crc32c.c +430 -0
- package/deps/librdkafka/src/crc32c.h +38 -0
- package/deps/librdkafka/src/generate_proto.sh +66 -0
- package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
- package/deps/librdkafka/src/lz4.c +2727 -0
- package/deps/librdkafka/src/lz4.h +842 -0
- package/deps/librdkafka/src/lz4frame.c +2078 -0
- package/deps/librdkafka/src/lz4frame.h +692 -0
- package/deps/librdkafka/src/lz4frame_static.h +47 -0
- package/deps/librdkafka/src/lz4hc.c +1631 -0
- package/deps/librdkafka/src/lz4hc.h +413 -0
- package/deps/librdkafka/src/nanopb/pb.h +917 -0
- package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
- package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
- package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
- package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
- package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
- package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
- package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
- package/deps/librdkafka/src/queue.h +850 -0
- package/deps/librdkafka/src/rd.h +592 -0
- package/deps/librdkafka/src/rdaddr.c +255 -0
- package/deps/librdkafka/src/rdaddr.h +202 -0
- package/deps/librdkafka/src/rdatomic.h +262 -0
- package/deps/librdkafka/src/rdavg.h +260 -0
- package/deps/librdkafka/src/rdavl.c +210 -0
- package/deps/librdkafka/src/rdavl.h +250 -0
- package/deps/librdkafka/src/rdbase64.c +200 -0
- package/deps/librdkafka/src/rdbase64.h +43 -0
- package/deps/librdkafka/src/rdbuf.c +1884 -0
- package/deps/librdkafka/src/rdbuf.h +375 -0
- package/deps/librdkafka/src/rdcrc32.c +114 -0
- package/deps/librdkafka/src/rdcrc32.h +170 -0
- package/deps/librdkafka/src/rddl.c +179 -0
- package/deps/librdkafka/src/rddl.h +43 -0
- package/deps/librdkafka/src/rdendian.h +175 -0
- package/deps/librdkafka/src/rdfloat.h +67 -0
- package/deps/librdkafka/src/rdfnv1a.c +113 -0
- package/deps/librdkafka/src/rdfnv1a.h +35 -0
- package/deps/librdkafka/src/rdgz.c +120 -0
- package/deps/librdkafka/src/rdgz.h +46 -0
- package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
- package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
- package/deps/librdkafka/src/rdhttp.c +831 -0
- package/deps/librdkafka/src/rdhttp.h +101 -0
- package/deps/librdkafka/src/rdinterval.h +177 -0
- package/deps/librdkafka/src/rdkafka.c +7287 -0
- package/deps/librdkafka/src/rdkafka.h +11795 -0
- package/deps/librdkafka/src/rdkafka_admin.c +10165 -0
- package/deps/librdkafka/src/rdkafka_admin.h +658 -0
- package/deps/librdkafka/src/rdkafka_assignment.c +1282 -0
- package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
- package/deps/librdkafka/src/rdkafka_assignor.c +1800 -0
- package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
- package/deps/librdkafka/src/rdkafka_aux.c +409 -0
- package/deps/librdkafka/src/rdkafka_aux.h +174 -0
- package/deps/librdkafka/src/rdkafka_background.c +222 -0
- package/deps/librdkafka/src/rdkafka_broker.c +6736 -0
- package/deps/librdkafka/src/rdkafka_broker.h +851 -0
- package/deps/librdkafka/src/rdkafka_buf.c +543 -0
- package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
- package/deps/librdkafka/src/rdkafka_cert.c +576 -0
- package/deps/librdkafka/src/rdkafka_cert.h +62 -0
- package/deps/librdkafka/src/rdkafka_cgrp.c +8310 -0
- package/deps/librdkafka/src/rdkafka_cgrp.h +589 -0
- package/deps/librdkafka/src/rdkafka_conf.c +5177 -0
- package/deps/librdkafka/src/rdkafka_conf.h +746 -0
- package/deps/librdkafka/src/rdkafka_confval.h +97 -0
- package/deps/librdkafka/src/rdkafka_coord.c +623 -0
- package/deps/librdkafka/src/rdkafka_coord.h +132 -0
- package/deps/librdkafka/src/rdkafka_error.c +228 -0
- package/deps/librdkafka/src/rdkafka_error.h +80 -0
- package/deps/librdkafka/src/rdkafka_event.c +502 -0
- package/deps/librdkafka/src/rdkafka_event.h +126 -0
- package/deps/librdkafka/src/rdkafka_feature.c +898 -0
- package/deps/librdkafka/src/rdkafka_feature.h +104 -0
- package/deps/librdkafka/src/rdkafka_fetcher.c +3820 -0
- package/deps/librdkafka/src/rdkafka_fetcher.h +62 -0
- package/deps/librdkafka/src/rdkafka_header.c +220 -0
- package/deps/librdkafka/src/rdkafka_header.h +76 -0
- package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
- package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
- package/deps/librdkafka/src/rdkafka_int.h +1505 -0
- package/deps/librdkafka/src/rdkafka_interceptor.c +842 -0
- package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
- package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
- package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
- package/deps/librdkafka/src/rdkafka_metadata.c +2347 -0
- package/deps/librdkafka/src/rdkafka_metadata.h +350 -0
- package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
- package/deps/librdkafka/src/rdkafka_mock.c +4514 -0
- package/deps/librdkafka/src/rdkafka_mock.h +867 -0
- package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1877 -0
- package/deps/librdkafka/src/rdkafka_mock_handlers.c +5255 -0
- package/deps/librdkafka/src/rdkafka_mock_int.h +1005 -0
- package/deps/librdkafka/src/rdkafka_mock_sharegrp.c +1207 -0
- package/deps/librdkafka/src/rdkafka_msg.c +2619 -0
- package/deps/librdkafka/src/rdkafka_msg.h +629 -0
- package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
- package/deps/librdkafka/src/rdkafka_msgset.h +105 -0
- package/deps/librdkafka/src/rdkafka_msgset_reader.c +2099 -0
- package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
- package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
- package/deps/librdkafka/src/rdkafka_offset.h +150 -0
- package/deps/librdkafka/src/rdkafka_op.c +1219 -0
- package/deps/librdkafka/src/rdkafka_op.h +1065 -0
- package/deps/librdkafka/src/rdkafka_partition.c +5109 -0
- package/deps/librdkafka/src/rdkafka_partition.h +1215 -0
- package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
- package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
- package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
- package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
- package/deps/librdkafka/src/rdkafka_proto.h +739 -0
- package/deps/librdkafka/src/rdkafka_protocol.h +131 -0
- package/deps/librdkafka/src/rdkafka_queue.c +1351 -0
- package/deps/librdkafka/src/rdkafka_queue.h +1235 -0
- package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
- package/deps/librdkafka/src/rdkafka_request.c +7298 -0
- package/deps/librdkafka/src/rdkafka_request.h +761 -0
- package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
- package/deps/librdkafka/src/rdkafka_sasl.c +589 -0
- package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
- package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
- package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1827 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
- package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
- package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
- package/deps/librdkafka/src/rdkafka_share_acknowledgement.c +1445 -0
- package/deps/librdkafka/src/rdkafka_share_acknowledgement.h +373 -0
- package/deps/librdkafka/src/rdkafka_ssl.c +2235 -0
- package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
- package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
- package/deps/librdkafka/src/rdkafka_subscription.c +411 -0
- package/deps/librdkafka/src/rdkafka_telemetry.c +761 -0
- package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1307 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.c +1309 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.h +459 -0
- package/deps/librdkafka/src/rdkafka_timer.c +407 -0
- package/deps/librdkafka/src/rdkafka_timer.h +117 -0
- package/deps/librdkafka/src/rdkafka_topic.c +2382 -0
- package/deps/librdkafka/src/rdkafka_topic.h +369 -0
- package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
- package/deps/librdkafka/src/rdkafka_transport.h +99 -0
- package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
- package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
- package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
- package/deps/librdkafka/src/rdlist.c +593 -0
- package/deps/librdkafka/src/rdlist.h +444 -0
- package/deps/librdkafka/src/rdlog.c +89 -0
- package/deps/librdkafka/src/rdlog.h +41 -0
- package/deps/librdkafka/src/rdmap.c +508 -0
- package/deps/librdkafka/src/rdmap.h +492 -0
- package/deps/librdkafka/src/rdmurmur2.c +167 -0
- package/deps/librdkafka/src/rdmurmur2.h +35 -0
- package/deps/librdkafka/src/rdports.c +61 -0
- package/deps/librdkafka/src/rdports.h +38 -0
- package/deps/librdkafka/src/rdposix.h +250 -0
- package/deps/librdkafka/src/rdrand.c +151 -0
- package/deps/librdkafka/src/rdrand.h +72 -0
- package/deps/librdkafka/src/rdregex.c +156 -0
- package/deps/librdkafka/src/rdregex.h +43 -0
- package/deps/librdkafka/src/rdsignal.h +57 -0
- package/deps/librdkafka/src/rdstring.c +645 -0
- package/deps/librdkafka/src/rdstring.h +98 -0
- package/deps/librdkafka/src/rdsysqueue.h +404 -0
- package/deps/librdkafka/src/rdtime.h +356 -0
- package/deps/librdkafka/src/rdtypes.h +86 -0
- package/deps/librdkafka/src/rdunittest.c +564 -0
- package/deps/librdkafka/src/rdunittest.h +232 -0
- package/deps/librdkafka/src/rdunittest_acknowledge.c +1177 -0
- package/deps/librdkafka/src/rdunittest_fetcher.c +1211 -0
- package/deps/librdkafka/src/rdunittest_msgset_errors.c +1521 -0
- package/deps/librdkafka/src/rdvarint.c +134 -0
- package/deps/librdkafka/src/rdvarint.h +165 -0
- package/deps/librdkafka/src/rdwin32.h +382 -0
- package/deps/librdkafka/src/rdxxhash.c +1030 -0
- package/deps/librdkafka/src/rdxxhash.h +328 -0
- package/deps/librdkafka/src/regexp.c +1352 -0
- package/deps/librdkafka/src/regexp.h +41 -0
- package/deps/librdkafka/src/snappy.c +1866 -0
- package/deps/librdkafka/src/snappy.h +62 -0
- package/deps/librdkafka/src/snappy_compat.h +138 -0
- package/deps/librdkafka/src/statistics_schema.json +444 -0
- package/deps/librdkafka/src/tinycthread.c +932 -0
- package/deps/librdkafka/src/tinycthread.h +503 -0
- package/deps/librdkafka/src/tinycthread_extra.c +210 -0
- package/deps/librdkafka/src/tinycthread_extra.h +218 -0
- package/deps/librdkafka/src/win32_config.h +58 -0
- package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
- package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
- package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
- package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
- package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
- package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
- package/deps/librdkafka/src-cpp/Makefile +55 -0
- package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
- package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
- package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
- package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
- package/deps/librdkafka/src-cpp/README.md +16 -0
- package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
- package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
- package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
- package/deps/librdkafka/tests/0000-unittests.c +72 -0
- package/deps/librdkafka/tests/0001-multiobj.c +102 -0
- package/deps/librdkafka/tests/0002-unkpart.c +244 -0
- package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
- package/deps/librdkafka/tests/0004-conf.c +934 -0
- package/deps/librdkafka/tests/0005-order.c +133 -0
- package/deps/librdkafka/tests/0006-symbols.c +163 -0
- package/deps/librdkafka/tests/0007-autotopic.c +136 -0
- package/deps/librdkafka/tests/0008-reqacks.c +179 -0
- package/deps/librdkafka/tests/0009-mock_cluster.c +272 -0
- package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
- package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
- package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
- package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
- package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
- package/deps/librdkafka/tests/0016-client_swname.c +181 -0
- package/deps/librdkafka/tests/0017-compression.c +140 -0
- package/deps/librdkafka/tests/0018-cgrp_term.c +444 -0
- package/deps/librdkafka/tests/0019-list_groups.c +289 -0
- package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
- package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
- package/deps/librdkafka/tests/0022-consume_batch.c +331 -0
- package/deps/librdkafka/tests/0025-timers.c +147 -0
- package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
- package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
- package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
- package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
- package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
- package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
- package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
- package/deps/librdkafka/tests/0035-api_version.c +73 -0
- package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
- package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
- package/deps/librdkafka/tests/0038-performance.c +121 -0
- package/deps/librdkafka/tests/0039-event.c +284 -0
- package/deps/librdkafka/tests/0040-io_event.c +257 -0
- package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
- package/deps/librdkafka/tests/0042-many_topics.c +252 -0
- package/deps/librdkafka/tests/0043-no_connection.c +77 -0
- package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
- package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
- package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
- package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
- package/deps/librdkafka/tests/0048-partitioner.c +283 -0
- package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
- package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
- package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
- package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
- package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
- package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
- package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
- package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
- package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
- package/deps/librdkafka/tests/0058-log.cpp +123 -0
- package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
- package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
- package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
- package/deps/librdkafka/tests/0062-stats_event.c +126 -0
- package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
- package/deps/librdkafka/tests/0064-interceptors.c +529 -0
- package/deps/librdkafka/tests/0065-yield.cpp +140 -0
- package/deps/librdkafka/tests/0066-plugins.cpp +143 -0
- package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
- package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
- package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
- package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
- package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
- package/deps/librdkafka/tests/0073-headers.c +381 -0
- package/deps/librdkafka/tests/0074-producev.c +87 -0
- package/deps/librdkafka/tests/0075-retry.c +290 -0
- package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
- package/deps/librdkafka/tests/0077-compaction.c +366 -0
- package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
- package/deps/librdkafka/tests/0079-fork.c +93 -0
- package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
- package/deps/librdkafka/tests/0081-admin.c +5633 -0
- package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
- package/deps/librdkafka/tests/0083-cb_event.c +233 -0
- package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
- package/deps/librdkafka/tests/0085-headers.cpp +392 -0
- package/deps/librdkafka/tests/0086-purge.c +368 -0
- package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
- package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
- package/deps/librdkafka/tests/0090-idempotence.c +171 -0
- package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
- package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
- package/deps/librdkafka/tests/0093-holb.c +200 -0
- package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
- package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
- package/deps/librdkafka/tests/0097-ssl_verify.cpp +674 -0
- package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
- package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
- package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
- package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
- package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
- package/deps/librdkafka/tests/0103-transactions.c +1383 -0
- package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
- package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
- package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
- package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
- package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
- package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
- package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
- package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
- package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
- package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
- package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
- package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
- package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
- package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
- package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
- package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
- package/deps/librdkafka/tests/0121-clusterid.c +115 -0
- package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
- package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
- package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
- package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
- package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +1164 -0
- package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
- package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +217 -0
- package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
- package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
- package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
- package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
- package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
- package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
- package/deps/librdkafka/tests/0135-sasl_credentials.cpp +279 -0
- package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
- package/deps/librdkafka/tests/0137-barrier_batch_consume.c +752 -0
- package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
- package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
- package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
- package/deps/librdkafka/tests/0142-reauthentication.c +931 -0
- package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
- package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
- package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
- package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
- package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +1210 -0
- package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +569 -0
- package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
- package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
- package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
- package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
- package/deps/librdkafka/tests/0153-memberid.c +128 -0
- package/deps/librdkafka/tests/0155-share_group_heartbeat_mock.c +2695 -0
- package/deps/librdkafka/tests/0156-share_consumer_fetch_mock.c +1551 -0
- package/deps/librdkafka/tests/0157-share_consumer_ack_mock.c +1788 -0
- package/deps/librdkafka/tests/0158-share_consumer_transactions_mock.c +467 -0
- package/deps/librdkafka/tests/0170-share_consumer_subscription.c +2192 -0
- package/deps/librdkafka/tests/0171-share_consumer_consume.c +2150 -0
- package/deps/librdkafka/tests/0172-share_consumer_acknowledge.c +1919 -0
- package/deps/librdkafka/tests/0173-share_consumer_commit_async.c +2735 -0
- package/deps/librdkafka/tests/0174-share_consumer_concurrency.c +1434 -0
- package/deps/librdkafka/tests/0175-share_consumer_groups.c +574 -0
- package/deps/librdkafka/tests/0176-share_consumer_commit_sync.c +2986 -0
- package/deps/librdkafka/tests/0177-share_consumer_transactions.c +1815 -0
- package/deps/librdkafka/tests/0178-share_consumer_close.c +2102 -0
- package/deps/librdkafka/tests/0179-share_consumer_destroy.c +2482 -0
- package/deps/librdkafka/tests/0180-share_consumer_config.c +1677 -0
- package/deps/librdkafka/tests/0181-share_consumer_topic_delete.c +354 -0
- package/deps/librdkafka/tests/0182-share_consumer_error_handling_mock.c +3358 -0
- package/deps/librdkafka/tests/0183-share_consumer_leader_change_mock.c +1234 -0
- package/deps/librdkafka/tests/0184-share_consumer_topic_recreate.c +1356 -0
- package/deps/librdkafka/tests/0185-share_consumer_max_poll_interval.c +557 -0
- package/deps/librdkafka/tests/0186-share_consumer_fatal_error.c +360 -0
- package/deps/librdkafka/tests/0190-share_consumer_telemetry.c +387 -0
- package/deps/librdkafka/tests/1000-unktopic.c +164 -0
- package/deps/librdkafka/tests/8000-idle.cpp +60 -0
- package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
- package/deps/librdkafka/tests/CMakeLists.txt +193 -0
- package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
- package/deps/librdkafka/tests/Makefile +182 -0
- package/deps/librdkafka/tests/README.md +514 -0
- package/deps/librdkafka/tests/autotest.sh +33 -0
- package/deps/librdkafka/tests/backtrace.gdb +30 -0
- package/deps/librdkafka/tests/broker_version_tests.py +315 -0
- package/deps/librdkafka/tests/buildbox.sh +17 -0
- package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
- package/deps/librdkafka/tests/cluster_testing.py +203 -0
- package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
- package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
- package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
- package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +50 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
- package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
- package/deps/librdkafka/tests/fuzzers/README.md +31 -0
- package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
- package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
- package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
- package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
- package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
- package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
- package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
- package/deps/librdkafka/tests/java/Makefile +13 -0
- package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
- package/deps/librdkafka/tests/java/README.md +14 -0
- package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
- package/deps/librdkafka/tests/java/run-class.sh +11 -0
- package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
- package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
- package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
- package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
- package/deps/librdkafka/tests/performance_plot.py +115 -0
- package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
- package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
- package/deps/librdkafka/tests/requirements.txt +2 -0
- package/deps/librdkafka/tests/run-all-tests.sh +81 -0
- package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-test-batches.py +157 -0
- package/deps/librdkafka/tests/run-test.sh +141 -0
- package/deps/librdkafka/tests/rusage.c +249 -0
- package/deps/librdkafka/tests/sasl_test.py +289 -0
- package/deps/librdkafka/tests/scenarios/README.md +6 -0
- package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
- package/deps/librdkafka/tests/scenarios/default.json +5 -0
- package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
- package/deps/librdkafka/tests/share_telemetry_verify/share-otel-collector-config.yaml +28 -0
- package/deps/librdkafka/tests/sockem.c +801 -0
- package/deps/librdkafka/tests/sockem.h +85 -0
- package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
- package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
- package/deps/librdkafka/tests/test.c +8376 -0
- package/deps/librdkafka/tests/test.conf.example +27 -0
- package/deps/librdkafka/tests/test.h +1150 -0
- package/deps/librdkafka/tests/testcpp.cpp +131 -0
- package/deps/librdkafka/tests/testcpp.h +388 -0
- package/deps/librdkafka/tests/testshared.h +416 -0
- package/deps/librdkafka/tests/tools/README.md +4 -0
- package/deps/librdkafka/tests/tools/stats/README.md +21 -0
- package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
- package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
- package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
- package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
- package/deps/librdkafka/tests/trivup/trivup-0.15.0.tar.gz +0 -0
- package/deps/librdkafka/tests/until-fail.sh +87 -0
- package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
- package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
- package/deps/librdkafka/vcpkg.json +23 -0
- package/deps/librdkafka/win32/README.md +5 -0
- package/deps/librdkafka/win32/build-package.bat +3 -0
- package/deps/librdkafka/win32/build.bat +19 -0
- package/deps/librdkafka/win32/common.vcxproj +84 -0
- package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
- package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
- package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
- package/deps/librdkafka/win32/librdkafka.sln +226 -0
- package/deps/librdkafka/win32/librdkafka.vcxproj +282 -0
- package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
- package/deps/librdkafka/win32/msbuild.ps1 +58 -0
- package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
- package/deps/librdkafka/win32/package-zip.ps1 +46 -0
- package/deps/librdkafka/win32/packages/repositories.config +4 -0
- package/deps/librdkafka/win32/push-package.bat +4 -0
- package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
- package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
- package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
- package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
- package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
- package/deps/librdkafka/win32/tests/test.conf.example +25 -0
- package/deps/librdkafka/win32/tests/tests.vcxproj +278 -0
- package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
- package/deps/librdkafka/win32/wingetopt.c +564 -0
- package/deps/librdkafka/win32/wingetopt.h +101 -0
- package/deps/librdkafka/win32/wintime.h +33 -0
- package/deps/librdkafka.gyp +83 -0
- package/deps/windows-install.py +80 -0
- package/index.d.ts +3 -0
- package/lib/admin.js +732 -0
- package/lib/client.js +679 -0
- package/lib/error.js +501 -0
- package/lib/index.js +8 -0
- package/lib/kafka-consumer-stream.js +399 -0
- package/lib/kafka-consumer.js +798 -0
- package/lib/kafkajs/_admin.js +1052 -0
- package/lib/kafkajs/_common.js +887 -0
- package/lib/kafkajs/_consumer.js +2156 -0
- package/lib/kafkajs/_consumer_cache.js +310 -0
- package/lib/kafkajs/_error.js +298 -0
- package/lib/kafkajs/_kafka.js +125 -0
- package/lib/kafkajs/_linked-list.js +220 -0
- package/lib/kafkajs/_producer.js +863 -0
- package/lib/kafkajs/index.js +5 -0
- package/lib/producer/high-level-producer.js +400 -0
- package/lib/producer-stream.js +337 -0
- package/lib/producer.js +405 -0
- package/lib/rdkafka.js +44 -0
- package/lib/tools/ref-counter.js +53 -0
- package/lib/topic-partition.js +91 -0
- package/lib/topic.js +43 -0
- package/lib/util.js +55 -0
- package/librdkafka.js +12 -0
- package/package.json +85 -0
- package/shim/source_location +54 -0
- package/src/admin.cc +1597 -0
- package/src/admin.h +112 -0
- package/src/binding.cc +76 -0
- package/src/binding.h +25 -0
- package/src/callbacks.cc +676 -0
- package/src/callbacks.h +302 -0
- package/src/common.cc +1628 -0
- package/src/common.h +192 -0
- package/src/config.cc +219 -0
- package/src/config.h +61 -0
- package/src/connection.cc +703 -0
- package/src/connection.h +117 -0
- package/src/errors.cc +119 -0
- package/src/errors.h +60 -0
- package/src/kafka-consumer.cc +1539 -0
- package/src/kafka-consumer.h +147 -0
- package/src/producer.cc +917 -0
- package/src/producer.h +124 -0
- package/src/topic.cc +173 -0
- package/src/topic.h +54 -0
- package/src/workers.cc +1714 -0
- package/src/workers.h +690 -0
- package/types/config.d.ts +1269 -0
- package/types/errors.d.ts +373 -0
- package/types/kafkajs.d.ts +568 -0
- package/types/rdkafka.d.ts +571 -0
- package/util/configure.js +32 -0
- package/util/generate-docs.sh +18 -0
- package/util/get-env.js +6 -0
- package/util/test-compile.js +11 -0
- package/util/test-producer-delivery.js +100 -0
package/src/admin.cc
ADDED
|
@@ -0,0 +1,1597 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* confluent-kafka-javascript - Node.js wrapper for RdKafka C/C++ library
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-2023 Blizzard Entertainment
|
|
5
|
+
* (c) 2023 Confluent, Inc.
|
|
6
|
+
*
|
|
7
|
+
* This software may be modified and distributed under the terms
|
|
8
|
+
* of the MIT license. See the LICENSE.txt file for details.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include "src/admin.h"
|
|
12
|
+
|
|
13
|
+
#include <math.h>
|
|
14
|
+
#include <string>
|
|
15
|
+
#include <vector>
|
|
16
|
+
|
|
17
|
+
#include "src/workers.h"
|
|
18
|
+
|
|
19
|
+
using Nan::FunctionCallbackInfo;
|
|
20
|
+
|
|
21
|
+
namespace NodeKafka {
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @brief AdminClient v8 wrapped object.
|
|
25
|
+
*
|
|
26
|
+
* Specializes the connection to wrap a producer object through compositional
|
|
27
|
+
* inheritence. Establishes its prototype in node through `Init`
|
|
28
|
+
*
|
|
29
|
+
* @sa RdKafka::Handle
|
|
30
|
+
* @sa NodeKafka::Client
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
AdminClient::AdminClient(Conf *gconfig) : Connection(gconfig, NULL) {}
|
|
34
|
+
|
|
35
|
+
AdminClient::AdminClient(Connection *connection) : Connection(connection) {}
|
|
36
|
+
|
|
37
|
+
AdminClient::~AdminClient() {
|
|
38
|
+
Disconnect();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Baton AdminClient::Connect() {
|
|
42
|
+
if (IsConnected()) {
|
|
43
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* We should never fail the IsConnected check when we have an underlying
|
|
47
|
+
* client, as it should always be connected. */
|
|
48
|
+
if (m_has_underlying) {
|
|
49
|
+
return Baton(RdKafka::ERR__STATE,
|
|
50
|
+
"Existing client is not connected, and dependent client "
|
|
51
|
+
"cannot initiate connection.");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
Baton baton = setupSaslOAuthBearerConfig();
|
|
55
|
+
if (baton.err() != RdKafka::ERR_NO_ERROR) {
|
|
56
|
+
return baton;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
std::string errstr;
|
|
60
|
+
{
|
|
61
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
62
|
+
m_client = RdKafka::Producer::create(m_gconfig, errstr);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!m_client || !errstr.empty()) {
|
|
66
|
+
DeactivateDispatchers();
|
|
67
|
+
return Baton(RdKafka::ERR__STATE, errstr);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Set the client name at the first possible opportunity for logging. */
|
|
71
|
+
m_event_cb.dispatcher.SetClientName(m_client->name());
|
|
72
|
+
|
|
73
|
+
baton = setupSaslOAuthBearerBackgroundQueue();
|
|
74
|
+
if (baton.err() != RdKafka::ERR_NO_ERROR) {
|
|
75
|
+
DeactivateDispatchers();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
std::string stats_interval_ms;
|
|
79
|
+
if (this->m_gconfig->get("statistics.interval.ms", stats_interval_ms) ==
|
|
80
|
+
RdKafka::Conf::CONF_OK) {
|
|
81
|
+
Connection::SetPollInBackground(true);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return baton;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Baton AdminClient::Disconnect() {
|
|
88
|
+
/* Dependent AdminClients don't need to do anything. We block the call to
|
|
89
|
+
* disconnect in JavaScript, but the destructor of AdminClient might trigger
|
|
90
|
+
* this call. */
|
|
91
|
+
if (m_has_underlying) {
|
|
92
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (IsConnected()) {
|
|
96
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
97
|
+
|
|
98
|
+
DeactivateDispatchers();
|
|
99
|
+
|
|
100
|
+
delete m_client;
|
|
101
|
+
m_client = NULL;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Nan::Persistent<v8::Function> AdminClient::constructor;
|
|
108
|
+
|
|
109
|
+
void AdminClient::Init(v8::Local<v8::Object> exports) {
|
|
110
|
+
Nan::HandleScope scope;
|
|
111
|
+
|
|
112
|
+
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
|
|
113
|
+
tpl->SetClassName(Nan::New("AdminClient").ToLocalChecked());
|
|
114
|
+
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
|
115
|
+
|
|
116
|
+
// Inherited from NodeKafka::Connection
|
|
117
|
+
Nan::SetPrototypeMethod(tpl, "configureCallbacks", NodeConfigureCallbacks);
|
|
118
|
+
Nan::SetPrototypeMethod(tpl, "name", NodeName);
|
|
119
|
+
|
|
120
|
+
// Admin client operations
|
|
121
|
+
Nan::SetPrototypeMethod(tpl, "createTopic", NodeCreateTopic);
|
|
122
|
+
Nan::SetPrototypeMethod(tpl, "deleteTopic", NodeDeleteTopic);
|
|
123
|
+
Nan::SetPrototypeMethod(tpl, "createPartitions", NodeCreatePartitions);
|
|
124
|
+
Nan::SetPrototypeMethod(tpl, "deleteRecords", NodeDeleteRecords);
|
|
125
|
+
Nan::SetPrototypeMethod(tpl, "describeTopics", NodeDescribeTopics);
|
|
126
|
+
Nan::SetPrototypeMethod(tpl, "listOffsets", NodeListOffsets);
|
|
127
|
+
|
|
128
|
+
// Consumer group related operations
|
|
129
|
+
Nan::SetPrototypeMethod(tpl, "listGroups", NodeListGroups);
|
|
130
|
+
Nan::SetPrototypeMethod(tpl, "describeGroups", NodeDescribeGroups);
|
|
131
|
+
Nan::SetPrototypeMethod(tpl, "deleteGroups", NodeDeleteGroups);
|
|
132
|
+
Nan::SetPrototypeMethod(tpl, "listConsumerGroupOffsets",
|
|
133
|
+
NodeListConsumerGroupOffsets);
|
|
134
|
+
|
|
135
|
+
Nan::SetPrototypeMethod(tpl, "connect", NodeConnect);
|
|
136
|
+
Nan::SetPrototypeMethod(tpl, "disconnect", NodeDisconnect);
|
|
137
|
+
Nan::SetPrototypeMethod(tpl, "setSaslCredentials", NodeSetSaslCredentials);
|
|
138
|
+
Nan::SetPrototypeMethod(tpl, "getMetadata", NodeGetMetadata);
|
|
139
|
+
Nan::SetPrototypeMethod(tpl, "setOAuthBearerToken", NodeSetOAuthBearerToken);
|
|
140
|
+
Nan::SetPrototypeMethod(tpl, "setOAuthBearerTokenFailure",
|
|
141
|
+
NodeSetOAuthBearerTokenFailure);
|
|
142
|
+
|
|
143
|
+
constructor.Reset(
|
|
144
|
+
(tpl->GetFunction(Nan::GetCurrentContext())).ToLocalChecked());
|
|
145
|
+
Nan::Set(exports, Nan::New("AdminClient").ToLocalChecked(),
|
|
146
|
+
tpl->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
void AdminClient::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
|
150
|
+
if (!info.IsConstructCall()) {
|
|
151
|
+
return Nan::ThrowError("non-constructor invocation not supported");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (info.Length() < 1) {
|
|
155
|
+
return Nan::ThrowError("You must supply a global configuration or a preexisting client"); // NOLINT
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
Connection *connection = NULL;
|
|
159
|
+
Conf *gconfig = NULL;
|
|
160
|
+
AdminClient *client = NULL;
|
|
161
|
+
|
|
162
|
+
if (info.Length() >= 3 && !info[2]->IsNull() && !info[2]->IsUndefined()) {
|
|
163
|
+
if (!info[2]->IsObject()) {
|
|
164
|
+
return Nan::ThrowError("Third argument, if provided, must be a client object"); // NOLINT
|
|
165
|
+
}
|
|
166
|
+
// We check whether this is a wrapped object within the calling JavaScript
|
|
167
|
+
// code, so it's safe to unwrap it here. We Unwrap it directly into a
|
|
168
|
+
// Connection object, since it's OK to unwrap into the parent class.
|
|
169
|
+
connection = ObjectWrap::Unwrap<Connection>(
|
|
170
|
+
info[2]->ToObject(Nan::GetCurrentContext()).ToLocalChecked());
|
|
171
|
+
client = new AdminClient(connection);
|
|
172
|
+
} else {
|
|
173
|
+
if (!info[0]->IsObject()) {
|
|
174
|
+
return Nan::ThrowError("Global configuration data must be specified");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
std::string errstr;
|
|
178
|
+
gconfig = Conf::create(
|
|
179
|
+
RdKafka::Conf::CONF_GLOBAL,
|
|
180
|
+
(info[0]->ToObject(Nan::GetCurrentContext())).ToLocalChecked(), errstr);
|
|
181
|
+
|
|
182
|
+
if (!gconfig) {
|
|
183
|
+
return Nan::ThrowError(errstr.c_str());
|
|
184
|
+
}
|
|
185
|
+
client = new AdminClient(gconfig);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Wrap it
|
|
189
|
+
client->Wrap(info.This());
|
|
190
|
+
|
|
191
|
+
// Then there is some weird initialization that happens
|
|
192
|
+
// basically it sets the configuration data
|
|
193
|
+
// we don't need to do that because we lazy load it
|
|
194
|
+
|
|
195
|
+
info.GetReturnValue().Set(info.This());
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
v8::Local<v8::Object> AdminClient::NewInstance(v8::Local<v8::Value> arg) {
|
|
199
|
+
Nan::EscapableHandleScope scope;
|
|
200
|
+
|
|
201
|
+
const unsigned argc = 1;
|
|
202
|
+
|
|
203
|
+
v8::Local<v8::Value> argv[argc] = { arg };
|
|
204
|
+
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
|
|
205
|
+
v8::Local<v8::Object> instance =
|
|
206
|
+
Nan::NewInstance(cons, argc, argv).ToLocalChecked();
|
|
207
|
+
|
|
208
|
+
return scope.Escape(instance);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Poll for a particular event on a queue.
|
|
213
|
+
*
|
|
214
|
+
* This will keep polling until it gets an event of that type,
|
|
215
|
+
* given the number of tries and a timeout
|
|
216
|
+
*/
|
|
217
|
+
rd_kafka_event_t* PollForEvent(
|
|
218
|
+
rd_kafka_queue_t * topic_rkqu,
|
|
219
|
+
rd_kafka_event_type_t event_type,
|
|
220
|
+
int timeout_ms) {
|
|
221
|
+
// Initiate exponential timeout
|
|
222
|
+
int attempts = 1;
|
|
223
|
+
int exp_timeout_ms = timeout_ms;
|
|
224
|
+
if (timeout_ms > 2000) {
|
|
225
|
+
// measure optimal number of attempts
|
|
226
|
+
attempts = log10(timeout_ms / 1000) / log10(2) + 1;
|
|
227
|
+
// measure initial exponential timeout based on attempts
|
|
228
|
+
exp_timeout_ms = timeout_ms / (pow(2, attempts) - 1);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
rd_kafka_event_t * event_response = nullptr;
|
|
232
|
+
|
|
233
|
+
// Poll the event queue until we get it
|
|
234
|
+
do {
|
|
235
|
+
// free previously fetched event
|
|
236
|
+
rd_kafka_event_destroy(event_response);
|
|
237
|
+
// poll and update attempts and exponential timeout
|
|
238
|
+
event_response = rd_kafka_queue_poll(topic_rkqu, exp_timeout_ms);
|
|
239
|
+
attempts = attempts - 1;
|
|
240
|
+
exp_timeout_ms = 2 * exp_timeout_ms;
|
|
241
|
+
} while (
|
|
242
|
+
rd_kafka_event_type(event_response) != event_type &&
|
|
243
|
+
attempts > 0);
|
|
244
|
+
|
|
245
|
+
// TODO: change this function so a type mismatch leads to an INVALID_TYPE
|
|
246
|
+
// error rather than a null event. A null event is treated as a timeout, which
|
|
247
|
+
// isn't true all the time.
|
|
248
|
+
// If this isn't the type of response we want, or if we do not have a response
|
|
249
|
+
// type, bail out with a null
|
|
250
|
+
if (event_response == NULL ||
|
|
251
|
+
rd_kafka_event_type(event_response) != event_type) {
|
|
252
|
+
rd_kafka_event_destroy(event_response);
|
|
253
|
+
return NULL;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return event_response;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
Baton AdminClient::CreateTopic(rd_kafka_NewTopic_t* topic, int timeout_ms) {
|
|
260
|
+
if (!IsConnected()) {
|
|
261
|
+
return Baton(RdKafka::ERR__STATE);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
{
|
|
265
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
266
|
+
if (!IsConnected()) {
|
|
267
|
+
return Baton(RdKafka::ERR__STATE);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Make admin options to establish that we are creating topics
|
|
271
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
272
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_CREATETOPICS);
|
|
273
|
+
|
|
274
|
+
// Create queue just for this operation
|
|
275
|
+
rd_kafka_queue_t * topic_rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
276
|
+
|
|
277
|
+
rd_kafka_CreateTopics(m_client->c_ptr(), &topic, 1, options, topic_rkqu);
|
|
278
|
+
|
|
279
|
+
// Poll for an event by type in that queue
|
|
280
|
+
rd_kafka_event_t * event_response = PollForEvent(
|
|
281
|
+
topic_rkqu,
|
|
282
|
+
RD_KAFKA_EVENT_CREATETOPICS_RESULT,
|
|
283
|
+
timeout_ms);
|
|
284
|
+
|
|
285
|
+
// Destroy the queue since we are done with it.
|
|
286
|
+
rd_kafka_queue_destroy(topic_rkqu);
|
|
287
|
+
|
|
288
|
+
// Destroy the options we just made because we polled already
|
|
289
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
290
|
+
|
|
291
|
+
// If we got no response from that operation, this is a failure
|
|
292
|
+
// likely due to time out
|
|
293
|
+
if (event_response == NULL) {
|
|
294
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Now we can get the error code from the event
|
|
298
|
+
if (rd_kafka_event_error(event_response)) {
|
|
299
|
+
// If we had a special error code, get out of here with it
|
|
300
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(event_response);
|
|
301
|
+
rd_kafka_event_destroy(event_response);
|
|
302
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// get the created results
|
|
306
|
+
const rd_kafka_CreateTopics_result_t * create_topic_results =
|
|
307
|
+
rd_kafka_event_CreateTopics_result(event_response);
|
|
308
|
+
|
|
309
|
+
size_t created_topic_count;
|
|
310
|
+
const rd_kafka_topic_result_t **restopics = rd_kafka_CreateTopics_result_topics( // NOLINT
|
|
311
|
+
create_topic_results,
|
|
312
|
+
&created_topic_count);
|
|
313
|
+
|
|
314
|
+
for (int i = 0 ; i < static_cast<int>(created_topic_count) ; i++) {
|
|
315
|
+
const rd_kafka_topic_result_t *terr = restopics[i];
|
|
316
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_topic_result_error(terr);
|
|
317
|
+
const char *errmsg = rd_kafka_topic_result_error_string(terr);
|
|
318
|
+
|
|
319
|
+
if (errcode != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
320
|
+
if (errmsg) {
|
|
321
|
+
const std::string errormsg = std::string(errmsg);
|
|
322
|
+
rd_kafka_event_destroy(event_response);
|
|
323
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode), errormsg); // NOLINT
|
|
324
|
+
} else {
|
|
325
|
+
rd_kafka_event_destroy(event_response);
|
|
326
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
rd_kafka_event_destroy(event_response);
|
|
332
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
Baton AdminClient::DeleteTopic(rd_kafka_DeleteTopic_t* topic, int timeout_ms) {
|
|
337
|
+
if (!IsConnected()) {
|
|
338
|
+
return Baton(RdKafka::ERR__STATE);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
{
|
|
342
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
343
|
+
if (!IsConnected()) {
|
|
344
|
+
return Baton(RdKafka::ERR__STATE);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Make admin options to establish that we are deleting topics
|
|
348
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
349
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_DELETETOPICS);
|
|
350
|
+
|
|
351
|
+
// Create queue just for this operation.
|
|
352
|
+
// May be worth making a "scoped queue" class or something like a lock
|
|
353
|
+
// for RAII
|
|
354
|
+
rd_kafka_queue_t * topic_rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
355
|
+
|
|
356
|
+
rd_kafka_DeleteTopics(m_client->c_ptr(), &topic, 1, options, topic_rkqu);
|
|
357
|
+
|
|
358
|
+
// Poll for an event by type in that queue
|
|
359
|
+
rd_kafka_event_t * event_response = PollForEvent(
|
|
360
|
+
topic_rkqu,
|
|
361
|
+
RD_KAFKA_EVENT_DELETETOPICS_RESULT,
|
|
362
|
+
timeout_ms);
|
|
363
|
+
|
|
364
|
+
// Destroy the queue since we are done with it.
|
|
365
|
+
rd_kafka_queue_destroy(topic_rkqu);
|
|
366
|
+
|
|
367
|
+
// Destroy the options we just made because we polled already
|
|
368
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
369
|
+
|
|
370
|
+
// If we got no response from that operation, this is a failure
|
|
371
|
+
// likely due to time out
|
|
372
|
+
if (event_response == NULL) {
|
|
373
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Now we can get the error code from the event
|
|
377
|
+
if (rd_kafka_event_error(event_response)) {
|
|
378
|
+
// If we had a special error code, get out of here with it
|
|
379
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(event_response);
|
|
380
|
+
rd_kafka_event_destroy(event_response);
|
|
381
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// get the created results
|
|
385
|
+
const rd_kafka_DeleteTopics_result_t * delete_topic_results =
|
|
386
|
+
rd_kafka_event_DeleteTopics_result(event_response);
|
|
387
|
+
|
|
388
|
+
size_t deleted_topic_count;
|
|
389
|
+
const rd_kafka_topic_result_t **restopics = rd_kafka_DeleteTopics_result_topics( // NOLINT
|
|
390
|
+
delete_topic_results,
|
|
391
|
+
&deleted_topic_count);
|
|
392
|
+
|
|
393
|
+
for (int i = 0 ; i < static_cast<int>(deleted_topic_count) ; i++) {
|
|
394
|
+
const rd_kafka_topic_result_t *terr = restopics[i];
|
|
395
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_topic_result_error(terr);
|
|
396
|
+
|
|
397
|
+
if (errcode != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
398
|
+
rd_kafka_event_destroy(event_response);
|
|
399
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
rd_kafka_event_destroy(event_response);
|
|
404
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
Baton AdminClient::CreatePartitions(
|
|
409
|
+
rd_kafka_NewPartitions_t* partitions,
|
|
410
|
+
int timeout_ms) {
|
|
411
|
+
if (!IsConnected()) {
|
|
412
|
+
return Baton(RdKafka::ERR__STATE);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
{
|
|
416
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
417
|
+
if (!IsConnected()) {
|
|
418
|
+
return Baton(RdKafka::ERR__STATE);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Make admin options to establish that we are deleting topics
|
|
422
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
423
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_CREATEPARTITIONS);
|
|
424
|
+
|
|
425
|
+
// Create queue just for this operation.
|
|
426
|
+
// May be worth making a "scoped queue" class or something like a lock
|
|
427
|
+
// for RAII
|
|
428
|
+
rd_kafka_queue_t * topic_rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
429
|
+
|
|
430
|
+
rd_kafka_CreatePartitions(m_client->c_ptr(),
|
|
431
|
+
&partitions, 1, options, topic_rkqu);
|
|
432
|
+
|
|
433
|
+
// Poll for an event by type in that queue
|
|
434
|
+
rd_kafka_event_t * event_response = PollForEvent(
|
|
435
|
+
topic_rkqu,
|
|
436
|
+
RD_KAFKA_EVENT_CREATEPARTITIONS_RESULT,
|
|
437
|
+
timeout_ms);
|
|
438
|
+
|
|
439
|
+
// Destroy the queue since we are done with it.
|
|
440
|
+
rd_kafka_queue_destroy(topic_rkqu);
|
|
441
|
+
|
|
442
|
+
// Destroy the options we just made because we polled already
|
|
443
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
444
|
+
|
|
445
|
+
// If we got no response from that operation, this is a failure
|
|
446
|
+
// likely due to time out
|
|
447
|
+
if (event_response == NULL) {
|
|
448
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Now we can get the error code from the event
|
|
452
|
+
if (rd_kafka_event_error(event_response)) {
|
|
453
|
+
// If we had a special error code, get out of here with it
|
|
454
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(event_response);
|
|
455
|
+
rd_kafka_event_destroy(event_response);
|
|
456
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// get the created results
|
|
460
|
+
const rd_kafka_CreatePartitions_result_t * create_partitions_results =
|
|
461
|
+
rd_kafka_event_CreatePartitions_result(event_response);
|
|
462
|
+
|
|
463
|
+
size_t created_partitions_topic_count;
|
|
464
|
+
const rd_kafka_topic_result_t **restopics = rd_kafka_CreatePartitions_result_topics( // NOLINT
|
|
465
|
+
create_partitions_results,
|
|
466
|
+
&created_partitions_topic_count);
|
|
467
|
+
|
|
468
|
+
for (int i = 0 ; i < static_cast<int>(created_partitions_topic_count) ; i++) { // NOLINT
|
|
469
|
+
const rd_kafka_topic_result_t *terr = restopics[i];
|
|
470
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_topic_result_error(terr);
|
|
471
|
+
const char *errmsg = rd_kafka_topic_result_error_string(terr);
|
|
472
|
+
|
|
473
|
+
if (errcode != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
474
|
+
if (errmsg) {
|
|
475
|
+
const std::string errormsg = std::string(errmsg);
|
|
476
|
+
rd_kafka_event_destroy(event_response);
|
|
477
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode), errormsg); // NOLINT
|
|
478
|
+
} else {
|
|
479
|
+
rd_kafka_event_destroy(event_response);
|
|
480
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
rd_kafka_event_destroy(event_response);
|
|
486
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
Baton AdminClient::ListGroups(
|
|
491
|
+
bool is_match_states_set,
|
|
492
|
+
std::vector<rd_kafka_consumer_group_state_t> &match_states,
|
|
493
|
+
bool is_match_types_set,
|
|
494
|
+
std::vector<rd_kafka_consumer_group_type_t> &match_types, int timeout_ms,
|
|
495
|
+
/* out */ rd_kafka_event_t **event_response) {
|
|
496
|
+
if (!IsConnected()) {
|
|
497
|
+
return Baton(RdKafka::ERR__STATE);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
{
|
|
501
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
502
|
+
if (!IsConnected()) {
|
|
503
|
+
return Baton(RdKafka::ERR__STATE);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Make admin options to establish that we are listing groups
|
|
507
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
508
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_LISTCONSUMERGROUPS);
|
|
509
|
+
|
|
510
|
+
char errstr[512];
|
|
511
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
512
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
513
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
514
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (is_match_states_set) {
|
|
518
|
+
rd_kafka_error_t *error =
|
|
519
|
+
rd_kafka_AdminOptions_set_match_consumer_group_states(
|
|
520
|
+
options, &match_states[0], match_states.size());
|
|
521
|
+
if (error) {
|
|
522
|
+
return Baton::BatonFromErrorAndDestroy(error);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (is_match_types_set) {
|
|
527
|
+
rd_kafka_error_t *error =
|
|
528
|
+
rd_kafka_AdminOptions_set_match_consumer_group_types(
|
|
529
|
+
options, &match_types[0], match_types.size());
|
|
530
|
+
if (error) {
|
|
531
|
+
return Baton::BatonFromErrorAndDestroy(error);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Create queue just for this operation.
|
|
536
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
537
|
+
|
|
538
|
+
rd_kafka_ListConsumerGroups(m_client->c_ptr(), options, rkqu);
|
|
539
|
+
|
|
540
|
+
// Poll for an event by type in that queue
|
|
541
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
542
|
+
// the caller's.
|
|
543
|
+
*event_response = PollForEvent(
|
|
544
|
+
rkqu, RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT, timeout_ms);
|
|
545
|
+
|
|
546
|
+
// Destroy the queue since we are done with it.
|
|
547
|
+
rd_kafka_queue_destroy(rkqu);
|
|
548
|
+
|
|
549
|
+
// Destroy the options we just made because we polled already
|
|
550
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
551
|
+
|
|
552
|
+
// If we got no response from that operation, this is a failure
|
|
553
|
+
// likely due to time out
|
|
554
|
+
if (*event_response == NULL) {
|
|
555
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Now we can get the error code from the event
|
|
559
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
560
|
+
// If we had a special error code, get out of here with it
|
|
561
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
562
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// At this point, event_response contains the result, which needs
|
|
566
|
+
// to be parsed/converted by the caller.
|
|
567
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
Baton AdminClient::DescribeGroups(std::vector<std::string> &groups,
|
|
572
|
+
bool include_authorized_operations,
|
|
573
|
+
int timeout_ms,
|
|
574
|
+
/* out */ rd_kafka_event_t **event_response) {
|
|
575
|
+
if (!IsConnected()) {
|
|
576
|
+
return Baton(RdKafka::ERR__STATE);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
{
|
|
580
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
581
|
+
if (!IsConnected()) {
|
|
582
|
+
return Baton(RdKafka::ERR__STATE);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// Make admin options to establish that we are describing groups
|
|
586
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
587
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_DESCRIBECONSUMERGROUPS);
|
|
588
|
+
|
|
589
|
+
char errstr[512];
|
|
590
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
591
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
592
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
593
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (include_authorized_operations) {
|
|
597
|
+
rd_kafka_error_t *error =
|
|
598
|
+
rd_kafka_AdminOptions_set_include_authorized_operations(
|
|
599
|
+
options, include_authorized_operations);
|
|
600
|
+
if (error) {
|
|
601
|
+
return Baton::BatonFromErrorAndDestroy(error);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Create queue just for this operation.
|
|
606
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
607
|
+
|
|
608
|
+
// Construct a char** to pass to librdkafka. Avoid too many allocations.
|
|
609
|
+
std::vector<const char *> c_groups(groups.size());
|
|
610
|
+
for (size_t i = 0; i < groups.size(); i++) {
|
|
611
|
+
c_groups[i] = groups[i].c_str();
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
rd_kafka_DescribeConsumerGroups(m_client->c_ptr(), &c_groups[0],
|
|
615
|
+
groups.size(), options, rkqu);
|
|
616
|
+
|
|
617
|
+
// Poll for an event by type in that queue
|
|
618
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
619
|
+
// the caller's.
|
|
620
|
+
*event_response = PollForEvent(
|
|
621
|
+
rkqu, RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT, timeout_ms);
|
|
622
|
+
|
|
623
|
+
// Destroy the queue since we are done with it.
|
|
624
|
+
rd_kafka_queue_destroy(rkqu);
|
|
625
|
+
|
|
626
|
+
// Destroy the options we just made because we polled already
|
|
627
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
628
|
+
|
|
629
|
+
// If we got no response from that operation, this is a failure
|
|
630
|
+
// likely due to time out
|
|
631
|
+
if (*event_response == NULL) {
|
|
632
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// Now we can get the error code from the event
|
|
636
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
637
|
+
// If we had a special error code, get out of here with it
|
|
638
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
639
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// At this point, event_response contains the result, which needs
|
|
643
|
+
// to be parsed/converted by the caller.
|
|
644
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
Baton AdminClient::DeleteGroups(rd_kafka_DeleteGroup_t **group_list,
|
|
649
|
+
size_t group_cnt, int timeout_ms,
|
|
650
|
+
/* out */ rd_kafka_event_t **event_response) {
|
|
651
|
+
if (!IsConnected()) {
|
|
652
|
+
return Baton(RdKafka::ERR__STATE);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
{
|
|
656
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
657
|
+
if (!IsConnected()) {
|
|
658
|
+
return Baton(RdKafka::ERR__STATE);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Make admin options to establish that we are deleting groups
|
|
662
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
663
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_DELETEGROUPS);
|
|
664
|
+
|
|
665
|
+
char errstr[512];
|
|
666
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
667
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
668
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
669
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Create queue just for this operation.
|
|
673
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
674
|
+
|
|
675
|
+
rd_kafka_DeleteGroups(m_client->c_ptr(), group_list, group_cnt, options,
|
|
676
|
+
rkqu);
|
|
677
|
+
|
|
678
|
+
// Poll for an event by type in that queue
|
|
679
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
680
|
+
// the caller's.
|
|
681
|
+
*event_response =
|
|
682
|
+
PollForEvent(rkqu, RD_KAFKA_EVENT_DELETEGROUPS_RESULT, timeout_ms);
|
|
683
|
+
|
|
684
|
+
// Destroy the queue since we are done with it.
|
|
685
|
+
rd_kafka_queue_destroy(rkqu);
|
|
686
|
+
|
|
687
|
+
// Destroy the options we just made because we polled already
|
|
688
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
689
|
+
|
|
690
|
+
// If we got no response from that operation, this is a failure
|
|
691
|
+
// likely due to time out
|
|
692
|
+
if (*event_response == NULL) {
|
|
693
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Now we can get the error code from the event
|
|
697
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
698
|
+
// If we had a special error code, get out of here with it
|
|
699
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
700
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// At this point, event_response contains the result, which needs
|
|
704
|
+
// to be parsed/converted by the caller.
|
|
705
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
Baton AdminClient::ListConsumerGroupOffsets(
|
|
710
|
+
rd_kafka_ListConsumerGroupOffsets_t **req, size_t req_cnt,
|
|
711
|
+
bool require_stable_offsets, int timeout_ms,
|
|
712
|
+
rd_kafka_event_t **event_response) {
|
|
713
|
+
if (!IsConnected()) {
|
|
714
|
+
return Baton(RdKafka::ERR__STATE);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
{
|
|
718
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
719
|
+
if (!IsConnected()) {
|
|
720
|
+
return Baton(RdKafka::ERR__STATE);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// Make admin options to establish that we are fetching offsets
|
|
724
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
725
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_LISTCONSUMERGROUPOFFSETS);
|
|
726
|
+
|
|
727
|
+
char errstr[512];
|
|
728
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
729
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
730
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
731
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if (require_stable_offsets) {
|
|
735
|
+
rd_kafka_error_t *error =
|
|
736
|
+
rd_kafka_AdminOptions_set_require_stable_offsets(
|
|
737
|
+
options, require_stable_offsets);
|
|
738
|
+
if (error) {
|
|
739
|
+
return Baton::BatonFromErrorAndDestroy(error);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// Create queue just for this operation.
|
|
744
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
745
|
+
|
|
746
|
+
rd_kafka_ListConsumerGroupOffsets(m_client->c_ptr(), req, req_cnt, options,
|
|
747
|
+
rkqu);
|
|
748
|
+
|
|
749
|
+
// Poll for an event by type in that queue
|
|
750
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
751
|
+
// the caller's.
|
|
752
|
+
*event_response = PollForEvent(
|
|
753
|
+
rkqu, RD_KAFKA_EVENT_LISTCONSUMERGROUPOFFSETS_RESULT, timeout_ms);
|
|
754
|
+
|
|
755
|
+
// Destroy the queue since we are done with it.
|
|
756
|
+
rd_kafka_queue_destroy(rkqu);
|
|
757
|
+
|
|
758
|
+
// Destroy the options we just made because we polled already
|
|
759
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
760
|
+
|
|
761
|
+
// If we got no response from that operation, this is a failure
|
|
762
|
+
// likely due to time out
|
|
763
|
+
if (*event_response == NULL) {
|
|
764
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Now we can get the error code from the event
|
|
768
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
769
|
+
// If we had a special error code, get out of here with it
|
|
770
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
771
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// At this point, event_response contains the result, which needs
|
|
775
|
+
// to be parsed/converted by the caller.
|
|
776
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
Baton AdminClient::DeleteRecords(rd_kafka_DeleteRecords_t **del_records,
|
|
781
|
+
size_t del_records_cnt,
|
|
782
|
+
int operation_timeout_ms, int timeout_ms,
|
|
783
|
+
rd_kafka_event_t **event_response) {
|
|
784
|
+
if (!IsConnected()) {
|
|
785
|
+
return Baton(RdKafka::ERR__STATE);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
{
|
|
789
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
790
|
+
if (!IsConnected()) {
|
|
791
|
+
return Baton(RdKafka::ERR__STATE);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Make admin options to establish that we are deleting records
|
|
795
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
796
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_DELETERECORDS);
|
|
797
|
+
|
|
798
|
+
char errstr[512];
|
|
799
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
800
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
801
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
802
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
err = rd_kafka_AdminOptions_set_operation_timeout(
|
|
806
|
+
options, operation_timeout_ms, errstr, sizeof(errstr));
|
|
807
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
808
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// Create queue just for this operation.
|
|
812
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
813
|
+
|
|
814
|
+
rd_kafka_DeleteRecords(m_client->c_ptr(), del_records,
|
|
815
|
+
del_records_cnt, options, rkqu);
|
|
816
|
+
|
|
817
|
+
// Poll for an event by type in that queue
|
|
818
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
819
|
+
// the caller's.
|
|
820
|
+
*event_response =
|
|
821
|
+
PollForEvent(rkqu, RD_KAFKA_EVENT_DELETERECORDS_RESULT, timeout_ms);
|
|
822
|
+
|
|
823
|
+
// Destroy the queue since we are done with it.
|
|
824
|
+
rd_kafka_queue_destroy(rkqu);
|
|
825
|
+
|
|
826
|
+
// Destroy the options we just made because we polled already
|
|
827
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
828
|
+
|
|
829
|
+
// If we got no response from that operation, this is a failure
|
|
830
|
+
// likely due to time out
|
|
831
|
+
if (*event_response == NULL) {
|
|
832
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Now we can get the error code from the event
|
|
836
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
837
|
+
// If we had a special error code, get out of here with it
|
|
838
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
839
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// At this point, event_response contains the result, which needs
|
|
843
|
+
// to be parsed/converted by the caller.
|
|
844
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
Baton AdminClient::DescribeTopics(rd_kafka_TopicCollection_t *topics,
|
|
849
|
+
bool include_authorized_operations,
|
|
850
|
+
int timeout_ms,
|
|
851
|
+
rd_kafka_event_t **event_response) {
|
|
852
|
+
if (!IsConnected()) {
|
|
853
|
+
return Baton(RdKafka::ERR__STATE);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
{
|
|
857
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
858
|
+
if (!IsConnected()) {
|
|
859
|
+
return Baton(RdKafka::ERR__STATE);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Make admin options to establish that we are describing topics
|
|
863
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
864
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_DESCRIBETOPICS);
|
|
865
|
+
|
|
866
|
+
if (include_authorized_operations) {
|
|
867
|
+
rd_kafka_error_t *error =
|
|
868
|
+
rd_kafka_AdminOptions_set_include_authorized_operations(
|
|
869
|
+
options, include_authorized_operations);
|
|
870
|
+
if (error) {
|
|
871
|
+
return Baton::BatonFromErrorAndDestroy(error);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
char errstr[512];
|
|
876
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
877
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
878
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
879
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// Create queue just for this operation.
|
|
883
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
884
|
+
|
|
885
|
+
rd_kafka_DescribeTopics(m_client->c_ptr(), topics, options, rkqu);
|
|
886
|
+
|
|
887
|
+
// Poll for an event by type in that queue
|
|
888
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
889
|
+
// the caller's.
|
|
890
|
+
*event_response =
|
|
891
|
+
PollForEvent(rkqu, RD_KAFKA_EVENT_DESCRIBETOPICS_RESULT, timeout_ms);
|
|
892
|
+
|
|
893
|
+
// Destroy the queue since we are done with it.
|
|
894
|
+
rd_kafka_queue_destroy(rkqu);
|
|
895
|
+
|
|
896
|
+
// Destroy the options we just made because we polled already
|
|
897
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
898
|
+
|
|
899
|
+
// If we got no response from that operation, this is a failure
|
|
900
|
+
// likely due to time out
|
|
901
|
+
if (*event_response == NULL) {
|
|
902
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Now we can get the error code from the event
|
|
906
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
907
|
+
// If we had a special error code, get out of here with it
|
|
908
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
909
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// At this point, event_response contains the result, which needs
|
|
913
|
+
// to be parsed/converted by the caller.
|
|
914
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
Baton AdminClient::ListOffsets(rd_kafka_topic_partition_list_t *partitions,
|
|
920
|
+
int timeout_ms,
|
|
921
|
+
rd_kafka_IsolationLevel_t isolation_level,
|
|
922
|
+
rd_kafka_event_t **event_response) {
|
|
923
|
+
if (!IsConnected()) {
|
|
924
|
+
return Baton(RdKafka::ERR__STATE);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
{
|
|
928
|
+
scoped_shared_write_lock lock(m_connection_lock);
|
|
929
|
+
if (!IsConnected()) {
|
|
930
|
+
return Baton(RdKafka::ERR__STATE);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// Make admin options to establish that we are fetching offsets
|
|
934
|
+
rd_kafka_AdminOptions_t *options = rd_kafka_AdminOptions_new(
|
|
935
|
+
m_client->c_ptr(), RD_KAFKA_ADMIN_OP_LISTOFFSETS);
|
|
936
|
+
|
|
937
|
+
char errstr[512];
|
|
938
|
+
rd_kafka_resp_err_t err = rd_kafka_AdminOptions_set_request_timeout(
|
|
939
|
+
options, timeout_ms, errstr, sizeof(errstr));
|
|
940
|
+
if (err != RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
941
|
+
return Baton(static_cast<RdKafka::ErrorCode>(err), errstr);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
rd_kafka_error_t *error =
|
|
945
|
+
rd_kafka_AdminOptions_set_isolation_level(options, isolation_level);
|
|
946
|
+
if (error) {
|
|
947
|
+
return Baton::BatonFromErrorAndDestroy(error);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// Create queue just for this operation.
|
|
951
|
+
rd_kafka_queue_t *rkqu = rd_kafka_queue_new(m_client->c_ptr());
|
|
952
|
+
|
|
953
|
+
rd_kafka_ListOffsets(m_client->c_ptr(), partitions, options, rkqu);
|
|
954
|
+
|
|
955
|
+
// Poll for an event by type in that queue
|
|
956
|
+
// DON'T destroy the event. It is the out parameter, and ownership is
|
|
957
|
+
// the caller's.
|
|
958
|
+
*event_response =
|
|
959
|
+
PollForEvent(rkqu, RD_KAFKA_EVENT_LISTOFFSETS_RESULT, timeout_ms);
|
|
960
|
+
|
|
961
|
+
// Destroy the queue since we are done with it.
|
|
962
|
+
rd_kafka_queue_destroy(rkqu);
|
|
963
|
+
|
|
964
|
+
// Destroy the options we just made because we polled already
|
|
965
|
+
rd_kafka_AdminOptions_destroy(options);
|
|
966
|
+
|
|
967
|
+
// If we got no response from that operation, this is a failure
|
|
968
|
+
// likely due to time out
|
|
969
|
+
if (*event_response == NULL) {
|
|
970
|
+
return Baton(RdKafka::ERR__TIMED_OUT);
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// Now we can get the error code from the event
|
|
974
|
+
if (rd_kafka_event_error(*event_response)) {
|
|
975
|
+
// If we had a special error code, get out of here with it
|
|
976
|
+
const rd_kafka_resp_err_t errcode = rd_kafka_event_error(*event_response);
|
|
977
|
+
return Baton(static_cast<RdKafka::ErrorCode>(errcode));
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// At this point, event_response contains the result, which needs
|
|
981
|
+
// to be parsed/converted by the caller.
|
|
982
|
+
return Baton(RdKafka::ERR_NO_ERROR);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
void AdminClient::ActivateDispatchers() {
|
|
987
|
+
// Listen to global config
|
|
988
|
+
m_gconfig->listen();
|
|
989
|
+
|
|
990
|
+
// Listen to non global config
|
|
991
|
+
// tconfig->listen();
|
|
992
|
+
|
|
993
|
+
// This should be refactored to config based management
|
|
994
|
+
m_event_cb.dispatcher.Activate();
|
|
995
|
+
}
|
|
996
|
+
void AdminClient::DeactivateDispatchers() {
|
|
997
|
+
// Stop listening to the config dispatchers
|
|
998
|
+
m_gconfig->stop();
|
|
999
|
+
|
|
1000
|
+
// Also this one
|
|
1001
|
+
m_event_cb.dispatcher.Deactivate();
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* @section
|
|
1006
|
+
* C++ Exported prototype functions
|
|
1007
|
+
*/
|
|
1008
|
+
|
|
1009
|
+
NAN_METHOD(AdminClient::NodeConnect) {
|
|
1010
|
+
Nan::HandleScope scope;
|
|
1011
|
+
|
|
1012
|
+
AdminClient* client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1013
|
+
|
|
1014
|
+
// Activate the dispatchers before the connection, as some callbacks may run
|
|
1015
|
+
// on the background thread.
|
|
1016
|
+
// We will deactivate them if the connection fails.
|
|
1017
|
+
// Because the Admin Client connect is synchronous, we can do this within
|
|
1018
|
+
// AdminClient::Connect as well, but we do it here to keep the code similiar
|
|
1019
|
+
// to the Producer and Consumer.
|
|
1020
|
+
client->ActivateDispatchers();
|
|
1021
|
+
|
|
1022
|
+
Baton b = client->Connect();
|
|
1023
|
+
// Let the JS library throw if we need to so the error can be more rich
|
|
1024
|
+
int error_code = static_cast<int>(b.err());
|
|
1025
|
+
return info.GetReturnValue().Set(Nan::New<v8::Number>(error_code));
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
NAN_METHOD(AdminClient::NodeDisconnect) {
|
|
1029
|
+
Nan::HandleScope scope;
|
|
1030
|
+
|
|
1031
|
+
AdminClient* client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1032
|
+
|
|
1033
|
+
Baton b = client->Disconnect();
|
|
1034
|
+
// Let the JS library throw if we need to so the error can be more rich
|
|
1035
|
+
int error_code = static_cast<int>(b.err());
|
|
1036
|
+
return info.GetReturnValue().Set(Nan::New<v8::Number>(error_code));
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Create topic
|
|
1041
|
+
*/
|
|
1042
|
+
NAN_METHOD(AdminClient::NodeCreateTopic) {
|
|
1043
|
+
Nan::HandleScope scope;
|
|
1044
|
+
|
|
1045
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1046
|
+
// Just throw an exception
|
|
1047
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
if (!info[1]->IsNumber()) {
|
|
1051
|
+
return Nan::ThrowError("Must provide 'timeout'");
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// Create the final callback object
|
|
1055
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1056
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1057
|
+
AdminClient* client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1058
|
+
|
|
1059
|
+
// Get the timeout
|
|
1060
|
+
int timeout = Nan::To<int32_t>(info[1]).FromJust();
|
|
1061
|
+
|
|
1062
|
+
std::string errstr;
|
|
1063
|
+
// Get that topic we want to create
|
|
1064
|
+
rd_kafka_NewTopic_t* topic = Conversion::Admin::FromV8TopicObject(
|
|
1065
|
+
info[0].As<v8::Object>(), errstr);
|
|
1066
|
+
|
|
1067
|
+
if (topic == NULL) {
|
|
1068
|
+
Nan::ThrowError(errstr.c_str());
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// Queue up dat work
|
|
1073
|
+
Nan::AsyncQueueWorker(
|
|
1074
|
+
new Workers::AdminClientCreateTopic(callback, client, topic, timeout));
|
|
1075
|
+
|
|
1076
|
+
return info.GetReturnValue().Set(Nan::Null());
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* Delete topic
|
|
1081
|
+
*/
|
|
1082
|
+
NAN_METHOD(AdminClient::NodeDeleteTopic) {
|
|
1083
|
+
Nan::HandleScope scope;
|
|
1084
|
+
|
|
1085
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1086
|
+
// Just throw an exception
|
|
1087
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (!info[1]->IsNumber() || !info[0]->IsString()) {
|
|
1091
|
+
return Nan::ThrowError("Must provide 'timeout', and 'topicName'");
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// Create the final callback object
|
|
1095
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1096
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1097
|
+
AdminClient* client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1098
|
+
|
|
1099
|
+
// Get the topic name from the string
|
|
1100
|
+
std::string topic_name = Util::FromV8String(
|
|
1101
|
+
Nan::To<v8::String>(info[0]).ToLocalChecked());
|
|
1102
|
+
|
|
1103
|
+
// Get the timeout
|
|
1104
|
+
int timeout = Nan::To<int32_t>(info[1]).FromJust();
|
|
1105
|
+
|
|
1106
|
+
// Get that topic we want to create
|
|
1107
|
+
rd_kafka_DeleteTopic_t* topic = rd_kafka_DeleteTopic_new(
|
|
1108
|
+
topic_name.c_str());
|
|
1109
|
+
|
|
1110
|
+
// Queue up dat work
|
|
1111
|
+
Nan::AsyncQueueWorker(
|
|
1112
|
+
new Workers::AdminClientDeleteTopic(callback, client, topic, timeout));
|
|
1113
|
+
|
|
1114
|
+
return info.GetReturnValue().Set(Nan::Null());
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Delete topic
|
|
1119
|
+
*/
|
|
1120
|
+
NAN_METHOD(AdminClient::NodeCreatePartitions) {
|
|
1121
|
+
Nan::HandleScope scope;
|
|
1122
|
+
|
|
1123
|
+
if (info.Length() < 4) {
|
|
1124
|
+
// Just throw an exception
|
|
1125
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
if (!info[3]->IsFunction()) {
|
|
1129
|
+
// Just throw an exception
|
|
1130
|
+
return Nan::ThrowError("Need to specify a callback 2");
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
if (!info[2]->IsNumber() || !info[1]->IsNumber() || !info[0]->IsString()) {
|
|
1134
|
+
return Nan::ThrowError(
|
|
1135
|
+
"Must provide 'totalPartitions', 'timeout', and 'topicName'");
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// Create the final callback object
|
|
1139
|
+
v8::Local<v8::Function> cb = info[3].As<v8::Function>();
|
|
1140
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1141
|
+
AdminClient* client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1142
|
+
|
|
1143
|
+
// Get the timeout
|
|
1144
|
+
int timeout = Nan::To<int32_t>(info[2]).FromJust();
|
|
1145
|
+
|
|
1146
|
+
// Get the total number of desired partitions
|
|
1147
|
+
int partition_total_count = Nan::To<int32_t>(info[1]).FromJust();
|
|
1148
|
+
|
|
1149
|
+
// Get the topic name from the string
|
|
1150
|
+
std::string topic_name = Util::FromV8String(
|
|
1151
|
+
Nan::To<v8::String>(info[0]).ToLocalChecked());
|
|
1152
|
+
|
|
1153
|
+
// Create an error buffer we can throw
|
|
1154
|
+
char* errbuf = reinterpret_cast<char*>(malloc(100));
|
|
1155
|
+
|
|
1156
|
+
// Create the new partitions request
|
|
1157
|
+
rd_kafka_NewPartitions_t* new_partitions = rd_kafka_NewPartitions_new(
|
|
1158
|
+
topic_name.c_str(), partition_total_count, errbuf, 100);
|
|
1159
|
+
|
|
1160
|
+
// If we got a failure on the create new partitions request,
|
|
1161
|
+
// fail here
|
|
1162
|
+
if (new_partitions == NULL) {
|
|
1163
|
+
return Nan::ThrowError(errbuf);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// Queue up dat work
|
|
1167
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientCreatePartitions(
|
|
1168
|
+
callback, client, new_partitions, timeout));
|
|
1169
|
+
|
|
1170
|
+
return info.GetReturnValue().Set(Nan::Null());
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* List Consumer Groups.
|
|
1175
|
+
*/
|
|
1176
|
+
NAN_METHOD(AdminClient::NodeListGroups) {
|
|
1177
|
+
Nan::HandleScope scope;
|
|
1178
|
+
|
|
1179
|
+
if (info.Length() < 2 || !info[1]->IsFunction()) {
|
|
1180
|
+
// Just throw an exception
|
|
1181
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
if (!info[0]->IsObject()) {
|
|
1185
|
+
return Nan::ThrowError("Must provide options object");
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
v8::Local<v8::Object> config = info[0].As<v8::Object>();
|
|
1189
|
+
|
|
1190
|
+
// Create the final callback object
|
|
1191
|
+
v8::Local<v8::Function> cb = info[1].As<v8::Function>();
|
|
1192
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1193
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1194
|
+
|
|
1195
|
+
// Get the timeout - default 5000.
|
|
1196
|
+
int timeout_ms = GetParameter<int64_t>(config, "timeout", 5000);
|
|
1197
|
+
|
|
1198
|
+
// Get the match states, or not if they are unset.
|
|
1199
|
+
std::vector<rd_kafka_consumer_group_state_t> match_states;
|
|
1200
|
+
v8::Local<v8::String> match_consumer_group_states_key =
|
|
1201
|
+
Nan::New("matchConsumerGroupStates").ToLocalChecked();
|
|
1202
|
+
bool is_match_states_set =
|
|
1203
|
+
Nan::Has(config, match_consumer_group_states_key).FromMaybe(false);
|
|
1204
|
+
v8::Local<v8::Array> match_states_array = Nan::New<v8::Array>();
|
|
1205
|
+
|
|
1206
|
+
if (is_match_states_set) {
|
|
1207
|
+
match_states_array = GetParameter<v8::Local<v8::Array>>(
|
|
1208
|
+
config, "matchConsumerGroupStates", match_states_array);
|
|
1209
|
+
if (match_states_array->Length()) {
|
|
1210
|
+
match_states = Conversion::Admin::FromV8GroupStateArray(
|
|
1211
|
+
match_states_array);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
std::vector<rd_kafka_consumer_group_type_t> match_types;
|
|
1216
|
+
v8::Local<v8::String> match_consumer_group_types_key =
|
|
1217
|
+
Nan::New("matchConsumerGroupTypes").ToLocalChecked();
|
|
1218
|
+
bool is_match_types_set =
|
|
1219
|
+
Nan::Has(config, match_consumer_group_types_key).FromMaybe(false);
|
|
1220
|
+
v8::Local<v8::Array> match_types_array = Nan::New<v8::Array>();
|
|
1221
|
+
|
|
1222
|
+
if (is_match_types_set) {
|
|
1223
|
+
match_types_array = GetParameter<v8::Local<v8::Array>>(
|
|
1224
|
+
config, "matchConsumerGroupTypes", match_types_array);
|
|
1225
|
+
if (match_types_array->Length()) {
|
|
1226
|
+
match_types = Conversion::Admin::FromV8GroupTypeArray(
|
|
1227
|
+
match_types_array);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
// Queue the work.
|
|
1232
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientListGroups(
|
|
1233
|
+
callback, client, is_match_states_set, match_states, is_match_types_set,
|
|
1234
|
+
match_types, timeout_ms));
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Describe Consumer Groups.
|
|
1239
|
+
*/
|
|
1240
|
+
NAN_METHOD(AdminClient::NodeDescribeGroups) {
|
|
1241
|
+
Nan::HandleScope scope;
|
|
1242
|
+
|
|
1243
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1244
|
+
// Just throw an exception
|
|
1245
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
if (!info[0]->IsArray()) {
|
|
1249
|
+
return Nan::ThrowError("Must provide group name array");
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
if (!info[1]->IsObject()) {
|
|
1253
|
+
return Nan::ThrowError("Must provide options object");
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
// Get list of group names to describe.
|
|
1257
|
+
v8::Local<v8::Array> group_names = info[0].As<v8::Array>();
|
|
1258
|
+
if (group_names->Length() == 0) {
|
|
1259
|
+
return Nan::ThrowError("Must provide at least one group name");
|
|
1260
|
+
}
|
|
1261
|
+
std::vector<std::string> group_names_vector =
|
|
1262
|
+
v8ArrayToStringVector(group_names);
|
|
1263
|
+
|
|
1264
|
+
v8::Local<v8::Object> config = info[1].As<v8::Object>();
|
|
1265
|
+
|
|
1266
|
+
// Get the timeout - default 5000.
|
|
1267
|
+
int timeout_ms = GetParameter<int64_t>(config, "timeout", 5000);
|
|
1268
|
+
|
|
1269
|
+
// Get whether to include authorized operations - default false.
|
|
1270
|
+
bool include_authorized_operations =
|
|
1271
|
+
GetParameter<bool>(config, "includeAuthorizedOperations", false);
|
|
1272
|
+
|
|
1273
|
+
// Create the final callback object
|
|
1274
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1275
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1276
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1277
|
+
|
|
1278
|
+
// Queue the work.
|
|
1279
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientDescribeGroups(
|
|
1280
|
+
callback, client, group_names_vector, include_authorized_operations,
|
|
1281
|
+
timeout_ms));
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
* Delete Consumer Groups.
|
|
1286
|
+
*/
|
|
1287
|
+
NAN_METHOD(AdminClient::NodeDeleteGroups) {
|
|
1288
|
+
Nan::HandleScope scope;
|
|
1289
|
+
|
|
1290
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1291
|
+
// Just throw an exception
|
|
1292
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if (!info[0]->IsArray()) {
|
|
1296
|
+
return Nan::ThrowError("Must provide group name array");
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
if (!info[1]->IsObject()) {
|
|
1300
|
+
return Nan::ThrowError("Must provide options object");
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// Get list of group names to delete, and convert it into an
|
|
1304
|
+
// rd_kafka_DeleteGroup_t array.
|
|
1305
|
+
v8::Local<v8::Array> group_names = info[0].As<v8::Array>();
|
|
1306
|
+
if (group_names->Length() == 0) {
|
|
1307
|
+
return Nan::ThrowError("Must provide at least one group name");
|
|
1308
|
+
}
|
|
1309
|
+
std::vector<std::string> group_names_vector =
|
|
1310
|
+
v8ArrayToStringVector(group_names);
|
|
1311
|
+
|
|
1312
|
+
// The ownership of this array is transferred to the worker.
|
|
1313
|
+
rd_kafka_DeleteGroup_t **group_list = static_cast<rd_kafka_DeleteGroup_t **>(
|
|
1314
|
+
malloc(sizeof(rd_kafka_DeleteGroup_t *) * group_names_vector.size()));
|
|
1315
|
+
for (size_t i = 0; i < group_names_vector.size(); i++) {
|
|
1316
|
+
group_list[i] = rd_kafka_DeleteGroup_new(group_names_vector[i].c_str());
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
v8::Local<v8::Object> config = info[1].As<v8::Object>();
|
|
1320
|
+
|
|
1321
|
+
// Get the timeout - default 5000.
|
|
1322
|
+
int timeout_ms = GetParameter<int64_t>(config, "timeout", 5000);
|
|
1323
|
+
|
|
1324
|
+
// Create the final callback object
|
|
1325
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1326
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1327
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1328
|
+
|
|
1329
|
+
// Queue the work.
|
|
1330
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientDeleteGroups(
|
|
1331
|
+
callback, client, group_list, group_names_vector.size(), timeout_ms));
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
/**
|
|
1335
|
+
* List Consumer Group Offsets.
|
|
1336
|
+
*/
|
|
1337
|
+
NAN_METHOD(AdminClient::NodeListConsumerGroupOffsets) {
|
|
1338
|
+
Nan::HandleScope scope;
|
|
1339
|
+
|
|
1340
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1341
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
if (!info[0]->IsArray()) {
|
|
1345
|
+
return Nan::ThrowError("Must provide an array of 'listGroupOffsets'");
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
v8::Local<v8::Array> listGroupOffsets = info[0].As<v8::Array>();
|
|
1349
|
+
|
|
1350
|
+
if (listGroupOffsets->Length() == 0) {
|
|
1351
|
+
return Nan::ThrowError("'listGroupOffsets' cannot be empty");
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/**
|
|
1355
|
+
* The ownership of this is taken by
|
|
1356
|
+
* Workers::AdminClientListConsumerGroupOffsets and freeing it is also handled
|
|
1357
|
+
* by that class.
|
|
1358
|
+
*/
|
|
1359
|
+
rd_kafka_ListConsumerGroupOffsets_t **requests =
|
|
1360
|
+
static_cast<rd_kafka_ListConsumerGroupOffsets_t **>(
|
|
1361
|
+
malloc(sizeof(rd_kafka_ListConsumerGroupOffsets_t *) *
|
|
1362
|
+
listGroupOffsets->Length()));
|
|
1363
|
+
|
|
1364
|
+
for (uint32_t i = 0; i < listGroupOffsets->Length(); ++i) {
|
|
1365
|
+
v8::Local<v8::Value> listGroupOffsetValue =
|
|
1366
|
+
Nan::Get(listGroupOffsets, i).ToLocalChecked();
|
|
1367
|
+
if (!listGroupOffsetValue->IsObject()) {
|
|
1368
|
+
return Nan::ThrowError("Each entry must be an object");
|
|
1369
|
+
}
|
|
1370
|
+
v8::Local<v8::Object> listGroupOffsetObj =
|
|
1371
|
+
listGroupOffsetValue.As<v8::Object>();
|
|
1372
|
+
|
|
1373
|
+
v8::Local<v8::Value> groupIdValue;
|
|
1374
|
+
if (!Nan::Get(listGroupOffsetObj, Nan::New("groupId").ToLocalChecked())
|
|
1375
|
+
.ToLocal(&groupIdValue)) {
|
|
1376
|
+
return Nan::ThrowError("Each entry must have 'groupId'");
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
Nan::MaybeLocal<v8::String> groupIdMaybe =
|
|
1380
|
+
Nan::To<v8::String>(groupIdValue);
|
|
1381
|
+
if (groupIdMaybe.IsEmpty()) {
|
|
1382
|
+
return Nan::ThrowError("'groupId' must be a string");
|
|
1383
|
+
}
|
|
1384
|
+
Nan::Utf8String groupIdUtf8(groupIdMaybe.ToLocalChecked());
|
|
1385
|
+
std::string groupIdStr = *groupIdUtf8;
|
|
1386
|
+
|
|
1387
|
+
v8::Local<v8::Value> partitionsValue;
|
|
1388
|
+
rd_kafka_topic_partition_list_t *partitions = NULL;
|
|
1389
|
+
|
|
1390
|
+
if (Nan::Get(listGroupOffsetObj, Nan::New("partitions").ToLocalChecked())
|
|
1391
|
+
.ToLocal(&partitionsValue) &&
|
|
1392
|
+
partitionsValue->IsArray()) {
|
|
1393
|
+
v8::Local<v8::Array> partitionsArray = partitionsValue.As<v8::Array>();
|
|
1394
|
+
|
|
1395
|
+
if (partitionsArray->Length() > 0) {
|
|
1396
|
+
partitions = Conversion::TopicPartition::
|
|
1397
|
+
TopicPartitionv8ArrayToTopicPartitionList(partitionsArray, false);
|
|
1398
|
+
if (partitions == NULL) {
|
|
1399
|
+
return Nan::ThrowError(
|
|
1400
|
+
"Failed to convert partitions to list, provide proper object in "
|
|
1401
|
+
"partitions");
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
requests[i] =
|
|
1407
|
+
rd_kafka_ListConsumerGroupOffsets_new(groupIdStr.c_str(), partitions);
|
|
1408
|
+
|
|
1409
|
+
if (partitions != NULL) {
|
|
1410
|
+
rd_kafka_topic_partition_list_destroy(partitions);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
// Now process the second argument: options (timeout and requireStableOffsets)
|
|
1415
|
+
v8::Local<v8::Object> options = info[1].As<v8::Object>();
|
|
1416
|
+
|
|
1417
|
+
bool require_stable_offsets =
|
|
1418
|
+
GetParameter<bool>(options, "requireStableOffsets", false);
|
|
1419
|
+
int timeout_ms = GetParameter<int64_t>(options, "timeout", 5000);
|
|
1420
|
+
|
|
1421
|
+
// Create the final callback object
|
|
1422
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1423
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1424
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1425
|
+
|
|
1426
|
+
// Queue the worker to process the offset fetch request asynchronously
|
|
1427
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientListConsumerGroupOffsets(
|
|
1428
|
+
callback, client, requests, listGroupOffsets->Length(),
|
|
1429
|
+
require_stable_offsets, timeout_ms));
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/**
|
|
1433
|
+
* Delete Records.
|
|
1434
|
+
*/
|
|
1435
|
+
NAN_METHOD(AdminClient::NodeDeleteRecords) {
|
|
1436
|
+
Nan::HandleScope scope;
|
|
1437
|
+
|
|
1438
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1439
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
if (!info[0]->IsArray()) {
|
|
1443
|
+
return Nan::ThrowError(
|
|
1444
|
+
"Must provide array containg 'TopicPartitionOffset' objects");
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
if (!info[1]->IsObject()) {
|
|
1448
|
+
return Nan::ThrowError("Must provide 'options' object");
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Get list of TopicPartitions to delete records from
|
|
1452
|
+
// and convert it into rd_kafka_DeleteRecords_t array
|
|
1453
|
+
v8::Local<v8::Array> delete_records_list = info[0].As<v8::Array>();
|
|
1454
|
+
|
|
1455
|
+
if (delete_records_list->Length() == 0) {
|
|
1456
|
+
return Nan::ThrowError("Must provide at least one TopicPartitionOffset");
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* The ownership of this is taken by
|
|
1461
|
+
* Workers::AdminClientDeleteRecords and freeing it is also handled
|
|
1462
|
+
* by that class.
|
|
1463
|
+
*/
|
|
1464
|
+
rd_kafka_DeleteRecords_t **delete_records =
|
|
1465
|
+
static_cast<rd_kafka_DeleteRecords_t **>(
|
|
1466
|
+
malloc(sizeof(rd_kafka_DeleteRecords_t *) * 1));
|
|
1467
|
+
|
|
1468
|
+
rd_kafka_topic_partition_list_t *partitions =
|
|
1469
|
+
Conversion::TopicPartition::TopicPartitionv8ArrayToTopicPartitionList(
|
|
1470
|
+
delete_records_list, true);
|
|
1471
|
+
if (partitions == NULL) {
|
|
1472
|
+
return Nan::ThrowError(
|
|
1473
|
+
"Failed to convert objects in delete records list, provide proper "
|
|
1474
|
+
"TopicPartitionOffset objects");
|
|
1475
|
+
}
|
|
1476
|
+
delete_records[0] = rd_kafka_DeleteRecords_new(partitions);
|
|
1477
|
+
|
|
1478
|
+
rd_kafka_topic_partition_list_destroy(partitions);
|
|
1479
|
+
|
|
1480
|
+
// Now process the second argument: options (timeout and operation_timeout)
|
|
1481
|
+
v8::Local<v8::Object> options = info[1].As<v8::Object>();
|
|
1482
|
+
|
|
1483
|
+
int operation_timeout_ms =
|
|
1484
|
+
GetParameter<int64_t>(options, "operation_timeout", 60000);
|
|
1485
|
+
int timeout_ms = GetParameter<int64_t>(options, "timeout", 5000);
|
|
1486
|
+
|
|
1487
|
+
// Create the final callback object
|
|
1488
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1489
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1490
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1491
|
+
|
|
1492
|
+
// Queue the worker to process the offset fetch request asynchronously
|
|
1493
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientDeleteRecords(
|
|
1494
|
+
callback, client, delete_records, 1, operation_timeout_ms, timeout_ms));
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
/**
|
|
1498
|
+
* Describe Topics.
|
|
1499
|
+
*/
|
|
1500
|
+
NAN_METHOD(AdminClient::NodeDescribeTopics) {
|
|
1501
|
+
Nan::HandleScope scope;
|
|
1502
|
+
|
|
1503
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1504
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
if (!info[0]->IsArray()) {
|
|
1508
|
+
return Nan::ThrowError("Must provide an array of 'topicNames'");
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
v8::Local<v8::Array> topicNames = info[0].As<v8::Array>();
|
|
1512
|
+
|
|
1513
|
+
if (topicNames->Length() == 0) {
|
|
1514
|
+
return Nan::ThrowError("'topicNames' cannot be empty");
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
std::vector<std::string> topicNamesVector = v8ArrayToStringVector(topicNames);
|
|
1518
|
+
|
|
1519
|
+
const char **topics = static_cast<const char **>(
|
|
1520
|
+
malloc(sizeof(const char *) * topicNamesVector.size()));
|
|
1521
|
+
|
|
1522
|
+
for (size_t i = 0; i < topicNamesVector.size(); i++) {
|
|
1523
|
+
topics[i] = topicNamesVector[i].c_str();
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
/**
|
|
1527
|
+
* The ownership of this is taken by
|
|
1528
|
+
* Workers::AdminClientDescribeTopics and freeing it is also handled
|
|
1529
|
+
* by that class.
|
|
1530
|
+
*/
|
|
1531
|
+
rd_kafka_TopicCollection_t *topic_collection =
|
|
1532
|
+
rd_kafka_TopicCollection_of_topic_names(topics, topicNamesVector.size());
|
|
1533
|
+
|
|
1534
|
+
free(topics);
|
|
1535
|
+
|
|
1536
|
+
v8::Local<v8::Object> options = info[1].As<v8::Object>();
|
|
1537
|
+
|
|
1538
|
+
bool include_authorised_operations =
|
|
1539
|
+
GetParameter<bool>(options, "includeAuthorizedOperations", false);
|
|
1540
|
+
|
|
1541
|
+
int timeout_ms = GetParameter<int64_t>(options, "timeout", 5000);
|
|
1542
|
+
|
|
1543
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1544
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1545
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1546
|
+
|
|
1547
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientDescribeTopics(
|
|
1548
|
+
callback, client, topic_collection,
|
|
1549
|
+
include_authorised_operations, timeout_ms));
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* List Offsets.
|
|
1555
|
+
*/
|
|
1556
|
+
NAN_METHOD(AdminClient::NodeListOffsets) {
|
|
1557
|
+
Nan::HandleScope scope;
|
|
1558
|
+
|
|
1559
|
+
if (info.Length() < 3 || !info[2]->IsFunction()) {
|
|
1560
|
+
return Nan::ThrowError("Need to specify a callback");
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
if (!info[0]->IsArray()) {
|
|
1564
|
+
return Nan::ThrowError("Must provide an array of 'TopicPartitionOffsets'");
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
v8::Local<v8::Array> listOffsets = info[0].As<v8::Array>();
|
|
1568
|
+
|
|
1569
|
+
/**
|
|
1570
|
+
* The ownership of this is taken by
|
|
1571
|
+
* Workers::AdminClientListOffsets and freeing it is also handled
|
|
1572
|
+
* by that class.
|
|
1573
|
+
*/
|
|
1574
|
+
rd_kafka_topic_partition_list_t *partitions = Conversion::TopicPartition::
|
|
1575
|
+
TopicPartitionOffsetSpecv8ArrayToTopicPartitionList(listOffsets);
|
|
1576
|
+
|
|
1577
|
+
// Now process the second argument: options (timeout and isolationLevel)
|
|
1578
|
+
v8::Local<v8::Object> options = info[1].As<v8::Object>();
|
|
1579
|
+
|
|
1580
|
+
rd_kafka_IsolationLevel_t isolation_level =
|
|
1581
|
+
static_cast<rd_kafka_IsolationLevel_t>(GetParameter<int32_t>(
|
|
1582
|
+
options, "isolationLevel",
|
|
1583
|
+
static_cast<int32_t>(RD_KAFKA_ISOLATION_LEVEL_READ_UNCOMMITTED)));
|
|
1584
|
+
|
|
1585
|
+
int timeout_ms = GetParameter<int64_t>(options, "timeout", 5000);
|
|
1586
|
+
|
|
1587
|
+
// Create the final callback object
|
|
1588
|
+
v8::Local<v8::Function> cb = info[2].As<v8::Function>();
|
|
1589
|
+
Nan::Callback *callback = new Nan::Callback(cb);
|
|
1590
|
+
AdminClient *client = ObjectWrap::Unwrap<AdminClient>(info.This());
|
|
1591
|
+
|
|
1592
|
+
// Queue the worker to process the offset fetch request asynchronously
|
|
1593
|
+
Nan::AsyncQueueWorker(new Workers::AdminClientListOffsets(
|
|
1594
|
+
callback, client, partitions, timeout_ms, isolation_level));
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
} // namespace NodeKafka
|