@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
@@ -0,0 +1,1282 @@
1
+ /*
2
+ * librdkafka - The Apache Kafka C/C++ library
3
+ *
4
+ * Copyright (c) 2020-2022, Magnus Edenhill
5
+ * 2023 Confluent Inc.
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright notice,
12
+ * this list of conditions and the following disclaimer.
13
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ * this list of conditions and the following disclaimer in the documentation
15
+ * and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ * POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+
31
+ /**
32
+ * @name Consumer assignment state.
33
+ *
34
+ * Responsible for managing the state of assigned partitions.
35
+ *
36
+ *
37
+ ******************************************************************************
38
+ * rd_kafka_assignment_serve()
39
+ * ---------------------------
40
+ *
41
+ * It is important to call rd_kafka_assignment_serve() after each change
42
+ * to the assignment through assignment_add, assignment_subtract or
43
+ * assignment_clear as those functions only modify the assignment but does
44
+ * not take any action to transition partitions to or from the assignment
45
+ * states.
46
+ *
47
+ * The reason assignment_serve() is not automatically called from these
48
+ * functions is for the caller to be able to set the current state before
49
+ * the side-effects of serve() kick in, such as the call to
50
+ * rd_kafka_cgrp_assignment_done() that in turn will set the cgrp state.
51
+ *
52
+ *
53
+ *
54
+ ******************************************************************************
55
+ * Querying for committed offsets (.queried list)
56
+ * ----------------------------------------------
57
+ *
58
+ * We only allow one outstanding query (fetch committed offset), this avoids
59
+ * complex handling of partitions that are assigned, unassigned and reassigned
60
+ * all within the window of a OffsetFetch request.
61
+ * Consider the following case:
62
+ *
63
+ * 1. tp1 and tp2 are incrementally assigned.
64
+ * 2. An OffsetFetchRequest is sent for tp1 and tp2
65
+ * 3. tp2 is incremental unassigned.
66
+ * 4. Broker sends OffsetFetchResponse with offsets tp1=10, tp2=20.
67
+ * 4. Some other consumer commits offsets 30 for tp2.
68
+ * 5. tp2 is incrementally assigned again.
69
+ * 6. The OffsetFetchResponse is received.
70
+ *
71
+ * Without extra handling the consumer would start fetching tp1 at offset 10
72
+ * (which is correct) and tp2 at offset 20 (which is incorrect, the last
73
+ * committed offset is now 30).
74
+ *
75
+ * To alleviate this situation we remove unassigned partitions from the
76
+ * .queried list, and in the OffsetFetch response handler we only use offsets
77
+ * for partitions that are on the .queried list.
78
+ *
79
+ * To make sure the tp1 offset is used and not re-queried we only allow
80
+ * one outstanding OffsetFetch request at the time, meaning that at step 5
81
+ * a new OffsetFetch request will not be sent and tp2 will remain in the
82
+ * .pending list until the outstanding OffsetFetch response is received in
83
+ * step 6. At this point tp2 will transition to .queried and a new
84
+ * OffsetFetch request will be sent.
85
+ *
86
+ * This explanation is more verbose than the code involved.
87
+ *
88
+ ******************************************************************************
89
+ *
90
+ *
91
+ * @remark Try to keep any cgrp state out of this file.
92
+ *
93
+ * FIXME: There are some pretty obvious optimizations that needs to be done here
94
+ * with regards to partition_list_t lookups. But we can do that when
95
+ * we know the current implementation works correctly.
96
+ */
97
+
98
+ #include "rdkafka_int.h"
99
+ #include "rdkafka_cgrp.h"
100
+ #include "rdkafka_offset.h"
101
+ #include "rdkafka_request.h"
102
+
103
+
104
+ static void rd_kafka_assignment_dump(rd_kafka_t *rk) {
105
+ rd_kafka_dbg(rk, CGRP, "DUMP",
106
+ "Assignment dump (started_cnt=%d, wait_stop_cnt=%d)",
107
+ rk->rk_consumer.assignment.started_cnt,
108
+ rk->rk_consumer.assignment.wait_stop_cnt);
109
+
110
+ rd_kafka_topic_partition_list_log(rk, "DUMP_ALL", RD_KAFKA_DBG_CGRP,
111
+ rk->rk_consumer.assignment.all);
112
+
113
+ rd_kafka_topic_partition_list_log(rk, "DUMP_PND", RD_KAFKA_DBG_CGRP,
114
+ rk->rk_consumer.assignment.pending);
115
+
116
+ rd_kafka_topic_partition_list_log(rk, "DUMP_QRY", RD_KAFKA_DBG_CGRP,
117
+ rk->rk_consumer.assignment.queried);
118
+
119
+ rd_kafka_topic_partition_list_log(rk, "DUMP_REM", RD_KAFKA_DBG_CGRP,
120
+ rk->rk_consumer.assignment.removed);
121
+ }
122
+
123
+ /**
124
+ * @brief Apply the fetched committed offsets to the current assignment's
125
+ * queried partitions.
126
+ *
127
+ * @param err is the request-level error, if any. The caller is responsible
128
+ * for raising this error to the application. It is only used here
129
+ * to avoid taking actions.
130
+ *
131
+ * Called from the FetchOffsets response handler below.
132
+ */
133
+ static void
134
+ rd_kafka_assignment_apply_offsets(rd_kafka_t *rk,
135
+ rd_kafka_topic_partition_list_t *offsets,
136
+ rd_kafka_resp_err_t err) {
137
+ rd_kafka_topic_partition_t *rktpar;
138
+
139
+ RD_KAFKA_TPLIST_FOREACH(rktpar, offsets) {
140
+ /* May be NULL, borrow ref. */
141
+ rd_kafka_toppar_t *rktp =
142
+ rd_kafka_topic_partition_toppar(rk, rktpar);
143
+
144
+ if (!rd_kafka_topic_partition_list_del(
145
+ rk->rk_consumer.assignment.queried, rktpar->topic,
146
+ rktpar->partition)) {
147
+ rd_kafka_dbg(rk, CGRP, "OFFSETFETCH",
148
+ "Ignoring OffsetFetch "
149
+ "response for %s [%" PRId32
150
+ "] which is no "
151
+ "longer in the queried list "
152
+ "(possibly unassigned?)",
153
+ rktpar->topic, rktpar->partition);
154
+ continue;
155
+ }
156
+
157
+ if (err == RD_KAFKA_RESP_ERR_STALE_MEMBER_EPOCH ||
158
+ rktpar->err == RD_KAFKA_RESP_ERR_STALE_MEMBER_EPOCH) {
159
+ rd_kafka_topic_partition_t *rktpar_copy;
160
+
161
+ rd_kafka_dbg(rk, CGRP, "OFFSETFETCH",
162
+ "Adding %s [%" PRId32
163
+ "] back to pending "
164
+ "list because of stale member epoch",
165
+ rktpar->topic, rktpar->partition);
166
+
167
+ rktpar_copy = rd_kafka_topic_partition_list_add_copy(
168
+ rk->rk_consumer.assignment.pending, rktpar);
169
+ /* Need to reset offset to STORED to query for
170
+ * the committed offset again. If the offset is
171
+ * kept INVALID then auto.offset.reset will be
172
+ * triggered.
173
+ *
174
+ * Not necessary if err is UNSTABLE_OFFSET_COMMIT
175
+ * because the buffer is retried there. */
176
+ rktpar_copy->offset = RD_KAFKA_OFFSET_STORED;
177
+
178
+ } else if (err == RD_KAFKA_RESP_ERR_UNSTABLE_OFFSET_COMMIT ||
179
+ rktpar->err ==
180
+ RD_KAFKA_RESP_ERR_UNSTABLE_OFFSET_COMMIT) {
181
+ /* Ongoing transactions are blocking offset retrieval.
182
+ * This is typically retried from the OffsetFetch
183
+ * handler but we can come here if the assignment
184
+ * (and thus the assignment.version) was changed while
185
+ * the OffsetFetch request was in-flight, in which case
186
+ * we put this partition back on the pending list for
187
+ * later handling by the assignment state machine. */
188
+
189
+ rd_kafka_dbg(rk, CGRP, "OFFSETFETCH",
190
+ "Adding %s [%" PRId32
191
+ "] back to pending "
192
+ "list because on-going transaction is "
193
+ "blocking offset retrieval",
194
+ rktpar->topic, rktpar->partition);
195
+
196
+ rd_kafka_topic_partition_list_add_copy(
197
+ rk->rk_consumer.assignment.pending, rktpar);
198
+
199
+ } else if (rktpar->err) {
200
+ /* Partition-level error */
201
+ rd_kafka_consumer_err(
202
+ rk->rk_consumer.q, RD_KAFKA_NODEID_UA, rktpar->err,
203
+ 0, rktpar->topic, rktp, RD_KAFKA_OFFSET_INVALID,
204
+ "Failed to fetch committed offset for "
205
+ "group \"%s\" topic %s [%" PRId32 "]: %s",
206
+ rk->rk_group_id->str, rktpar->topic,
207
+ rktpar->partition, rd_kafka_err2str(rktpar->err));
208
+
209
+ /* The partition will not be added back to .pending
210
+ * and thus only reside on .all until the application
211
+ * unassigns it and possible re-assigns it. */
212
+
213
+ } else if (!err) {
214
+ /* If rktpar->offset is RD_KAFKA_OFFSET_INVALID it means
215
+ * there was no committed offset for this partition.
216
+ * serve_pending() will now start this partition
217
+ * since the offset is set to INVALID (rather than
218
+ * STORED) and the partition fetcher will employ
219
+ * auto.offset.reset to know what to do. */
220
+
221
+ /* Add partition to pending list where serve()
222
+ * will start the fetcher. */
223
+ rd_kafka_dbg(rk, CGRP, "OFFSETFETCH",
224
+ "Adding %s [%" PRId32
225
+ "] back to pending "
226
+ "list with offset %s",
227
+ rktpar->topic, rktpar->partition,
228
+ rd_kafka_offset2str(rktpar->offset));
229
+
230
+ rd_kafka_topic_partition_list_add_copy(
231
+ rk->rk_consumer.assignment.pending, rktpar);
232
+ }
233
+ /* Do nothing for request-level errors (err is set). */
234
+ }
235
+
236
+ /* In case of stale member epoch we retry to serve the
237
+ * assignment only after a successful ConsumerGroupHeartbeat. */
238
+ if (offsets->cnt > 0 && err != RD_KAFKA_RESP_ERR_STALE_MEMBER_EPOCH)
239
+ rd_kafka_assignment_serve(rk);
240
+ }
241
+
242
+
243
+
244
+ /**
245
+ * @brief Reply handler for OffsetFetch queries from the assignment code.
246
+ *
247
+ * @param opaque Is a malloced int64_t* containing the assignment version at the
248
+ * time of the request.
249
+ *
250
+ * @locality rdkafka main thread
251
+ */
252
+ static void rd_kafka_assignment_handle_OffsetFetch(rd_kafka_t *rk,
253
+ rd_kafka_broker_t *rkb,
254
+ rd_kafka_resp_err_t err,
255
+ rd_kafka_buf_t *reply,
256
+ rd_kafka_buf_t *request,
257
+ void *opaque) {
258
+ rd_kafka_topic_partition_list_t *offsets = NULL;
259
+ int64_t *req_assignment_version = (int64_t *)opaque;
260
+ /* Only allow retries if there's been no change to the assignment,
261
+ * otherwise rely on assignment state machine to retry. */
262
+ rd_bool_t allow_retry =
263
+ *req_assignment_version == rk->rk_consumer.assignment.version;
264
+
265
+ if (err == RD_KAFKA_RESP_ERR__DESTROY) {
266
+ /* Termination, quick cleanup. */
267
+ rd_free(req_assignment_version);
268
+ return;
269
+ }
270
+
271
+ err = rd_kafka_handle_OffsetFetch(
272
+ rk, rkb, err, reply, request, &offsets,
273
+ rd_true /* Update toppars */, rd_true /* Add parts */, allow_retry);
274
+ if (err == RD_KAFKA_RESP_ERR__IN_PROGRESS) {
275
+ if (offsets)
276
+ rd_kafka_topic_partition_list_destroy(offsets);
277
+ return; /* retrying */
278
+ }
279
+
280
+ rd_free(req_assignment_version);
281
+
282
+ /* offsets may be NULL for certain errors, such
283
+ * as ERR__TRANSPORT. */
284
+ if (!offsets && !allow_retry) {
285
+ rd_dassert(err);
286
+ if (!err)
287
+ err = RD_KAFKA_RESP_ERR__NO_OFFSET;
288
+
289
+ rd_kafka_dbg(rk, CGRP, "OFFSET", "Offset fetch error: %s",
290
+ rd_kafka_err2str(err));
291
+ rd_kafka_consumer_err(
292
+ rk->rk_consumer.q, rd_kafka_broker_id(rkb), err, 0, NULL,
293
+ NULL, RD_KAFKA_OFFSET_INVALID,
294
+ "Failed to fetch committed "
295
+ "offsets for partitions "
296
+ "in group \"%s\": %s",
297
+ rk->rk_group_id->str, rd_kafka_err2str(err));
298
+
299
+ return;
300
+ }
301
+
302
+ if (err) {
303
+ switch (err) {
304
+ case RD_KAFKA_RESP_ERR_STALE_MEMBER_EPOCH:
305
+ rk->rk_cgrp->rkcg_consumer_flags |=
306
+ RD_KAFKA_CGRP_CONSUMER_F_SERVE_PENDING;
307
+ rd_kafka_cgrp_consumer_expedite_next_heartbeat(
308
+ rk->rk_cgrp,
309
+ "OffsetFetch error: Stale member epoch");
310
+ break;
311
+ case RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID:
312
+ rd_kafka_cgrp_consumer_expedite_next_heartbeat(
313
+ rk->rk_cgrp, "OffsetFetch error: Unknown member");
314
+ break;
315
+ default:
316
+ rd_kafka_dbg(
317
+ rk, CGRP, "OFFSET",
318
+ "Offset fetch error for %d partition(s): %s",
319
+ offsets->cnt, rd_kafka_err2str(err));
320
+ rd_kafka_consumer_err(
321
+ rk->rk_consumer.q, rd_kafka_broker_id(rkb), err, 0,
322
+ NULL, NULL, RD_KAFKA_OFFSET_INVALID,
323
+ "Failed to fetch committed offsets for "
324
+ "%d partition(s) in group \"%s\": %s",
325
+ offsets->cnt, rk->rk_group_id->str,
326
+ rd_kafka_err2str(err));
327
+ }
328
+ }
329
+
330
+ /* Apply the fetched offsets to the assignment */
331
+ rd_kafka_assignment_apply_offsets(rk, offsets, err);
332
+
333
+ rd_kafka_topic_partition_list_destroy(offsets);
334
+ }
335
+
336
+ static void rd_kafka_share_assignment_serve_removals(rd_kafka_t *rk) {
337
+ rd_kafka_topic_partition_t *rktpar;
338
+
339
+ RD_KAFKA_TPLIST_FOREACH(rktpar, rk->rk_consumer.assignment.removed) {
340
+ rd_kafka_toppar_t *rktp =
341
+ rd_kafka_topic_partition_ensure_toppar(
342
+ rk, rktpar, rd_true); /* Borrow ref */
343
+
344
+ /* Remove from pending list if present */
345
+ rd_kafka_topic_partition_list_del(
346
+ rk->rk_consumer.assignment.pending, rktpar->topic,
347
+ rktpar->partition);
348
+
349
+ /* Detach the partition from the cgrp directly. This sends
350
+ * SHARE_SESSION_PARTITION_REMOVE to the partition's broker
351
+ * so it queues a forget on the next ShareFetch. */
352
+ rd_dassert(rktp->rktp_cgrp);
353
+ rd_kafka_cgrp_partition_del(rktp->rktp_cgrp, rktp);
354
+
355
+ /* desired_del requires both topic_wrlock and toppar_lock. */
356
+ rd_kafka_topic_wrlock(rktp->rktp_rkt);
357
+ rd_kafka_toppar_lock(rktp);
358
+
359
+ /* No longer desired */
360
+ rd_kafka_toppar_desired_del(rktp);
361
+
362
+ rd_kafka_toppar_unlock(rktp);
363
+ rd_kafka_topic_wrunlock(rktp->rktp_rkt);
364
+
365
+ rd_kafka_dbg(rk, CGRP, "REMOVE",
366
+ "Removing %s [%" PRId32 "] from share assignment",
367
+ rktpar->topic, rktpar->partition);
368
+ }
369
+
370
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "REMOVE",
371
+ "Served %d removed partition(s).",
372
+ rk->rk_consumer.assignment.removed->cnt);
373
+
374
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.removed);
375
+ }
376
+
377
+
378
+ /**
379
+ * @brief Decommission all partitions in the removed list.
380
+ *
381
+ * @returns >0 if there are removal operations in progress, else 0.
382
+ */
383
+ static int rd_kafka_assignment_serve_removals(rd_kafka_t *rk) {
384
+ rd_kafka_topic_partition_t *rktpar;
385
+ int valid_offsets = 0;
386
+
387
+ RD_KAFKA_TPLIST_FOREACH(rktpar, rk->rk_consumer.assignment.removed) {
388
+ rd_kafka_toppar_t *rktp =
389
+ rd_kafka_topic_partition_ensure_toppar(
390
+ rk, rktpar, rd_true); /* Borrow ref */
391
+ int was_pending, was_queried;
392
+
393
+ /* Remove partition from pending and querying lists,
394
+ * if it happens to be there.
395
+ * Outstanding OffsetFetch query results will be ignored
396
+ * for partitions that are no longer on the .queried list. */
397
+ was_pending = rd_kafka_topic_partition_list_del(
398
+ rk->rk_consumer.assignment.pending, rktpar->topic,
399
+ rktpar->partition);
400
+ was_queried = rd_kafka_topic_partition_list_del(
401
+ rk->rk_consumer.assignment.queried, rktpar->topic,
402
+ rktpar->partition);
403
+
404
+ if (rktp->rktp_started) {
405
+ /* Partition was started, stop the fetcher. */
406
+ rd_assert(rk->rk_consumer.assignment.started_cnt > 0);
407
+
408
+ rd_kafka_toppar_op_fetch_stop(
409
+ rktp, RD_KAFKA_REPLYQ(rk->rk_ops, 0));
410
+ rk->rk_consumer.assignment.wait_stop_cnt++;
411
+ }
412
+
413
+ /* Reset the (lib) pause flag which may have been set by
414
+ * the cgrp when scheduling the rebalance callback. */
415
+ rd_kafka_toppar_op_pause_resume(rktp, rd_false /*resume*/,
416
+ RD_KAFKA_TOPPAR_F_LIB_PAUSE,
417
+ RD_KAFKA_NO_REPLYQ);
418
+
419
+ rd_kafka_toppar_lock(rktp);
420
+
421
+ /* Save the currently stored offset and epoch on .removed
422
+ * so it will be committed below. */
423
+ rd_kafka_topic_partition_set_from_fetch_pos(
424
+ rktpar, rktp->rktp_stored_pos);
425
+ rd_kafka_topic_partition_set_metadata_from_rktp_stored(rktpar,
426
+ rktp);
427
+ valid_offsets += !RD_KAFKA_OFFSET_IS_LOGICAL(rktpar->offset);
428
+
429
+ /* Reset the stored offset to invalid so that
430
+ * a manual offset-less commit() or the auto-committer
431
+ * will not commit a stored offset from a previous
432
+ * assignment (issue #2782). */
433
+ rd_kafka_offset_store0(
434
+ rktp, RD_KAFKA_FETCH_POS(RD_KAFKA_OFFSET_INVALID, -1), NULL,
435
+ 0, rd_true, RD_DONT_LOCK);
436
+
437
+ /* Partition is no longer desired */
438
+ rd_kafka_toppar_desired_del(rktp);
439
+
440
+ rd_assert((rktp->rktp_flags & RD_KAFKA_TOPPAR_F_ASSIGNED));
441
+ rktp->rktp_flags &= ~RD_KAFKA_TOPPAR_F_ASSIGNED;
442
+
443
+ rd_kafka_toppar_unlock(rktp);
444
+
445
+ rd_kafka_dbg(rk, CGRP, "REMOVE",
446
+ "Removing %s [%" PRId32
447
+ "] from assignment "
448
+ "(started=%s, pending=%s, queried=%s, "
449
+ "stored offset=%s)",
450
+ rktpar->topic, rktpar->partition,
451
+ RD_STR_ToF(rktp->rktp_started),
452
+ RD_STR_ToF(was_pending), RD_STR_ToF(was_queried),
453
+ rd_kafka_offset2str(rktpar->offset));
454
+ }
455
+
456
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "REMOVE",
457
+ "Served %d removed partition(s), "
458
+ "with %d offset(s) to commit",
459
+ rk->rk_consumer.assignment.removed->cnt, valid_offsets);
460
+
461
+ /* If enable.auto.commit=true:
462
+ * Commit final offsets to broker for the removed partitions,
463
+ * unless this is a consumer destruction with a close() call. */
464
+ if (valid_offsets > 0 &&
465
+ rk->rk_conf.offset_store_method == RD_KAFKA_OFFSET_METHOD_BROKER &&
466
+ rk->rk_cgrp && rk->rk_conf.enable_auto_commit &&
467
+ !rd_kafka_destroy_flags_no_consumer_close(rk))
468
+ rd_kafka_cgrp_assigned_offsets_commit(
469
+ rk->rk_cgrp, rk->rk_consumer.assignment.removed,
470
+ rd_false /* use offsets from .removed */,
471
+ "unassigned partitions");
472
+
473
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.removed);
474
+
475
+ return rk->rk_consumer.assignment.wait_stop_cnt +
476
+ rk->rk_consumer.wait_commit_cnt;
477
+ }
478
+
479
+ static void rd_kafka_share_assignment_serve_pending(rd_kafka_t *rk) {
480
+ int i;
481
+
482
+ for (i = rk->rk_consumer.assignment.pending->cnt - 1; i >= 0; i--) {
483
+ rd_kafka_topic_partition_t *rktpar =
484
+ &rk->rk_consumer.assignment.pending->elems[i];
485
+ rd_kafka_toppar_t *rktp =
486
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
487
+
488
+ rd_kafka_dbg(rk, CGRP, "SRVPEND",
489
+ "Adding share partition %s [%" PRId32
490
+ "] to assignment",
491
+ rktpar->topic, rktpar->partition);
492
+
493
+ rktp->rktp_cgrp = rk->rk_cgrp;
494
+
495
+ rd_kafka_cgrp_partition_add(rktp->rktp_cgrp, rktp);
496
+ rd_kafka_topic_partition_list_del_by_idx(
497
+ rk->rk_consumer.assignment.pending, i);
498
+ }
499
+ }
500
+
501
+
502
+ /**
503
+ * @brief Serve all partitions in the pending list.
504
+ *
505
+ * This either (asynchronously) queries the partition's committed offset, or
506
+ * if the start offset is known, starts the partition fetcher.
507
+ *
508
+ * @returns >0 if there are pending operations in progress for the current
509
+ * assignment, else 0.
510
+ */
511
+ static int rd_kafka_assignment_serve_pending(rd_kafka_t *rk) {
512
+ rd_kafka_topic_partition_list_t *partitions_to_query = NULL;
513
+ /* We can query committed offsets only if all of the following are true:
514
+ * - We have a group coordinator.
515
+ * - There are no outstanding commits (since we might need to
516
+ * read back those commits as our starting position).
517
+ * - There are no outstanding queries already (since we want to
518
+ * avoid using a earlier queries response for a partition that
519
+ * is unassigned and then assigned again).
520
+ */
521
+ rd_kafka_broker_t *coord =
522
+ rk->rk_cgrp ? rd_kafka_cgrp_get_coord(rk->rk_cgrp) : NULL;
523
+ rd_bool_t can_query_offsets =
524
+ coord && rk->rk_consumer.wait_commit_cnt == 0 &&
525
+ rk->rk_consumer.assignment.queried->cnt == 0;
526
+ int i;
527
+
528
+ if (can_query_offsets)
529
+ partitions_to_query = rd_kafka_topic_partition_list_new(
530
+ rk->rk_consumer.assignment.pending->cnt);
531
+
532
+ /* Scan the list backwards so removals are cheap (no array shuffle) */
533
+ for (i = rk->rk_consumer.assignment.pending->cnt - 1; i >= 0; i--) {
534
+ rd_kafka_topic_partition_t *rktpar =
535
+ &rk->rk_consumer.assignment.pending->elems[i];
536
+ /* Borrow ref */
537
+ rd_kafka_toppar_t *rktp =
538
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
539
+
540
+ rd_assert(!rktp->rktp_started);
541
+
542
+ if (!RD_KAFKA_OFFSET_IS_LOGICAL(rktpar->offset) ||
543
+ rktpar->offset == RD_KAFKA_OFFSET_BEGINNING ||
544
+ rktpar->offset == RD_KAFKA_OFFSET_END ||
545
+ rktpar->offset == RD_KAFKA_OFFSET_INVALID ||
546
+ rktpar->offset <= RD_KAFKA_OFFSET_TAIL_BASE) {
547
+ /* The partition fetcher can handle absolute
548
+ * as well as beginning/end/tail start offsets, so we're
549
+ * ready to start the fetcher now.
550
+ * The INVALID offset means there was no committed
551
+ * offset and the partition fetcher will employ
552
+ * auto.offset.reset.
553
+ *
554
+ * Start fetcher for partition and forward partition's
555
+ * fetchq to consumer group's queue. */
556
+
557
+ rd_kafka_dbg(rk, CGRP, "SRVPEND",
558
+ "Starting pending assigned partition "
559
+ "%s [%" PRId32 "] at %s",
560
+ rktpar->topic, rktpar->partition,
561
+ rd_kafka_fetch_pos2str(
562
+ rd_kafka_topic_partition_get_fetch_pos(
563
+ rktpar)));
564
+
565
+ /* Reset the (lib) pause flag which may have been set by
566
+ * the cgrp when scheduling the rebalance callback. */
567
+ rd_kafka_toppar_op_pause_resume(
568
+ rktp, rd_false /*resume*/,
569
+ RD_KAFKA_TOPPAR_F_LIB_PAUSE, RD_KAFKA_NO_REPLYQ);
570
+
571
+ /* Start the fetcher */
572
+ rktp->rktp_started = rd_true;
573
+ rk->rk_consumer.assignment.started_cnt++;
574
+
575
+ rd_kafka_toppar_op_fetch_start(
576
+ rktp,
577
+ rd_kafka_topic_partition_get_fetch_pos(rktpar),
578
+ rk->rk_consumer.q, RD_KAFKA_NO_REPLYQ);
579
+
580
+
581
+ } else if (can_query_offsets) {
582
+ /* Else use the last committed offset for partition.
583
+ * We can't rely on any internal cached committed offset
584
+ * so we'll accumulate a list of partitions that need
585
+ * to be queried and then send FetchOffsetsRequest
586
+ * to the group coordinator. */
587
+
588
+ rd_dassert(!rd_kafka_topic_partition_list_find(
589
+ rk->rk_consumer.assignment.queried, rktpar->topic,
590
+ rktpar->partition));
591
+
592
+ rd_kafka_topic_partition_list_add_copy(
593
+ partitions_to_query, rktpar);
594
+
595
+ rd_kafka_topic_partition_list_add_copy(
596
+ rk->rk_consumer.assignment.queried, rktpar);
597
+
598
+ rd_kafka_dbg(rk, CGRP, "SRVPEND",
599
+ "Querying committed offset for pending "
600
+ "assigned partition %s [%" PRId32 "]",
601
+ rktpar->topic, rktpar->partition);
602
+
603
+
604
+ } else {
605
+ rd_kafka_dbg(
606
+ rk, CGRP, "SRVPEND",
607
+ "Pending assignment partition "
608
+ "%s [%" PRId32
609
+ "] can't fetch committed "
610
+ "offset yet "
611
+ "(cgrp state %s, awaiting %d commits, "
612
+ "%d partition(s) already being queried)",
613
+ rktpar->topic, rktpar->partition,
614
+ rk->rk_cgrp
615
+ ? rd_kafka_cgrp_state_names[rk->rk_cgrp
616
+ ->rkcg_state]
617
+ : "n/a",
618
+ rk->rk_consumer.wait_commit_cnt,
619
+ rk->rk_consumer.assignment.queried->cnt);
620
+
621
+ continue; /* Keep rktpar on pending list */
622
+ }
623
+
624
+ /* Remove rktpar from the pending list */
625
+ rd_kafka_topic_partition_list_del_by_idx(
626
+ rk->rk_consumer.assignment.pending, i);
627
+ }
628
+
629
+
630
+ if (!can_query_offsets) {
631
+ if (coord)
632
+ rd_kafka_broker_destroy(coord);
633
+ return rk->rk_consumer.assignment.pending->cnt +
634
+ rk->rk_consumer.assignment.queried->cnt;
635
+ }
636
+
637
+
638
+ if (partitions_to_query->cnt > 0) {
639
+ int64_t *req_assignment_version = rd_malloc(sizeof(int64_t));
640
+ *req_assignment_version = rk->rk_consumer.assignment.version;
641
+
642
+ rd_kafka_dbg(rk, CGRP, "OFFSETFETCH",
643
+ "Fetching committed offsets for "
644
+ "%d pending partition(s) in assignment",
645
+ partitions_to_query->cnt);
646
+
647
+ rd_kafka_OffsetFetchRequest(
648
+ coord, rk->rk_group_id->str, partitions_to_query, rd_false,
649
+ -1, NULL,
650
+ rk->rk_conf.isolation_level ==
651
+ RD_KAFKA_READ_COMMITTED /*require_stable_offsets*/,
652
+ 0, /* Timeout */
653
+ RD_KAFKA_REPLYQ(rk->rk_ops, 0),
654
+ rd_kafka_assignment_handle_OffsetFetch,
655
+ /* Must be freed by handler */
656
+ (void *)req_assignment_version);
657
+ }
658
+
659
+ if (coord)
660
+ rd_kafka_broker_destroy(coord);
661
+
662
+ rd_kafka_topic_partition_list_destroy(partitions_to_query);
663
+
664
+ return rk->rk_consumer.assignment.pending->cnt +
665
+ rk->rk_consumer.assignment.queried->cnt;
666
+ }
667
+
668
+ /**
669
+ * @brief Serve updates to the share assignment.
670
+ *
671
+ * Call on:
672
+ * - assignment changes
673
+ */
674
+ void rd_kafka_share_assignment_serve(rd_kafka_t *rk) {
675
+
676
+ rd_kafka_assignment_dump(rk);
677
+
678
+ /* Serve any partitions that should be removed */
679
+ if (rk->rk_consumer.assignment.removed->cnt > 0)
680
+ rd_kafka_share_assignment_serve_removals(rk);
681
+
682
+ /* Serve pending partitions */
683
+ if (rk->rk_consumer.assignment.pending->cnt > 0)
684
+ rd_kafka_share_assignment_serve_pending(rk);
685
+
686
+ /* Share-consumer serve always completes synchronously: removals
687
+ * don't wait for a fetcher stop (no fetcher), pending doesn't wait
688
+ * for an OffsetFetch (no offset commits). Signal done immediately. */
689
+ rd_kafka_cgrp_assignment_done(rk->rk_cgrp);
690
+
691
+ rd_kafka_dbg(rk, CGRP, "ASSIGNMENT",
692
+ "Share assignment served: %d partition(s) assigned",
693
+ rk->rk_consumer.assignment.all->cnt);
694
+ }
695
+
696
+ /**
697
+ * @brief Serve updates to the assignment.
698
+ *
699
+ * Call on:
700
+ * - assignment changes
701
+ * - wait_commit_cnt reaches 0
702
+ * - partition fetcher is stopped
703
+ */
704
+ void rd_kafka_assignment_serve(rd_kafka_t *rk) {
705
+ if (RD_KAFKA_IS_SHARE_CONSUMER(rk)) {
706
+ rd_kafka_share_assignment_serve(rk);
707
+ return;
708
+ }
709
+ int inp_removals = 0;
710
+ int inp_pending = 0;
711
+
712
+ rd_kafka_assignment_dump(rk);
713
+
714
+ /* Serve any partitions that should be removed */
715
+ if (rk->rk_consumer.assignment.removed->cnt > 0)
716
+ inp_removals = rd_kafka_assignment_serve_removals(rk);
717
+
718
+ /* Serve any partitions in the pending list that need further action,
719
+ * unless we're waiting for a previous assignment change (an unassign
720
+ * in some form) to propagate, or outstanding offset commits
721
+ * to finish (since we might need the committed offsets as start
722
+ * offsets). */
723
+ if (rk->rk_consumer.assignment.wait_stop_cnt == 0 &&
724
+ rk->rk_consumer.wait_commit_cnt == 0 && inp_removals == 0 &&
725
+ rk->rk_consumer.assignment.pending->cnt > 0)
726
+ inp_pending = rd_kafka_assignment_serve_pending(rk);
727
+
728
+ if (inp_removals + inp_pending +
729
+ rk->rk_consumer.assignment.queried->cnt +
730
+ rk->rk_consumer.assignment.wait_stop_cnt +
731
+ rk->rk_consumer.wait_commit_cnt ==
732
+ 0) {
733
+ /* No assignment operations in progress,
734
+ * signal assignment done back to cgrp to let it
735
+ * transition to its next state if necessary.
736
+ * We may emit this signalling more than necessary and it is
737
+ * up to the cgrp to only take action if needed, based on its
738
+ * state. */
739
+ rd_kafka_cgrp_assignment_done(rk->rk_cgrp);
740
+ } else {
741
+ rd_kafka_dbg(rk, CGRP, "ASSIGNMENT",
742
+ "Current assignment of %d partition(s) "
743
+ "with %d pending adds, %d offset queries, "
744
+ "%d partitions awaiting stop and "
745
+ "%d offset commits in progress",
746
+ rk->rk_consumer.assignment.all->cnt, inp_pending,
747
+ rk->rk_consumer.assignment.queried->cnt,
748
+ rk->rk_consumer.assignment.wait_stop_cnt,
749
+ rk->rk_consumer.wait_commit_cnt);
750
+ }
751
+ }
752
+
753
+
754
+ /**
755
+ * @returns true if the current or previous assignment has operations in
756
+ * progress, such as waiting for partition fetchers to stop.
757
+ */
758
+ rd_bool_t rd_kafka_assignment_in_progress(rd_kafka_t *rk) {
759
+ return rk->rk_consumer.wait_commit_cnt > 0 ||
760
+ rk->rk_consumer.assignment.wait_stop_cnt > 0 ||
761
+ rk->rk_consumer.assignment.pending->cnt > 0 ||
762
+ rk->rk_consumer.assignment.queried->cnt > 0 ||
763
+ rk->rk_consumer.assignment.removed->cnt > 0;
764
+ }
765
+
766
+
767
+ /**
768
+ * @brief Share-consumer variant of rd_kafka_assignment_clear().
769
+ */
770
+ static int rd_kafka_share_assignment_clear(rd_kafka_t *rk) {
771
+ int cnt = rk->rk_consumer.assignment.all->cnt;
772
+
773
+ if (cnt == 0) {
774
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "CLEARASSIGN",
775
+ "No current share assignment to clear");
776
+ return 0;
777
+ }
778
+
779
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "CLEARASSIGN",
780
+ "Clearing current share assignment of %d partition(s)",
781
+ cnt);
782
+
783
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.pending);
784
+
785
+ rd_kafka_topic_partition_list_add_list(
786
+ rk->rk_consumer.assignment.removed, rk->rk_consumer.assignment.all);
787
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.all);
788
+
789
+ return cnt;
790
+ }
791
+
792
+
793
+ /**
794
+ * @brief Clear the current assignment.
795
+ *
796
+ * @remark Make sure to call rd_kafka_assignment_serve() after successful
797
+ * return from this function.
798
+ *
799
+ * @returns the number of partitions removed.
800
+ */
801
+ int rd_kafka_assignment_clear(rd_kafka_t *rk) {
802
+ int cnt;
803
+
804
+ if (RD_KAFKA_IS_SHARE_CONSUMER(rk))
805
+ return rd_kafka_share_assignment_clear(rk);
806
+
807
+ cnt = rk->rk_consumer.assignment.all->cnt;
808
+
809
+ if (cnt == 0) {
810
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "CLEARASSIGN",
811
+ "No current assignment to clear");
812
+ return 0;
813
+ }
814
+
815
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "CLEARASSIGN",
816
+ "Clearing current assignment of %d partition(s)",
817
+ rk->rk_consumer.assignment.all->cnt);
818
+
819
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.pending);
820
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.queried);
821
+
822
+ rd_kafka_topic_partition_list_add_list(
823
+ rk->rk_consumer.assignment.removed, rk->rk_consumer.assignment.all);
824
+ rd_kafka_topic_partition_list_clear(rk->rk_consumer.assignment.all);
825
+
826
+ rk->rk_consumer.assignment.version++;
827
+
828
+ return cnt;
829
+ }
830
+
831
+
832
+ /**
833
+ * @brief Share-consumer variant of rd_kafka_assignment_add().
834
+ */
835
+ static rd_kafka_error_t *
836
+ rd_kafka_share_assignment_add(rd_kafka_t *rk,
837
+ rd_kafka_topic_partition_list_t *partitions) {
838
+ rd_bool_t was_empty = rk->rk_consumer.assignment.all->cnt == 0;
839
+ int i;
840
+
841
+ /* Reject duplicates inside the input list and overlap with the
842
+ * current assignment. Offset validation is omitted — broker owns
843
+ * the start position for share consumers. */
844
+ rd_kafka_topic_partition_list_sort(partitions, NULL, NULL);
845
+
846
+ for (i = 0; i < partitions->cnt; i++) {
847
+ rd_kafka_topic_partition_t *rktpar = &partitions->elems[i];
848
+ const rd_kafka_topic_partition_t *prev =
849
+ i > 0 ? &partitions->elems[i - 1] : NULL;
850
+
851
+ if (prev && !rd_kafka_topic_partition_cmp(rktpar, prev))
852
+ return rd_kafka_error_new(
853
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
854
+ "Duplicate %s [%" PRId32 "] in input list",
855
+ rktpar->topic, rktpar->partition);
856
+
857
+ if (rd_kafka_topic_partition_list_find(
858
+ rk->rk_consumer.assignment.all, rktpar->topic,
859
+ rktpar->partition))
860
+ return rd_kafka_error_new(RD_KAFKA_RESP_ERR__CONFLICT,
861
+ "%s [%" PRId32
862
+ "] is already part of the "
863
+ "current assignment",
864
+ rktpar->topic,
865
+ rktpar->partition);
866
+
867
+ /* Materialize the toppar (creating topic + toppar if
868
+ * missing) and cache it in rktpar->_private so the next
869
+ * loop can reuse the lookup. */
870
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
871
+ }
872
+
873
+ rd_kafka_topic_partition_list_add_list(rk->rk_consumer.assignment.all,
874
+ partitions);
875
+ if (!was_empty)
876
+ rd_kafka_topic_partition_list_sort(
877
+ rk->rk_consumer.assignment.all, NULL, NULL);
878
+
879
+ rd_kafka_topic_partition_list_add_list(
880
+ rk->rk_consumer.assignment.pending, partitions);
881
+
882
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "ASSIGNMENT",
883
+ "Added %d partition(s) to share assignment which "
884
+ "now consists of %d partition(s), %d in pending state",
885
+ partitions->cnt, rk->rk_consumer.assignment.all->cnt,
886
+ rk->rk_consumer.assignment.pending->cnt);
887
+
888
+ return NULL;
889
+ }
890
+
891
+
892
+ /**
893
+ * @brief Adds \p partitions to the current assignment.
894
+ *
895
+ * Will return error if trying to add a partition that is already in the
896
+ * assignment.
897
+ *
898
+ * @remark Make sure to call rd_kafka_assignment_serve() after successful
899
+ * return from this function.
900
+ */
901
+ rd_kafka_error_t *
902
+ rd_kafka_assignment_add(rd_kafka_t *rk,
903
+ rd_kafka_topic_partition_list_t *partitions) {
904
+ rd_bool_t was_empty = rk->rk_consumer.assignment.all->cnt == 0;
905
+ int i;
906
+
907
+ if (RD_KAFKA_IS_SHARE_CONSUMER(rk))
908
+ return rd_kafka_share_assignment_add(rk, partitions);
909
+
910
+ /* Make sure there are no duplicates, invalid partitions, or
911
+ * invalid offsets in the input partitions. */
912
+ rd_kafka_topic_partition_list_sort(partitions, NULL, NULL);
913
+
914
+ for (i = 0; i < partitions->cnt; i++) {
915
+ rd_kafka_topic_partition_t *rktpar = &partitions->elems[i];
916
+ const rd_kafka_topic_partition_t *prev =
917
+ i > 0 ? &partitions->elems[i - 1] : NULL;
918
+
919
+ if (RD_KAFKA_OFFSET_IS_LOGICAL(rktpar->offset) &&
920
+ rktpar->offset != RD_KAFKA_OFFSET_BEGINNING &&
921
+ rktpar->offset != RD_KAFKA_OFFSET_END &&
922
+ rktpar->offset != RD_KAFKA_OFFSET_STORED &&
923
+ rktpar->offset != RD_KAFKA_OFFSET_INVALID &&
924
+ rktpar->offset > RD_KAFKA_OFFSET_TAIL_BASE)
925
+ return rd_kafka_error_new(
926
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
927
+ "%s [%" PRId32
928
+ "] has invalid start offset %" PRId64,
929
+ rktpar->topic, rktpar->partition, rktpar->offset);
930
+
931
+ if (prev && !rd_kafka_topic_partition_cmp(rktpar, prev))
932
+ return rd_kafka_error_new(
933
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
934
+ "Duplicate %s [%" PRId32 "] in input list",
935
+ rktpar->topic, rktpar->partition);
936
+
937
+ if (rd_kafka_topic_partition_list_find(
938
+ rk->rk_consumer.assignment.all, rktpar->topic,
939
+ rktpar->partition))
940
+ return rd_kafka_error_new(RD_KAFKA_RESP_ERR__CONFLICT,
941
+ "%s [%" PRId32
942
+ "] is already part of the "
943
+ "current assignment",
944
+ rktpar->topic,
945
+ rktpar->partition);
946
+
947
+ /* Translate RD_KAFKA_OFFSET_INVALID to RD_KAFKA_OFFSET_STORED,
948
+ * i.e., read from committed offset, since we use INVALID
949
+ * internally to differentiate between querying for
950
+ * committed offset (STORED) and no committed offset (INVALID).
951
+ */
952
+ if (rktpar->offset == RD_KAFKA_OFFSET_INVALID)
953
+ rktpar->offset = RD_KAFKA_OFFSET_STORED;
954
+
955
+ /* Get toppar object for each partition.
956
+ * This is to make sure the rktp stays alive while unassigning
957
+ * any previous assignment in the call to
958
+ * assignment_clear() below. */
959
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
960
+ }
961
+
962
+ /* Mark all partition objects as assigned and reset the stored
963
+ * offsets back to invalid in case it was explicitly stored during
964
+ * the time the partition was not assigned. */
965
+ for (i = 0; i < partitions->cnt; i++) {
966
+ rd_kafka_topic_partition_t *rktpar = &partitions->elems[i];
967
+ rd_kafka_toppar_t *rktp =
968
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
969
+
970
+ rd_kafka_toppar_lock(rktp);
971
+
972
+ rd_assert(!(rktp->rktp_flags & RD_KAFKA_TOPPAR_F_ASSIGNED));
973
+ rktp->rktp_flags |= RD_KAFKA_TOPPAR_F_ASSIGNED;
974
+
975
+ /* Reset the stored offset to INVALID to avoid the race
976
+ * condition described in rdkafka_offset.h */
977
+ rd_kafka_offset_store0(
978
+ rktp, RD_KAFKA_FETCH_POS(RD_KAFKA_OFFSET_INVALID, -1), NULL,
979
+ 0, rd_true /* force */, RD_DONT_LOCK);
980
+
981
+ rd_kafka_toppar_unlock(rktp);
982
+ }
983
+
984
+
985
+ /* Add the new list of partitions to the current assignment.
986
+ * Only need to sort the final assignment if it was non-empty
987
+ * to begin with since \p partitions is sorted above. */
988
+ rd_kafka_topic_partition_list_add_list(rk->rk_consumer.assignment.all,
989
+ partitions);
990
+ if (!was_empty)
991
+ rd_kafka_topic_partition_list_sort(
992
+ rk->rk_consumer.assignment.all, NULL, NULL);
993
+
994
+ /* And add to .pending for serve_pending() to handle. */
995
+ rd_kafka_topic_partition_list_add_list(
996
+ rk->rk_consumer.assignment.pending, partitions);
997
+
998
+
999
+ rd_kafka_dbg(rk, CONSUMER | RD_KAFKA_DBG_CGRP, "ASSIGNMENT",
1000
+ "Added %d partition(s) to assignment which "
1001
+ "now consists of %d partition(s) where of %d are in "
1002
+ "pending state and %d are being queried",
1003
+ partitions->cnt, rk->rk_consumer.assignment.all->cnt,
1004
+ rk->rk_consumer.assignment.pending->cnt,
1005
+ rk->rk_consumer.assignment.queried->cnt);
1006
+
1007
+ rk->rk_consumer.assignment.version++;
1008
+
1009
+ return NULL;
1010
+ }
1011
+
1012
+
1013
+ /**
1014
+ * @brief Share-consumer variant of rd_kafka_assignment_subtract().
1015
+ */
1016
+ static rd_kafka_error_t *rd_kafka_share_assignment_subtract(
1017
+ rd_kafka_t *rk,
1018
+ rd_kafka_topic_partition_list_t *partitions) {
1019
+ int i;
1020
+ int assignment_pre_cnt;
1021
+
1022
+ if (rk->rk_consumer.assignment.all->cnt == 0 && partitions->cnt > 0)
1023
+ return rd_kafka_error_new(
1024
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
1025
+ "Can't subtract from empty assignment");
1026
+
1027
+ rd_kafka_topic_partition_list_sort(partitions, NULL, NULL);
1028
+
1029
+ for (i = 0; i < partitions->cnt; i++) {
1030
+ rd_kafka_topic_partition_t *rktpar = &partitions->elems[i];
1031
+
1032
+ if (!rd_kafka_topic_partition_list_find(
1033
+ rk->rk_consumer.assignment.all, rktpar->topic,
1034
+ rktpar->partition))
1035
+ return rd_kafka_error_new(
1036
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
1037
+ "%s [%" PRId32
1038
+ "] can't be unassigned since "
1039
+ "it is not in the current assignment",
1040
+ rktpar->topic, rktpar->partition);
1041
+
1042
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
1043
+ }
1044
+
1045
+ assignment_pre_cnt = rk->rk_consumer.assignment.all->cnt;
1046
+
1047
+ for (i = partitions->cnt - 1; i >= 0; i--) {
1048
+ const rd_kafka_topic_partition_t *rktpar =
1049
+ &partitions->elems[i];
1050
+
1051
+ if (!rd_kafka_topic_partition_list_del(
1052
+ rk->rk_consumer.assignment.all, rktpar->topic,
1053
+ rktpar->partition))
1054
+ RD_BUG("Removed partition %s [%" PRId32
1055
+ "] not found in assignment.all",
1056
+ rktpar->topic, rktpar->partition);
1057
+
1058
+ rd_kafka_topic_partition_list_del(
1059
+ rk->rk_consumer.assignment.pending, rktpar->topic,
1060
+ rktpar->partition);
1061
+
1062
+ rd_kafka_topic_partition_list_add_copy(
1063
+ rk->rk_consumer.assignment.removed, rktpar);
1064
+ }
1065
+
1066
+ rd_kafka_dbg(rk, CGRP, "REMOVEASSIGN",
1067
+ "Removed %d partition(s) from share assignment of "
1068
+ "%d partition(s)",
1069
+ partitions->cnt, assignment_pre_cnt);
1070
+
1071
+ if (rk->rk_consumer.assignment.all->cnt == 0)
1072
+ rd_assert(rk->rk_consumer.assignment.pending->cnt == 0);
1073
+
1074
+ return NULL;
1075
+ }
1076
+
1077
+
1078
+ /**
1079
+ * @brief Remove \p partitions from the current assignment.
1080
+ *
1081
+ * Will return error if trying to remove a partition that is not in the
1082
+ * assignment.
1083
+ *
1084
+ * @remark Make sure to call rd_kafka_assignment_serve() after successful
1085
+ * return from this function.
1086
+ */
1087
+ rd_kafka_error_t *
1088
+ rd_kafka_assignment_subtract(rd_kafka_t *rk,
1089
+ rd_kafka_topic_partition_list_t *partitions) {
1090
+ int i;
1091
+ int matched_queried_partitions = 0;
1092
+ int assignment_pre_cnt;
1093
+
1094
+ if (RD_KAFKA_IS_SHARE_CONSUMER(rk))
1095
+ return rd_kafka_share_assignment_subtract(rk, partitions);
1096
+
1097
+ if (rk->rk_consumer.assignment.all->cnt == 0 && partitions->cnt > 0)
1098
+ return rd_kafka_error_new(
1099
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
1100
+ "Can't subtract from empty assignment");
1101
+
1102
+ /* Verify that all partitions in \p partitions are in the assignment
1103
+ * before starting to modify the assignment. */
1104
+ rd_kafka_topic_partition_list_sort(partitions, NULL, NULL);
1105
+
1106
+ for (i = 0; i < partitions->cnt; i++) {
1107
+ rd_kafka_topic_partition_t *rktpar = &partitions->elems[i];
1108
+
1109
+ if (!rd_kafka_topic_partition_list_find(
1110
+ rk->rk_consumer.assignment.all, rktpar->topic,
1111
+ rktpar->partition))
1112
+ return rd_kafka_error_new(
1113
+ RD_KAFKA_RESP_ERR__INVALID_ARG,
1114
+ "%s [%" PRId32
1115
+ "] can't be unassigned since "
1116
+ "it is not in the current assignment",
1117
+ rktpar->topic, rktpar->partition);
1118
+
1119
+ rd_kafka_topic_partition_ensure_toppar(rk, rktpar, rd_true);
1120
+ }
1121
+
1122
+
1123
+ assignment_pre_cnt = rk->rk_consumer.assignment.all->cnt;
1124
+
1125
+ /* Remove partitions in reverse order to avoid excessive
1126
+ * array shuffling of .all.
1127
+ * Add the removed partitions to .pending for serve() to handle. */
1128
+ for (i = partitions->cnt - 1; i >= 0; i--) {
1129
+ const rd_kafka_topic_partition_t *rktpar =
1130
+ &partitions->elems[i];
1131
+
1132
+ if (!rd_kafka_topic_partition_list_del(
1133
+ rk->rk_consumer.assignment.all, rktpar->topic,
1134
+ rktpar->partition))
1135
+ RD_BUG("Removed partition %s [%" PRId32
1136
+ "] not found "
1137
+ "in assignment.all",
1138
+ rktpar->topic, rktpar->partition);
1139
+
1140
+ if (rd_kafka_topic_partition_list_del(
1141
+ rk->rk_consumer.assignment.queried, rktpar->topic,
1142
+ rktpar->partition))
1143
+ matched_queried_partitions++;
1144
+ else
1145
+ rd_kafka_topic_partition_list_del(
1146
+ rk->rk_consumer.assignment.pending, rktpar->topic,
1147
+ rktpar->partition);
1148
+
1149
+ /* Add to .removed list which will be served by
1150
+ * serve_removals(). */
1151
+ rd_kafka_topic_partition_list_add_copy(
1152
+ rk->rk_consumer.assignment.removed, rktpar);
1153
+ }
1154
+
1155
+ rd_kafka_dbg(rk, CGRP, "REMOVEASSIGN",
1156
+ "Removed %d partition(s) "
1157
+ "(%d with outstanding offset queries) from assignment "
1158
+ "of %d partition(s)",
1159
+ partitions->cnt, matched_queried_partitions,
1160
+ assignment_pre_cnt);
1161
+
1162
+ if (rk->rk_consumer.assignment.all->cnt == 0) {
1163
+ /* Some safe checking */
1164
+ rd_assert(rk->rk_consumer.assignment.pending->cnt == 0);
1165
+ rd_assert(rk->rk_consumer.assignment.queried->cnt == 0);
1166
+ }
1167
+
1168
+ rk->rk_consumer.assignment.version++;
1169
+
1170
+ return NULL;
1171
+ }
1172
+
1173
+
1174
+ /**
1175
+ * @brief Call when partition fetcher has stopped.
1176
+ */
1177
+ void rd_kafka_assignment_partition_stopped(rd_kafka_t *rk,
1178
+ rd_kafka_toppar_t *rktp) {
1179
+ rd_assert(rk->rk_consumer.assignment.wait_stop_cnt > 0);
1180
+ rk->rk_consumer.assignment.wait_stop_cnt--;
1181
+
1182
+ rd_assert(rktp->rktp_started);
1183
+ rktp->rktp_started = rd_false;
1184
+
1185
+ rd_assert(rk->rk_consumer.assignment.started_cnt > 0);
1186
+ rk->rk_consumer.assignment.started_cnt--;
1187
+
1188
+ /* If this was the last partition we awaited stop for, serve the
1189
+ * assignment to transition any existing assignment to the next state */
1190
+ if (rk->rk_consumer.assignment.wait_stop_cnt == 0) {
1191
+ rd_kafka_dbg(rk, CGRP, "STOPSERVE",
1192
+ "All partitions awaiting stop are now "
1193
+ "stopped: serving assignment");
1194
+ rd_kafka_assignment_serve(rk);
1195
+ }
1196
+ }
1197
+
1198
+
1199
+ /**
1200
+ * @brief Pause fetching of the currently assigned partitions.
1201
+ *
1202
+ * Partitions will be resumed by calling rd_kafka_assignment_resume() or
1203
+ * from either serve_removals() or serve_pending() above.
1204
+ */
1205
+ void rd_kafka_assignment_pause(rd_kafka_t *rk, const char *reason) {
1206
+
1207
+ /**
1208
+ * TODO KIP-932: Check how can remove the invocation
1209
+ * of this function altogether for share consumers.
1210
+ */
1211
+ if (RD_KAFKA_IS_SHARE_CONSUMER(rk)) {
1212
+ return;
1213
+ }
1214
+
1215
+ if (rk->rk_consumer.assignment.all->cnt == 0)
1216
+ return;
1217
+
1218
+ rd_kafka_dbg(rk, CGRP, "PAUSE",
1219
+ "Pausing fetchers for %d assigned partition(s): %s",
1220
+ rk->rk_consumer.assignment.all->cnt, reason);
1221
+
1222
+ rd_kafka_toppars_pause_resume(rk, rd_true /*pause*/, RD_ASYNC,
1223
+ RD_KAFKA_TOPPAR_F_LIB_PAUSE,
1224
+ rk->rk_consumer.assignment.all);
1225
+ }
1226
+
1227
+ /**
1228
+ * @brief Resume fetching of the currently assigned partitions which have
1229
+ * previously been paused by rd_kafka_assignment_pause().
1230
+ */
1231
+ void rd_kafka_assignment_resume(rd_kafka_t *rk, const char *reason) {
1232
+
1233
+ /**
1234
+ * TODO KIP-932: Check how can remove the invocation
1235
+ * of this function altogether for share consumers.
1236
+ */
1237
+ if (RD_KAFKA_IS_SHARE_CONSUMER(rk)) {
1238
+ return;
1239
+ }
1240
+
1241
+ if (rk->rk_consumer.assignment.all->cnt == 0)
1242
+ return;
1243
+
1244
+ rd_kafka_dbg(rk, CGRP, "PAUSE",
1245
+ "Resuming fetchers for %d assigned partition(s): %s",
1246
+ rk->rk_consumer.assignment.all->cnt, reason);
1247
+
1248
+ rd_kafka_toppars_pause_resume(rk, rd_false /*resume*/, RD_ASYNC,
1249
+ RD_KAFKA_TOPPAR_F_LIB_PAUSE,
1250
+ rk->rk_consumer.assignment.all);
1251
+ }
1252
+
1253
+
1254
+
1255
+ /**
1256
+ * @brief Destroy assignment state (but not \p assignment itself)
1257
+ */
1258
+ void rd_kafka_assignment_destroy(rd_kafka_t *rk) {
1259
+ if (!rk->rk_consumer.assignment.all)
1260
+ return; /* rd_kafka_assignment_init() not called */
1261
+ rd_kafka_topic_partition_list_destroy(rk->rk_consumer.assignment.all);
1262
+ rd_kafka_topic_partition_list_destroy(
1263
+ rk->rk_consumer.assignment.pending);
1264
+ rd_kafka_topic_partition_list_destroy(
1265
+ rk->rk_consumer.assignment.queried);
1266
+ rd_kafka_topic_partition_list_destroy(
1267
+ rk->rk_consumer.assignment.removed);
1268
+ }
1269
+
1270
+
1271
+ /**
1272
+ * @brief Initialize the assignment struct.
1273
+ */
1274
+ void rd_kafka_assignment_init(rd_kafka_t *rk) {
1275
+ rk->rk_consumer.assignment.all = rd_kafka_topic_partition_list_new(100);
1276
+ rk->rk_consumer.assignment.pending =
1277
+ rd_kafka_topic_partition_list_new(100);
1278
+ rk->rk_consumer.assignment.queried =
1279
+ rd_kafka_topic_partition_list_new(100);
1280
+ rk->rk_consumer.assignment.removed =
1281
+ rd_kafka_topic_partition_list_new(100);
1282
+ }