@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.
Files changed (628) hide show
  1. package/CHANGELOG.md +457 -0
  2. package/LICENSE.kafkajs +31 -0
  3. package/LICENSE.node-rdkafka +25 -0
  4. package/LICENSE.txt +20 -0
  5. package/README.md +133 -0
  6. package/binding.gyp +184 -0
  7. package/build/Release/confluent-kafka-javascript.node +0 -0
  8. package/build/deps/librdkafka++.so.1 +0 -0
  9. package/build/deps/librdkafka.Makefile +6 -0
  10. package/build/deps/librdkafka.so.1 +0 -0
  11. package/build/deps/librdkafka.target.mk +55 -0
  12. package/deps/librdkafka/.clang-format +136 -0
  13. package/deps/librdkafka/.clang-format-cpp +103 -0
  14. package/deps/librdkafka/.dir-locals.el +10 -0
  15. package/deps/librdkafka/.formatignore +35 -0
  16. package/deps/librdkafka/.gdbmacros +19 -0
  17. package/deps/librdkafka/CHANGELOG.md +2477 -0
  18. package/deps/librdkafka/CMakeLists.txt +291 -0
  19. package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
  20. package/deps/librdkafka/CONFIGURATION.md +212 -0
  21. package/deps/librdkafka/CONTRIBUTING.md +431 -0
  22. package/deps/librdkafka/Doxyfile +2375 -0
  23. package/deps/librdkafka/INTRODUCTION.md +2752 -0
  24. package/deps/librdkafka/LICENSE +26 -0
  25. package/deps/librdkafka/LICENSE.cjson +22 -0
  26. package/deps/librdkafka/LICENSE.crc32c +28 -0
  27. package/deps/librdkafka/LICENSE.fnv1a +18 -0
  28. package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
  29. package/deps/librdkafka/LICENSE.lz4 +26 -0
  30. package/deps/librdkafka/LICENSE.murmur2 +25 -0
  31. package/deps/librdkafka/LICENSE.nanopb +22 -0
  32. package/deps/librdkafka/LICENSE.opentelemetry +203 -0
  33. package/deps/librdkafka/LICENSE.pycrc +23 -0
  34. package/deps/librdkafka/LICENSE.queue +31 -0
  35. package/deps/librdkafka/LICENSE.regexp +5 -0
  36. package/deps/librdkafka/LICENSE.snappy +36 -0
  37. package/deps/librdkafka/LICENSE.tinycthread +26 -0
  38. package/deps/librdkafka/LICENSE.wingetopt +49 -0
  39. package/deps/librdkafka/LICENSES.txt +625 -0
  40. package/deps/librdkafka/Makefile +125 -0
  41. package/deps/librdkafka/README.md +201 -0
  42. package/deps/librdkafka/README.win32 +26 -0
  43. package/deps/librdkafka/STATISTICS.md +624 -0
  44. package/deps/librdkafka/configure +214 -0
  45. package/deps/librdkafka/configure.self +341 -0
  46. package/deps/librdkafka/dev-conf.sh +123 -0
  47. package/deps/librdkafka/lds-gen.py +73 -0
  48. package/deps/librdkafka/mainpage.doxy +40 -0
  49. package/deps/librdkafka/mklove/Makefile.base +329 -0
  50. package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
  51. package/deps/librdkafka/mklove/modules/configure.base +2484 -0
  52. package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
  53. package/deps/librdkafka/mklove/modules/configure.cc +186 -0
  54. package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
  55. package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
  56. package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
  57. package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
  58. package/deps/librdkafka/mklove/modules/configure.host +132 -0
  59. package/deps/librdkafka/mklove/modules/configure.lib +49 -0
  60. package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
  61. package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
  62. package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
  63. package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
  64. package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
  65. package/deps/librdkafka/mklove/modules/configure.pic +16 -0
  66. package/deps/librdkafka/mklove/modules/configure.socket +20 -0
  67. package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
  68. package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
  69. package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
  70. package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
  71. package/deps/librdkafka/service.yml +182 -0
  72. package/deps/librdkafka/src/CMakeLists.txt +379 -0
  73. package/deps/librdkafka/src/Makefile +105 -0
  74. package/deps/librdkafka/src/README.lz4.md +30 -0
  75. package/deps/librdkafka/src/cJSON.c +3191 -0
  76. package/deps/librdkafka/src/cJSON.h +306 -0
  77. package/deps/librdkafka/src/crc32c.c +430 -0
  78. package/deps/librdkafka/src/crc32c.h +38 -0
  79. package/deps/librdkafka/src/generate_proto.sh +66 -0
  80. package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
  81. package/deps/librdkafka/src/lz4.c +2727 -0
  82. package/deps/librdkafka/src/lz4.h +842 -0
  83. package/deps/librdkafka/src/lz4frame.c +2078 -0
  84. package/deps/librdkafka/src/lz4frame.h +692 -0
  85. package/deps/librdkafka/src/lz4frame_static.h +47 -0
  86. package/deps/librdkafka/src/lz4hc.c +1631 -0
  87. package/deps/librdkafka/src/lz4hc.h +413 -0
  88. package/deps/librdkafka/src/nanopb/pb.h +917 -0
  89. package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
  90. package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
  91. package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
  92. package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
  93. package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
  94. package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
  95. package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
  96. package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
  97. package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
  98. package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
  99. package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
  100. package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
  101. package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
  102. package/deps/librdkafka/src/queue.h +850 -0
  103. package/deps/librdkafka/src/rd.h +592 -0
  104. package/deps/librdkafka/src/rdaddr.c +255 -0
  105. package/deps/librdkafka/src/rdaddr.h +202 -0
  106. package/deps/librdkafka/src/rdatomic.h +262 -0
  107. package/deps/librdkafka/src/rdavg.h +260 -0
  108. package/deps/librdkafka/src/rdavl.c +210 -0
  109. package/deps/librdkafka/src/rdavl.h +250 -0
  110. package/deps/librdkafka/src/rdbase64.c +200 -0
  111. package/deps/librdkafka/src/rdbase64.h +43 -0
  112. package/deps/librdkafka/src/rdbuf.c +1884 -0
  113. package/deps/librdkafka/src/rdbuf.h +375 -0
  114. package/deps/librdkafka/src/rdcrc32.c +114 -0
  115. package/deps/librdkafka/src/rdcrc32.h +170 -0
  116. package/deps/librdkafka/src/rddl.c +179 -0
  117. package/deps/librdkafka/src/rddl.h +43 -0
  118. package/deps/librdkafka/src/rdendian.h +175 -0
  119. package/deps/librdkafka/src/rdfloat.h +67 -0
  120. package/deps/librdkafka/src/rdfnv1a.c +113 -0
  121. package/deps/librdkafka/src/rdfnv1a.h +35 -0
  122. package/deps/librdkafka/src/rdgz.c +120 -0
  123. package/deps/librdkafka/src/rdgz.h +46 -0
  124. package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
  125. package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
  126. package/deps/librdkafka/src/rdhttp.c +831 -0
  127. package/deps/librdkafka/src/rdhttp.h +101 -0
  128. package/deps/librdkafka/src/rdinterval.h +177 -0
  129. package/deps/librdkafka/src/rdkafka.c +7287 -0
  130. package/deps/librdkafka/src/rdkafka.h +11795 -0
  131. package/deps/librdkafka/src/rdkafka_admin.c +10165 -0
  132. package/deps/librdkafka/src/rdkafka_admin.h +658 -0
  133. package/deps/librdkafka/src/rdkafka_assignment.c +1282 -0
  134. package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
  135. package/deps/librdkafka/src/rdkafka_assignor.c +1800 -0
  136. package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
  137. package/deps/librdkafka/src/rdkafka_aux.c +409 -0
  138. package/deps/librdkafka/src/rdkafka_aux.h +174 -0
  139. package/deps/librdkafka/src/rdkafka_background.c +222 -0
  140. package/deps/librdkafka/src/rdkafka_broker.c +6736 -0
  141. package/deps/librdkafka/src/rdkafka_broker.h +851 -0
  142. package/deps/librdkafka/src/rdkafka_buf.c +543 -0
  143. package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
  144. package/deps/librdkafka/src/rdkafka_cert.c +576 -0
  145. package/deps/librdkafka/src/rdkafka_cert.h +62 -0
  146. package/deps/librdkafka/src/rdkafka_cgrp.c +8310 -0
  147. package/deps/librdkafka/src/rdkafka_cgrp.h +589 -0
  148. package/deps/librdkafka/src/rdkafka_conf.c +5177 -0
  149. package/deps/librdkafka/src/rdkafka_conf.h +746 -0
  150. package/deps/librdkafka/src/rdkafka_confval.h +97 -0
  151. package/deps/librdkafka/src/rdkafka_coord.c +623 -0
  152. package/deps/librdkafka/src/rdkafka_coord.h +132 -0
  153. package/deps/librdkafka/src/rdkafka_error.c +228 -0
  154. package/deps/librdkafka/src/rdkafka_error.h +80 -0
  155. package/deps/librdkafka/src/rdkafka_event.c +502 -0
  156. package/deps/librdkafka/src/rdkafka_event.h +126 -0
  157. package/deps/librdkafka/src/rdkafka_feature.c +898 -0
  158. package/deps/librdkafka/src/rdkafka_feature.h +104 -0
  159. package/deps/librdkafka/src/rdkafka_fetcher.c +3820 -0
  160. package/deps/librdkafka/src/rdkafka_fetcher.h +62 -0
  161. package/deps/librdkafka/src/rdkafka_header.c +220 -0
  162. package/deps/librdkafka/src/rdkafka_header.h +76 -0
  163. package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
  164. package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
  165. package/deps/librdkafka/src/rdkafka_int.h +1505 -0
  166. package/deps/librdkafka/src/rdkafka_interceptor.c +842 -0
  167. package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
  168. package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
  169. package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
  170. package/deps/librdkafka/src/rdkafka_metadata.c +2347 -0
  171. package/deps/librdkafka/src/rdkafka_metadata.h +350 -0
  172. package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
  173. package/deps/librdkafka/src/rdkafka_mock.c +4514 -0
  174. package/deps/librdkafka/src/rdkafka_mock.h +867 -0
  175. package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1877 -0
  176. package/deps/librdkafka/src/rdkafka_mock_handlers.c +5255 -0
  177. package/deps/librdkafka/src/rdkafka_mock_int.h +1005 -0
  178. package/deps/librdkafka/src/rdkafka_mock_sharegrp.c +1207 -0
  179. package/deps/librdkafka/src/rdkafka_msg.c +2619 -0
  180. package/deps/librdkafka/src/rdkafka_msg.h +629 -0
  181. package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
  182. package/deps/librdkafka/src/rdkafka_msgset.h +105 -0
  183. package/deps/librdkafka/src/rdkafka_msgset_reader.c +2099 -0
  184. package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
  185. package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
  186. package/deps/librdkafka/src/rdkafka_offset.h +150 -0
  187. package/deps/librdkafka/src/rdkafka_op.c +1219 -0
  188. package/deps/librdkafka/src/rdkafka_op.h +1065 -0
  189. package/deps/librdkafka/src/rdkafka_partition.c +5109 -0
  190. package/deps/librdkafka/src/rdkafka_partition.h +1215 -0
  191. package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
  192. package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
  193. package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
  194. package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
  195. package/deps/librdkafka/src/rdkafka_proto.h +739 -0
  196. package/deps/librdkafka/src/rdkafka_protocol.h +131 -0
  197. package/deps/librdkafka/src/rdkafka_queue.c +1351 -0
  198. package/deps/librdkafka/src/rdkafka_queue.h +1235 -0
  199. package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
  200. package/deps/librdkafka/src/rdkafka_request.c +7298 -0
  201. package/deps/librdkafka/src/rdkafka_request.h +761 -0
  202. package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
  203. package/deps/librdkafka/src/rdkafka_sasl.c +589 -0
  204. package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
  205. package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
  206. package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
  207. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
  208. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
  209. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1827 -0
  210. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +52 -0
  211. package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
  212. package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
  213. package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
  214. package/deps/librdkafka/src/rdkafka_share_acknowledgement.c +1445 -0
  215. package/deps/librdkafka/src/rdkafka_share_acknowledgement.h +373 -0
  216. package/deps/librdkafka/src/rdkafka_ssl.c +2235 -0
  217. package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
  218. package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
  219. package/deps/librdkafka/src/rdkafka_subscription.c +411 -0
  220. package/deps/librdkafka/src/rdkafka_telemetry.c +761 -0
  221. package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
  222. package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1307 -0
  223. package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
  224. package/deps/librdkafka/src/rdkafka_telemetry_encode.c +1309 -0
  225. package/deps/librdkafka/src/rdkafka_telemetry_encode.h +459 -0
  226. package/deps/librdkafka/src/rdkafka_timer.c +407 -0
  227. package/deps/librdkafka/src/rdkafka_timer.h +117 -0
  228. package/deps/librdkafka/src/rdkafka_topic.c +2382 -0
  229. package/deps/librdkafka/src/rdkafka_topic.h +369 -0
  230. package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
  231. package/deps/librdkafka/src/rdkafka_transport.h +99 -0
  232. package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
  233. package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
  234. package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
  235. package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
  236. package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
  237. package/deps/librdkafka/src/rdlist.c +593 -0
  238. package/deps/librdkafka/src/rdlist.h +444 -0
  239. package/deps/librdkafka/src/rdlog.c +89 -0
  240. package/deps/librdkafka/src/rdlog.h +41 -0
  241. package/deps/librdkafka/src/rdmap.c +508 -0
  242. package/deps/librdkafka/src/rdmap.h +492 -0
  243. package/deps/librdkafka/src/rdmurmur2.c +167 -0
  244. package/deps/librdkafka/src/rdmurmur2.h +35 -0
  245. package/deps/librdkafka/src/rdports.c +61 -0
  246. package/deps/librdkafka/src/rdports.h +38 -0
  247. package/deps/librdkafka/src/rdposix.h +250 -0
  248. package/deps/librdkafka/src/rdrand.c +151 -0
  249. package/deps/librdkafka/src/rdrand.h +72 -0
  250. package/deps/librdkafka/src/rdregex.c +156 -0
  251. package/deps/librdkafka/src/rdregex.h +43 -0
  252. package/deps/librdkafka/src/rdsignal.h +57 -0
  253. package/deps/librdkafka/src/rdstring.c +645 -0
  254. package/deps/librdkafka/src/rdstring.h +98 -0
  255. package/deps/librdkafka/src/rdsysqueue.h +404 -0
  256. package/deps/librdkafka/src/rdtime.h +356 -0
  257. package/deps/librdkafka/src/rdtypes.h +86 -0
  258. package/deps/librdkafka/src/rdunittest.c +564 -0
  259. package/deps/librdkafka/src/rdunittest.h +232 -0
  260. package/deps/librdkafka/src/rdunittest_acknowledge.c +1177 -0
  261. package/deps/librdkafka/src/rdunittest_fetcher.c +1211 -0
  262. package/deps/librdkafka/src/rdunittest_msgset_errors.c +1521 -0
  263. package/deps/librdkafka/src/rdvarint.c +134 -0
  264. package/deps/librdkafka/src/rdvarint.h +165 -0
  265. package/deps/librdkafka/src/rdwin32.h +382 -0
  266. package/deps/librdkafka/src/rdxxhash.c +1030 -0
  267. package/deps/librdkafka/src/rdxxhash.h +328 -0
  268. package/deps/librdkafka/src/regexp.c +1352 -0
  269. package/deps/librdkafka/src/regexp.h +41 -0
  270. package/deps/librdkafka/src/snappy.c +1866 -0
  271. package/deps/librdkafka/src/snappy.h +62 -0
  272. package/deps/librdkafka/src/snappy_compat.h +138 -0
  273. package/deps/librdkafka/src/statistics_schema.json +444 -0
  274. package/deps/librdkafka/src/tinycthread.c +932 -0
  275. package/deps/librdkafka/src/tinycthread.h +503 -0
  276. package/deps/librdkafka/src/tinycthread_extra.c +210 -0
  277. package/deps/librdkafka/src/tinycthread_extra.h +218 -0
  278. package/deps/librdkafka/src/win32_config.h +58 -0
  279. package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
  280. package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
  281. package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
  282. package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
  283. package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
  284. package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
  285. package/deps/librdkafka/src-cpp/Makefile +55 -0
  286. package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
  287. package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
  288. package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
  289. package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
  290. package/deps/librdkafka/src-cpp/README.md +16 -0
  291. package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
  292. package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
  293. package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
  294. package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
  295. package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
  296. package/deps/librdkafka/tests/0000-unittests.c +72 -0
  297. package/deps/librdkafka/tests/0001-multiobj.c +102 -0
  298. package/deps/librdkafka/tests/0002-unkpart.c +244 -0
  299. package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
  300. package/deps/librdkafka/tests/0004-conf.c +934 -0
  301. package/deps/librdkafka/tests/0005-order.c +133 -0
  302. package/deps/librdkafka/tests/0006-symbols.c +163 -0
  303. package/deps/librdkafka/tests/0007-autotopic.c +136 -0
  304. package/deps/librdkafka/tests/0008-reqacks.c +179 -0
  305. package/deps/librdkafka/tests/0009-mock_cluster.c +272 -0
  306. package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
  307. package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
  308. package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
  309. package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
  310. package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
  311. package/deps/librdkafka/tests/0016-client_swname.c +181 -0
  312. package/deps/librdkafka/tests/0017-compression.c +140 -0
  313. package/deps/librdkafka/tests/0018-cgrp_term.c +444 -0
  314. package/deps/librdkafka/tests/0019-list_groups.c +289 -0
  315. package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
  316. package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
  317. package/deps/librdkafka/tests/0022-consume_batch.c +331 -0
  318. package/deps/librdkafka/tests/0025-timers.c +147 -0
  319. package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
  320. package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
  321. package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
  322. package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
  323. package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
  324. package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
  325. package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
  326. package/deps/librdkafka/tests/0035-api_version.c +73 -0
  327. package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
  328. package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
  329. package/deps/librdkafka/tests/0038-performance.c +121 -0
  330. package/deps/librdkafka/tests/0039-event.c +284 -0
  331. package/deps/librdkafka/tests/0040-io_event.c +257 -0
  332. package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
  333. package/deps/librdkafka/tests/0042-many_topics.c +252 -0
  334. package/deps/librdkafka/tests/0043-no_connection.c +77 -0
  335. package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
  336. package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
  337. package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
  338. package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
  339. package/deps/librdkafka/tests/0048-partitioner.c +283 -0
  340. package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
  341. package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
  342. package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
  343. package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
  344. package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
  345. package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
  346. package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
  347. package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
  348. package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
  349. package/deps/librdkafka/tests/0058-log.cpp +123 -0
  350. package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
  351. package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
  352. package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
  353. package/deps/librdkafka/tests/0062-stats_event.c +126 -0
  354. package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
  355. package/deps/librdkafka/tests/0064-interceptors.c +529 -0
  356. package/deps/librdkafka/tests/0065-yield.cpp +140 -0
  357. package/deps/librdkafka/tests/0066-plugins.cpp +143 -0
  358. package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
  359. package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
  360. package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
  361. package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
  362. package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
  363. package/deps/librdkafka/tests/0073-headers.c +381 -0
  364. package/deps/librdkafka/tests/0074-producev.c +87 -0
  365. package/deps/librdkafka/tests/0075-retry.c +290 -0
  366. package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
  367. package/deps/librdkafka/tests/0077-compaction.c +366 -0
  368. package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
  369. package/deps/librdkafka/tests/0079-fork.c +93 -0
  370. package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
  371. package/deps/librdkafka/tests/0081-admin.c +5633 -0
  372. package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
  373. package/deps/librdkafka/tests/0083-cb_event.c +233 -0
  374. package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
  375. package/deps/librdkafka/tests/0085-headers.cpp +392 -0
  376. package/deps/librdkafka/tests/0086-purge.c +368 -0
  377. package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
  378. package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
  379. package/deps/librdkafka/tests/0090-idempotence.c +171 -0
  380. package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
  381. package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
  382. package/deps/librdkafka/tests/0093-holb.c +200 -0
  383. package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
  384. package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
  385. package/deps/librdkafka/tests/0097-ssl_verify.cpp +674 -0
  386. package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
  387. package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
  388. package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
  389. package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
  390. package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
  391. package/deps/librdkafka/tests/0103-transactions.c +1383 -0
  392. package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
  393. package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
  394. package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
  395. package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
  396. package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
  397. package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
  398. package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
  399. package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
  400. package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
  401. package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
  402. package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
  403. package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
  404. package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
  405. package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
  406. package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
  407. package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
  408. package/deps/librdkafka/tests/0121-clusterid.c +115 -0
  409. package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
  410. package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
  411. package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
  412. package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
  413. package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +1164 -0
  414. package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
  415. package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +217 -0
  416. package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
  417. package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
  418. package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
  419. package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
  420. package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
  421. package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
  422. package/deps/librdkafka/tests/0135-sasl_credentials.cpp +279 -0
  423. package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
  424. package/deps/librdkafka/tests/0137-barrier_batch_consume.c +752 -0
  425. package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
  426. package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
  427. package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
  428. package/deps/librdkafka/tests/0142-reauthentication.c +931 -0
  429. package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
  430. package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
  431. package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
  432. package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
  433. package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +1210 -0
  434. package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +569 -0
  435. package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
  436. package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
  437. package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
  438. package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
  439. package/deps/librdkafka/tests/0153-memberid.c +128 -0
  440. package/deps/librdkafka/tests/0155-share_group_heartbeat_mock.c +2695 -0
  441. package/deps/librdkafka/tests/0156-share_consumer_fetch_mock.c +1551 -0
  442. package/deps/librdkafka/tests/0157-share_consumer_ack_mock.c +1788 -0
  443. package/deps/librdkafka/tests/0158-share_consumer_transactions_mock.c +467 -0
  444. package/deps/librdkafka/tests/0170-share_consumer_subscription.c +2192 -0
  445. package/deps/librdkafka/tests/0171-share_consumer_consume.c +2150 -0
  446. package/deps/librdkafka/tests/0172-share_consumer_acknowledge.c +1919 -0
  447. package/deps/librdkafka/tests/0173-share_consumer_commit_async.c +2735 -0
  448. package/deps/librdkafka/tests/0174-share_consumer_concurrency.c +1434 -0
  449. package/deps/librdkafka/tests/0175-share_consumer_groups.c +574 -0
  450. package/deps/librdkafka/tests/0176-share_consumer_commit_sync.c +2986 -0
  451. package/deps/librdkafka/tests/0177-share_consumer_transactions.c +1815 -0
  452. package/deps/librdkafka/tests/0178-share_consumer_close.c +2102 -0
  453. package/deps/librdkafka/tests/0179-share_consumer_destroy.c +2482 -0
  454. package/deps/librdkafka/tests/0180-share_consumer_config.c +1677 -0
  455. package/deps/librdkafka/tests/0181-share_consumer_topic_delete.c +354 -0
  456. package/deps/librdkafka/tests/0182-share_consumer_error_handling_mock.c +3358 -0
  457. package/deps/librdkafka/tests/0183-share_consumer_leader_change_mock.c +1234 -0
  458. package/deps/librdkafka/tests/0184-share_consumer_topic_recreate.c +1356 -0
  459. package/deps/librdkafka/tests/0185-share_consumer_max_poll_interval.c +557 -0
  460. package/deps/librdkafka/tests/0186-share_consumer_fatal_error.c +360 -0
  461. package/deps/librdkafka/tests/0190-share_consumer_telemetry.c +387 -0
  462. package/deps/librdkafka/tests/1000-unktopic.c +164 -0
  463. package/deps/librdkafka/tests/8000-idle.cpp +60 -0
  464. package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
  465. package/deps/librdkafka/tests/CMakeLists.txt +193 -0
  466. package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
  467. package/deps/librdkafka/tests/Makefile +182 -0
  468. package/deps/librdkafka/tests/README.md +514 -0
  469. package/deps/librdkafka/tests/autotest.sh +33 -0
  470. package/deps/librdkafka/tests/backtrace.gdb +30 -0
  471. package/deps/librdkafka/tests/broker_version_tests.py +315 -0
  472. package/deps/librdkafka/tests/buildbox.sh +17 -0
  473. package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
  474. package/deps/librdkafka/tests/cluster_testing.py +203 -0
  475. package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
  476. package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
  477. package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
  478. package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -0
  479. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
  480. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
  481. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
  482. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +50 -0
  483. package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
  484. package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
  485. package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
  486. package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
  487. package/deps/librdkafka/tests/fuzzers/README.md +31 -0
  488. package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
  489. package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
  490. package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
  491. package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
  492. package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
  493. package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
  494. package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
  495. package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
  496. package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
  497. package/deps/librdkafka/tests/java/Makefile +13 -0
  498. package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
  499. package/deps/librdkafka/tests/java/README.md +14 -0
  500. package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
  501. package/deps/librdkafka/tests/java/run-class.sh +11 -0
  502. package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
  503. package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
  504. package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
  505. package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
  506. package/deps/librdkafka/tests/performance_plot.py +115 -0
  507. package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
  508. package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
  509. package/deps/librdkafka/tests/requirements.txt +2 -0
  510. package/deps/librdkafka/tests/run-all-tests.sh +81 -0
  511. package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
  512. package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
  513. package/deps/librdkafka/tests/run-test-batches.py +157 -0
  514. package/deps/librdkafka/tests/run-test.sh +141 -0
  515. package/deps/librdkafka/tests/rusage.c +249 -0
  516. package/deps/librdkafka/tests/sasl_test.py +289 -0
  517. package/deps/librdkafka/tests/scenarios/README.md +6 -0
  518. package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
  519. package/deps/librdkafka/tests/scenarios/default.json +5 -0
  520. package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
  521. package/deps/librdkafka/tests/share_telemetry_verify/share-otel-collector-config.yaml +28 -0
  522. package/deps/librdkafka/tests/sockem.c +801 -0
  523. package/deps/librdkafka/tests/sockem.h +85 -0
  524. package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
  525. package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
  526. package/deps/librdkafka/tests/test.c +8376 -0
  527. package/deps/librdkafka/tests/test.conf.example +27 -0
  528. package/deps/librdkafka/tests/test.h +1150 -0
  529. package/deps/librdkafka/tests/testcpp.cpp +131 -0
  530. package/deps/librdkafka/tests/testcpp.h +388 -0
  531. package/deps/librdkafka/tests/testshared.h +416 -0
  532. package/deps/librdkafka/tests/tools/README.md +4 -0
  533. package/deps/librdkafka/tests/tools/stats/README.md +21 -0
  534. package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
  535. package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
  536. package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
  537. package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
  538. package/deps/librdkafka/tests/trivup/trivup-0.15.0.tar.gz +0 -0
  539. package/deps/librdkafka/tests/until-fail.sh +87 -0
  540. package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
  541. package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
  542. package/deps/librdkafka/vcpkg.json +23 -0
  543. package/deps/librdkafka/win32/README.md +5 -0
  544. package/deps/librdkafka/win32/build-package.bat +3 -0
  545. package/deps/librdkafka/win32/build.bat +19 -0
  546. package/deps/librdkafka/win32/common.vcxproj +84 -0
  547. package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
  548. package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
  549. package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
  550. package/deps/librdkafka/win32/librdkafka.sln +226 -0
  551. package/deps/librdkafka/win32/librdkafka.vcxproj +282 -0
  552. package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
  553. package/deps/librdkafka/win32/msbuild.ps1 +58 -0
  554. package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
  555. package/deps/librdkafka/win32/package-zip.ps1 +46 -0
  556. package/deps/librdkafka/win32/packages/repositories.config +4 -0
  557. package/deps/librdkafka/win32/push-package.bat +4 -0
  558. package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
  559. package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
  560. package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
  561. package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
  562. package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
  563. package/deps/librdkafka/win32/tests/test.conf.example +25 -0
  564. package/deps/librdkafka/win32/tests/tests.vcxproj +278 -0
  565. package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
  566. package/deps/librdkafka/win32/wingetopt.c +564 -0
  567. package/deps/librdkafka/win32/wingetopt.h +101 -0
  568. package/deps/librdkafka/win32/wintime.h +33 -0
  569. package/deps/librdkafka.gyp +83 -0
  570. package/deps/windows-install.py +80 -0
  571. package/index.d.ts +3 -0
  572. package/lib/admin.js +732 -0
  573. package/lib/client.js +679 -0
  574. package/lib/error.js +501 -0
  575. package/lib/index.js +8 -0
  576. package/lib/kafka-consumer-stream.js +399 -0
  577. package/lib/kafka-consumer.js +798 -0
  578. package/lib/kafkajs/_admin.js +1052 -0
  579. package/lib/kafkajs/_common.js +887 -0
  580. package/lib/kafkajs/_consumer.js +2156 -0
  581. package/lib/kafkajs/_consumer_cache.js +310 -0
  582. package/lib/kafkajs/_error.js +298 -0
  583. package/lib/kafkajs/_kafka.js +125 -0
  584. package/lib/kafkajs/_linked-list.js +220 -0
  585. package/lib/kafkajs/_producer.js +863 -0
  586. package/lib/kafkajs/index.js +5 -0
  587. package/lib/producer/high-level-producer.js +400 -0
  588. package/lib/producer-stream.js +337 -0
  589. package/lib/producer.js +405 -0
  590. package/lib/rdkafka.js +44 -0
  591. package/lib/tools/ref-counter.js +53 -0
  592. package/lib/topic-partition.js +91 -0
  593. package/lib/topic.js +43 -0
  594. package/lib/util.js +55 -0
  595. package/librdkafka.js +12 -0
  596. package/package.json +85 -0
  597. package/shim/source_location +54 -0
  598. package/src/admin.cc +1597 -0
  599. package/src/admin.h +112 -0
  600. package/src/binding.cc +76 -0
  601. package/src/binding.h +25 -0
  602. package/src/callbacks.cc +676 -0
  603. package/src/callbacks.h +302 -0
  604. package/src/common.cc +1628 -0
  605. package/src/common.h +192 -0
  606. package/src/config.cc +219 -0
  607. package/src/config.h +61 -0
  608. package/src/connection.cc +703 -0
  609. package/src/connection.h +117 -0
  610. package/src/errors.cc +119 -0
  611. package/src/errors.h +60 -0
  612. package/src/kafka-consumer.cc +1539 -0
  613. package/src/kafka-consumer.h +147 -0
  614. package/src/producer.cc +917 -0
  615. package/src/producer.h +124 -0
  616. package/src/topic.cc +173 -0
  617. package/src/topic.h +54 -0
  618. package/src/workers.cc +1714 -0
  619. package/src/workers.h +690 -0
  620. package/types/config.d.ts +1269 -0
  621. package/types/errors.d.ts +373 -0
  622. package/types/kafkajs.d.ts +568 -0
  623. package/types/rdkafka.d.ts +571 -0
  624. package/util/configure.js +32 -0
  625. package/util/generate-docs.sh +18 -0
  626. package/util/get-env.js +6 -0
  627. package/util/test-compile.js +11 -0
  628. 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