@platformatic/rdkafka 4.0.1 → 4.1.0

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 (294) hide show
  1. package/README.md +5 -5
  2. package/bench/seed.sh +0 -0
  3. package/binding.gyp +8 -1
  4. package/ci/prepublish.js +0 -1
  5. package/config.d.ts +126 -10
  6. package/configure +0 -0
  7. package/deps/librdkafka/.semaphore/run-all-tests.yml +77 -0
  8. package/deps/librdkafka/.semaphore/semaphore-integration.yml +250 -0
  9. package/deps/librdkafka/.semaphore/semaphore.yml +67 -44
  10. package/deps/librdkafka/.semaphore/verify-linux-packages.yml +41 -0
  11. package/deps/librdkafka/CHANGELOG.md +471 -1
  12. package/deps/librdkafka/CONFIGURATION.md +29 -9
  13. package/deps/librdkafka/INTRODUCTION.md +909 -601
  14. package/deps/librdkafka/LICENSES.txt +592 -1
  15. package/deps/librdkafka/Makefile +2 -1
  16. package/deps/librdkafka/_mkltmpuuWEwa.c +13 -0
  17. package/deps/librdkafka/configure +0 -0
  18. package/deps/librdkafka/debian/rules +0 -0
  19. package/deps/librdkafka/dev-conf.sh +0 -0
  20. package/deps/librdkafka/examples/consumer.c +18 -8
  21. package/deps/librdkafka/examples/describe_consumer_groups.c +25 -6
  22. package/deps/librdkafka/examples/incremental_alter_configs.c +4 -5
  23. package/deps/librdkafka/examples/kafkatest_verifiable_client.cpp +26 -42
  24. package/deps/librdkafka/examples/openssl_engine_example.cpp +3 -4
  25. package/deps/librdkafka/examples/producer.cpp +2 -2
  26. package/deps/librdkafka/examples/user_scram.c +4 -5
  27. package/deps/librdkafka/examples/win_ssl_cert_store.cpp +4 -3
  28. package/deps/librdkafka/lds-gen.py +0 -0
  29. package/deps/librdkafka/mklove/Makefile.base +0 -0
  30. package/deps/librdkafka/packaging/RELEASE.md +8 -0
  31. package/deps/librdkafka/packaging/alpine/build-alpine.sh +0 -0
  32. package/deps/librdkafka/packaging/cp/README.md +4 -1
  33. package/deps/librdkafka/packaging/cp/check_features.c +12 -4
  34. package/deps/librdkafka/packaging/cp/verify-deb.sh +6 -6
  35. package/deps/librdkafka/packaging/cp/verify-packages.sh +52 -31
  36. package/deps/librdkafka/packaging/cp/verify-rpm.sh +6 -13
  37. package/deps/librdkafka/packaging/debian/rules +0 -0
  38. package/deps/librdkafka/packaging/get_version.py +0 -0
  39. package/deps/librdkafka/packaging/homebrew/brew-update-pr.sh +0 -0
  40. package/deps/librdkafka/packaging/mingw-w64/{travis-before-install.sh → export-variables.sh} +0 -7
  41. package/deps/librdkafka/packaging/mingw-w64/semaphoreci-build.sh +1 -1
  42. package/deps/librdkafka/packaging/nuget/artifact.py +0 -0
  43. package/deps/librdkafka/packaging/nuget/cleanup-s3.py +0 -0
  44. package/deps/librdkafka/packaging/nuget/nuget.sh +0 -0
  45. package/deps/librdkafka/packaging/nuget/packaging.py +0 -0
  46. package/deps/librdkafka/packaging/nuget/push-to-nuget.sh +0 -0
  47. package/deps/librdkafka/packaging/nuget/release.py +0 -0
  48. package/deps/librdkafka/packaging/nuget/requirements.txt +3 -3
  49. package/deps/librdkafka/packaging/rpm/mock-on-docker.sh +0 -0
  50. package/deps/librdkafka/packaging/rpm/tests/run-test.sh +0 -0
  51. package/deps/librdkafka/packaging/rpm/tests/test-on-docker.sh +0 -0
  52. package/deps/librdkafka/packaging/tools/build-configurations-checks.sh +3 -1
  53. package/deps/librdkafka/packaging/tools/build-deb-package.sh +0 -0
  54. package/deps/librdkafka/packaging/tools/build-debian.sh +0 -0
  55. package/deps/librdkafka/packaging/tools/build-manylinux.sh +0 -0
  56. package/deps/librdkafka/packaging/tools/build-release-artifacts.sh +0 -0
  57. package/deps/librdkafka/packaging/tools/distro-build.sh +0 -0
  58. package/deps/librdkafka/packaging/tools/gh-release-checksums.py +0 -0
  59. package/deps/librdkafka/packaging/tools/rdutcoverage.sh +0 -0
  60. package/deps/librdkafka/packaging/tools/run-in-docker.sh +28 -0
  61. package/deps/librdkafka/packaging/tools/run-integration-tests.sh +31 -0
  62. package/deps/librdkafka/packaging/tools/run-style-check.sh +4 -0
  63. package/deps/librdkafka/packaging/tools/style-format.sh +6 -5
  64. package/deps/librdkafka/packaging/tools/update_rpcs_max_versions.py +100 -0
  65. package/deps/librdkafka/service.yml +154 -0
  66. package/deps/librdkafka/src/generate_proto.sh +0 -0
  67. package/deps/librdkafka/src/rd.h +145 -2
  68. package/deps/librdkafka/src/rdaddr.h +6 -7
  69. package/deps/librdkafka/src/rdatomic.h +15 -11
  70. package/deps/librdkafka/src/rdavg.h +3 -2
  71. package/deps/librdkafka/src/rdbase64.c +33 -2
  72. package/deps/librdkafka/src/rdbase64.h +2 -0
  73. package/deps/librdkafka/src/rdendian.h +10 -9
  74. package/deps/librdkafka/src/rdhttp.c +418 -100
  75. package/deps/librdkafka/src/rdhttp.h +23 -5
  76. package/deps/librdkafka/src/rdkafka.c +299 -145
  77. package/deps/librdkafka/src/rdkafka.h +89 -6
  78. package/deps/librdkafka/src/rdkafka_admin.c +482 -105
  79. package/deps/librdkafka/src/rdkafka_admin.h +42 -0
  80. package/deps/librdkafka/src/rdkafka_broker.c +463 -312
  81. package/deps/librdkafka/src/rdkafka_broker.h +68 -10
  82. package/deps/librdkafka/src/rdkafka_buf.c +8 -5
  83. package/deps/librdkafka/src/rdkafka_buf.h +4 -3
  84. package/deps/librdkafka/src/rdkafka_cert.c +25 -1
  85. package/deps/librdkafka/src/rdkafka_cert.h +4 -3
  86. package/deps/librdkafka/src/rdkafka_cgrp.c +468 -143
  87. package/deps/librdkafka/src/rdkafka_cgrp.h +36 -2
  88. package/deps/librdkafka/src/rdkafka_conf.c +526 -102
  89. package/deps/librdkafka/src/rdkafka_conf.h +68 -4
  90. package/deps/librdkafka/src/rdkafka_feature.c +472 -35
  91. package/deps/librdkafka/src/rdkafka_feature.h +2 -0
  92. package/deps/librdkafka/src/rdkafka_fetcher.c +22 -2
  93. package/deps/librdkafka/src/rdkafka_fetcher.h +2 -2
  94. package/deps/librdkafka/src/rdkafka_int.h +84 -46
  95. package/deps/librdkafka/src/rdkafka_metadata.c +221 -136
  96. package/deps/librdkafka/src/rdkafka_metadata.h +15 -11
  97. package/deps/librdkafka/src/rdkafka_metadata_cache.c +279 -73
  98. package/deps/librdkafka/src/rdkafka_mock.c +795 -19
  99. package/deps/librdkafka/src/rdkafka_mock.h +119 -0
  100. package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1298 -132
  101. package/deps/librdkafka/src/rdkafka_mock_handlers.c +345 -49
  102. package/deps/librdkafka/src/rdkafka_mock_int.h +180 -61
  103. package/deps/librdkafka/src/rdkafka_msg.c +35 -19
  104. package/deps/librdkafka/src/rdkafka_msg.h +3 -3
  105. package/deps/librdkafka/src/rdkafka_msgset_writer.c +14 -10
  106. package/deps/librdkafka/src/rdkafka_offset.c +33 -5
  107. package/deps/librdkafka/src/rdkafka_op.c +1 -1
  108. package/deps/librdkafka/src/rdkafka_op.h +45 -21
  109. package/deps/librdkafka/src/rdkafka_partition.c +118 -23
  110. package/deps/librdkafka/src/rdkafka_partition.h +16 -7
  111. package/deps/librdkafka/src/rdkafka_proto.h +4 -1
  112. package/deps/librdkafka/src/rdkafka_protocol.h +1 -0
  113. package/deps/librdkafka/src/rdkafka_queue.c +125 -48
  114. package/deps/librdkafka/src/rdkafka_queue.h +19 -0
  115. package/deps/librdkafka/src/rdkafka_range_assignor.c +1 -1
  116. package/deps/librdkafka/src/rdkafka_request.c +336 -64
  117. package/deps/librdkafka/src/rdkafka_request.h +24 -1
  118. package/deps/librdkafka/src/rdkafka_sasl.c +5 -3
  119. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +14 -10
  120. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1166 -89
  121. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +13 -3
  122. package/deps/librdkafka/src/rdkafka_sasl_plain.c +3 -3
  123. package/deps/librdkafka/src/rdkafka_sasl_scram.c +4 -3
  124. package/deps/librdkafka/src/rdkafka_ssl.c +306 -81
  125. package/deps/librdkafka/src/rdkafka_ssl.h +22 -0
  126. package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4 -0
  127. package/deps/librdkafka/src/rdkafka_telemetry.c +80 -23
  128. package/deps/librdkafka/src/rdkafka_telemetry_encode.c +5 -1
  129. package/deps/librdkafka/src/rdkafka_telemetry_encode.h +20 -20
  130. package/deps/librdkafka/src/rdkafka_topic.c +220 -137
  131. package/deps/librdkafka/src/rdkafka_topic.h +14 -8
  132. package/deps/librdkafka/src/rdkafka_transport.c +59 -47
  133. package/deps/librdkafka/src/rdkafka_transport.h +5 -0
  134. package/deps/librdkafka/src/rdkafka_txnmgr.c +6 -1
  135. package/deps/librdkafka/src/rdmap.c +6 -1
  136. package/deps/librdkafka/src/rdrand.c +11 -1
  137. package/deps/librdkafka/src/rdtime.h +48 -17
  138. package/deps/librdkafka/src/rdunittest.c +42 -25
  139. package/deps/librdkafka/src/rdunittest.h +2 -0
  140. package/deps/librdkafka/src/rdwin32.h +1 -1
  141. package/deps/librdkafka/src/regexp.c +47 -42
  142. package/deps/librdkafka/src/tinycthread_extra.c +45 -21
  143. package/deps/librdkafka/src/tinycthread_extra.h +7 -3
  144. package/deps/librdkafka/src-cpp/rdkafkacpp.h +28 -2
  145. package/deps/librdkafka/tests/0001-multiobj.c +4 -0
  146. package/deps/librdkafka/tests/0004-conf.c +103 -36
  147. package/deps/librdkafka/tests/0009-mock_cluster.c +1 -0
  148. package/deps/librdkafka/tests/0011-produce_batch.c +2 -1
  149. package/deps/librdkafka/tests/0016-client_swname.c +18 -3
  150. package/deps/librdkafka/tests/0017-compression.c +6 -8
  151. package/deps/librdkafka/tests/0018-cgrp_term.c +8 -3
  152. package/deps/librdkafka/tests/0021-rkt_destroy.c +1 -0
  153. package/deps/librdkafka/tests/0022-consume_batch.c +4 -1
  154. package/deps/librdkafka/tests/0026-consume_pause.c +12 -14
  155. package/deps/librdkafka/tests/0028-long_topicnames.c +1 -1
  156. package/deps/librdkafka/tests/0029-assign_offset.c +6 -8
  157. package/deps/librdkafka/tests/0030-offset_commit.c +2 -2
  158. package/deps/librdkafka/tests/0033-regex_subscribe.c +33 -17
  159. package/deps/librdkafka/tests/0034-offset_reset.c +25 -4
  160. package/deps/librdkafka/tests/0036-partial_fetch.c +1 -0
  161. package/deps/librdkafka/tests/0038-performance.c +1 -0
  162. package/deps/librdkafka/tests/0040-io_event.c +11 -5
  163. package/deps/librdkafka/tests/0041-fetch_max_bytes.c +1 -0
  164. package/deps/librdkafka/tests/0044-partition_cnt.c +3 -2
  165. package/deps/librdkafka/tests/0045-subscribe_update.c +284 -20
  166. package/deps/librdkafka/tests/0047-partial_buf_tmout.c +1 -0
  167. package/deps/librdkafka/tests/0048-partitioner.c +1 -1
  168. package/deps/librdkafka/tests/0050-subscribe_adds.c +1 -0
  169. package/deps/librdkafka/tests/0051-assign_adds.c +1 -0
  170. package/deps/librdkafka/tests/0052-msg_timestamps.c +22 -4
  171. package/deps/librdkafka/tests/0053-stats_cb.cpp +12 -20
  172. package/deps/librdkafka/tests/0055-producer_latency.c +176 -3
  173. package/deps/librdkafka/tests/0056-balanced_group_mt.c +6 -2
  174. package/deps/librdkafka/tests/0058-log.cpp +3 -3
  175. package/deps/librdkafka/tests/0059-bsearch.cpp +8 -4
  176. package/deps/librdkafka/tests/0061-consumer_lag.cpp +25 -5
  177. package/deps/librdkafka/tests/0067-empty_topic.cpp +3 -0
  178. package/deps/librdkafka/tests/0068-produce_timeout.c +21 -23
  179. package/deps/librdkafka/tests/0069-consumer_add_parts.c +3 -7
  180. package/deps/librdkafka/tests/0075-retry.c +38 -1
  181. package/deps/librdkafka/tests/0076-produce_retry.c +2 -0
  182. package/deps/librdkafka/tests/0077-compaction.c +8 -2
  183. package/deps/librdkafka/tests/0080-admin_ut.c +34 -4
  184. package/deps/librdkafka/tests/0081-admin.c +455 -155
  185. package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +4 -0
  186. package/deps/librdkafka/tests/0083-cb_event.c +8 -3
  187. package/deps/librdkafka/tests/0084-destroy_flags.c +14 -18
  188. package/deps/librdkafka/tests/0085-headers.cpp +4 -0
  189. package/deps/librdkafka/tests/0086-purge.c +40 -7
  190. package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +1 -1
  191. package/deps/librdkafka/tests/0089-max_poll_interval.c +12 -7
  192. package/deps/librdkafka/tests/0090-idempotence.c +1 -2
  193. package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +5 -7
  194. package/deps/librdkafka/tests/0092-mixed_msgver.c +6 -0
  195. package/deps/librdkafka/tests/0093-holb.c +8 -5
  196. package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +1 -0
  197. package/deps/librdkafka/tests/0097-ssl_verify.cpp +262 -70
  198. package/deps/librdkafka/tests/0098-consumer-txn.cpp +16 -16
  199. package/deps/librdkafka/tests/0099-commit_metadata.c +1 -1
  200. package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +1 -1
  201. package/deps/librdkafka/tests/0102-static_group_rebalance.c +317 -16
  202. package/deps/librdkafka/tests/0103-transactions.c +7 -7
  203. package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +1 -0
  204. package/deps/librdkafka/tests/0105-transactions_mock.c +18 -11
  205. package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +35 -14
  206. package/deps/librdkafka/tests/0107-topic_recreate.c +2 -2
  207. package/deps/librdkafka/tests/0109-auto_create_topics.cpp +86 -26
  208. package/deps/librdkafka/tests/0110-batch_size.cpp +1 -2
  209. package/deps/librdkafka/tests/0112-assign_unknown_part.c +3 -14
  210. package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +248 -104
  211. package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +3 -3
  212. package/deps/librdkafka/tests/0115-producer_auth.cpp +4 -1
  213. package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +7 -5
  214. package/deps/librdkafka/tests/0117-mock_errors.c +15 -5
  215. package/deps/librdkafka/tests/0118-commit_rebalance.c +41 -8
  216. package/deps/librdkafka/tests/0119-consumer_auth.cpp +20 -1
  217. package/deps/librdkafka/tests/0120-asymmetric_subscription.c +8 -3
  218. package/deps/librdkafka/tests/0125-immediate_flush.c +1 -1
  219. package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +323 -8
  220. package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +1 -0
  221. package/deps/librdkafka/tests/0132-strategy_ordering.c +12 -4
  222. package/deps/librdkafka/tests/0133-ssl_keys.c +28 -6
  223. package/deps/librdkafka/tests/0137-barrier_batch_consume.c +24 -14
  224. package/deps/librdkafka/tests/0139-offset_validation_mock.c +510 -2
  225. package/deps/librdkafka/tests/0140-commit_metadata.cpp +1 -1
  226. package/deps/librdkafka/tests/0142-reauthentication.c +37 -17
  227. package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +39 -40
  228. package/deps/librdkafka/tests/0146-metadata_mock.c +76 -15
  229. package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +952 -0
  230. package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +563 -0
  231. package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
  232. package/deps/librdkafka/tests/0150-telemetry_mock.c +9 -6
  233. package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
  234. package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
  235. package/deps/librdkafka/tests/0153-memberid.c +128 -0
  236. package/deps/librdkafka/tests/CMakeLists.txt +6 -0
  237. package/deps/librdkafka/tests/LibrdkafkaTestApp.py +34 -9
  238. package/deps/librdkafka/tests/autotest.sh +0 -0
  239. package/deps/librdkafka/tests/broker_version_tests.py +0 -0
  240. package/deps/librdkafka/tests/buildbox.sh +0 -0
  241. package/deps/librdkafka/tests/cleanup-checker-tests.sh +0 -0
  242. package/deps/librdkafka/tests/cluster_testing.py +0 -0
  243. package/deps/librdkafka/tests/delete-test-topics.sh +0 -0
  244. package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
  245. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
  246. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
  247. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
  248. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +42 -101
  249. package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
  250. package/deps/librdkafka/tests/fixtures/ssl/client2.key +41 -29
  251. package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +112 -37
  252. package/deps/librdkafka/tests/gen-ssl-certs.sh +0 -0
  253. package/deps/librdkafka/tests/interactive_broker_version.py +0 -0
  254. package/deps/librdkafka/tests/java/Makefile +2 -1
  255. package/deps/librdkafka/tests/java/run-class.sh +0 -0
  256. package/deps/librdkafka/tests/lz4_manual_test.sh +0 -0
  257. package/deps/librdkafka/tests/multi-broker-version-test.sh +0 -0
  258. package/deps/librdkafka/tests/parse-refcnt.sh +0 -0
  259. package/deps/librdkafka/tests/performance_plot.py +0 -0
  260. package/deps/librdkafka/tests/requirements.txt +1 -1
  261. package/deps/librdkafka/tests/run-all-tests.sh +79 -0
  262. package/deps/librdkafka/tests/run-consumer-tests.sh +0 -0
  263. package/deps/librdkafka/tests/run-producer-tests.sh +0 -0
  264. package/deps/librdkafka/tests/run-test-batches.py +157 -0
  265. package/deps/librdkafka/tests/run-test.sh +0 -0
  266. package/deps/librdkafka/tests/sasl_test.py +0 -0
  267. package/deps/librdkafka/tests/test.c +478 -18
  268. package/deps/librdkafka/tests/test.h +62 -13
  269. package/deps/librdkafka/tests/testcpp.cpp +6 -1
  270. package/deps/librdkafka/tests/testcpp.h +30 -2
  271. package/deps/librdkafka/tests/testshared.h +16 -2
  272. package/deps/librdkafka/tests/tools/stats/graph.py +0 -0
  273. package/deps/librdkafka/tests/tools/stats/to_csv.py +1 -1
  274. package/deps/librdkafka/tests/trivup/trivup-0.14.0.tar.gz +0 -0
  275. package/deps/librdkafka/tests/until-fail.sh +0 -0
  276. package/deps/librdkafka/tests/xxxx-metadata.cpp +1 -1
  277. package/deps/librdkafka/vcpkg.json +1 -1
  278. package/deps/librdkafka/win32/setup-msys2.ps1 +24 -8
  279. package/deps/librdkafka/win32/setup-vcpkg.ps1 +28 -6
  280. package/deps/librdkafka/win32/tests/tests.vcxproj +6 -0
  281. package/deps/librdkafka/win32/wingetopt.h +5 -4
  282. package/errors.d.ts +27 -1
  283. package/lib/error.js +29 -3
  284. package/make_docs.sh +0 -0
  285. package/package.json +11 -11
  286. package/run_docker.sh +0 -0
  287. package/src/callbacks.cc +6 -9
  288. package/src/callbacks.h +1 -5
  289. package/test/kafka-consumer-worker.js +10 -7
  290. package/test/kafka-consumer.spec.js +32 -21
  291. package/ci/update-version.js +0 -123
  292. package/deps/librdkafka/.semaphore/project.yml +0 -43
  293. package/deps/librdkafka/.semaphore/project_public.yml +0 -20
  294. package/deps/librdkafka/win32/install-openssl.ps1 +0 -33
@@ -123,6 +123,7 @@ int rd_kafka_err_action(rd_kafka_broker_t *rkb,
123
123
  case RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE:
124
124
  case RD_KAFKA_RESP_ERR_NOT_COORDINATOR:
125
125
  case RD_KAFKA_RESP_ERR__WAIT_COORD:
126
+ case RD_KAFKA_RESP_ERR__DESTROY_BROKER:
126
127
  /* Request metadata information update */
127
128
  actions |= RD_KAFKA_ERR_ACTION_REFRESH |
128
129
  RD_KAFKA_ERR_ACTION_MSG_NOT_PERSISTED;
@@ -200,16 +201,15 @@ int rd_kafka_err_action(rd_kafka_broker_t *rkb,
200
201
  return actions;
201
202
  }
202
203
 
203
-
204
204
  /**
205
205
  * @brief Read a list of topic+partitions+extra from \p rkbuf.
206
206
  *
207
- * @param rkbuf buffer to read from
207
+ * @param rkbuf Buffer to read from
208
208
  * @param fields An array of fields to read from the buffer and set on
209
209
  * the rktpar object, in the specified order, must end
210
210
  * with RD_KAFKA_TOPIC_PARTITION_FIELD_END.
211
211
  *
212
- * @returns a newly allocated list on success, or NULL on parse error.
212
+ * @returns A newly allocated list on success, or NULL on parse error.
213
213
  */
214
214
  rd_kafka_topic_partition_list_t *rd_kafka_buf_read_topic_partitions(
215
215
  rd_kafka_buf_t *rkbuf,
@@ -217,14 +217,44 @@ rd_kafka_topic_partition_list_t *rd_kafka_buf_read_topic_partitions(
217
217
  rd_bool_t use_topic_name,
218
218
  size_t estimated_part_cnt,
219
219
  const rd_kafka_topic_partition_field_t *fields) {
220
+ rd_bool_t parse_err;
221
+ /* Even if NULL it should be treated as a parse error,
222
+ * as this field isn't nullable. */
223
+ return rd_kafka_buf_read_topic_partitions_nullable(
224
+ rkbuf, use_topic_id, use_topic_name, estimated_part_cnt, fields,
225
+ &parse_err);
226
+ }
227
+
228
+ /**
229
+ * @brief Read a nullable list of topic+partitions+extra from \p rkbuf.
230
+ *
231
+ * @param rkbuf Buffer to read from
232
+ * @param fields An array of fields to read from the buffer and set on
233
+ * the rktpar object, in the specified order, must end
234
+ * with RD_KAFKA_TOPIC_PARTITION_FIELD_END.
235
+ * @param parse_err Is set to true if a parsing error occurred.
236
+ *
237
+ * @returns A newly allocated list, or NULL.
238
+ */
239
+ rd_kafka_topic_partition_list_t *rd_kafka_buf_read_topic_partitions_nullable(
240
+ rd_kafka_buf_t *rkbuf,
241
+ rd_bool_t use_topic_id,
242
+ rd_bool_t use_topic_name,
243
+ size_t estimated_part_cnt,
244
+ const rd_kafka_topic_partition_field_t *fields,
245
+ rd_bool_t *parse_err) {
220
246
  const int log_decode_errors = LOG_ERR;
221
247
  int32_t TopicArrayCnt;
222
248
  rd_kafka_topic_partition_list_t *parts = NULL;
223
249
 
224
- /* We assume here that the topic partition list is not NULL.
225
- * FIXME: check NULL topic array case, if required in future. */
250
+ rd_dassert(parse_err);
251
+ *parse_err = rd_false;
226
252
 
227
253
  rd_kafka_buf_read_arraycnt(rkbuf, &TopicArrayCnt, RD_KAFKAP_TOPICS_MAX);
254
+ if (TopicArrayCnt < -1)
255
+ goto err_parse;
256
+ else if (TopicArrayCnt == -1)
257
+ return NULL;
228
258
 
229
259
  parts = rd_kafka_topic_partition_list_new(
230
260
  RD_MAX(TopicArrayCnt * 4, (int)estimated_part_cnt));
@@ -334,6 +364,7 @@ err_parse:
334
364
  if (parts)
335
365
  rd_kafka_topic_partition_list_destroy(parts);
336
366
 
367
+ *parse_err = rd_true;
337
368
  return NULL;
338
369
  }
339
370
 
@@ -1132,6 +1163,11 @@ void rd_kafka_OffsetForLeaderEpochRequest(
1132
1163
  }
1133
1164
 
1134
1165
 
1166
+ int rd_kafka_handle_OffsetFetch_err_action(rd_kafka_broker_t *rkb,
1167
+ rd_kafka_resp_err_t err,
1168
+ rd_kafka_buf_t *request) {
1169
+ return rd_kafka_err_action(rkb, err, request, RD_KAFKA_ERR_ACTION_END);
1170
+ }
1135
1171
 
1136
1172
  /**
1137
1173
  * Generic handler for OffsetFetch responses.
@@ -1331,8 +1367,7 @@ err:
1331
1367
  seen_cnt, (*offsets)->cnt, retry_unstable,
1332
1368
  rd_kafka_err2str(err));
1333
1369
 
1334
- actions =
1335
- rd_kafka_err_action(rkb, err, request, RD_KAFKA_ERR_ACTION_END);
1370
+ actions = rd_kafka_handle_OffsetFetch_err_action(rkb, err, request);
1336
1371
 
1337
1372
  if (actions & RD_KAFKA_ERR_ACTION_REFRESH) {
1338
1373
  /* Re-query for coordinator */
@@ -1695,9 +1730,9 @@ rd_kafka_handle_OffsetCommit(rd_kafka_t *rk,
1695
1730
  continue;
1696
1731
  }
1697
1732
 
1733
+ rktpar->err = partition->err;
1698
1734
  if (partition->err) {
1699
- rktpar->err = partition->err;
1700
- err = partition->err;
1735
+ err = partition->err;
1701
1736
  errcnt++;
1702
1737
  /* Accumulate actions for per-partition
1703
1738
  * errors. */
@@ -2242,7 +2277,8 @@ void rd_kafka_ConsumerGroupHeartbeatRequest(
2242
2277
  const rd_kafkap_str_t *group_instance_id,
2243
2278
  const rd_kafkap_str_t *rack_id,
2244
2279
  int32_t rebalance_timeout_ms,
2245
- const rd_kafka_topic_partition_list_t *subscribe_topics,
2280
+ const rd_kafka_topic_partition_list_t *subscribed_topics,
2281
+ rd_kafkap_str_t *subscribed_topic_regex,
2246
2282
  const rd_kafkap_str_t *remote_assignor,
2247
2283
  const rd_kafka_topic_partition_list_t *current_assignments,
2248
2284
  rd_kafka_replyq_t replyq,
@@ -2253,26 +2289,37 @@ void rd_kafka_ConsumerGroupHeartbeatRequest(
2253
2289
  int16_t ApiVersion = 0;
2254
2290
  int features;
2255
2291
  size_t rkbuf_size = 0;
2292
+ rd_kafkap_str_t *subscribed_topic_regex_to_send =
2293
+ subscribed_topic_regex;
2256
2294
 
2257
2295
  ApiVersion = rd_kafka_broker_ApiVersion_supported(
2258
- rkb, RD_KAFKAP_ConsumerGroupHeartbeat, 0, 0, &features);
2296
+ rkb, RD_KAFKAP_ConsumerGroupHeartbeat, 1, 1, &features);
2297
+
2298
+ if (ApiVersion == -1) {
2299
+ rd_kafka_cgrp_coord_dead(rkb->rkb_rk->rk_cgrp,
2300
+ RD_KAFKA_RESP_ERR__UNSUPPORTED_FEATURE,
2301
+ "ConsumerGroupHeartbeatRequest not "
2302
+ "supported by broker");
2303
+ return;
2304
+ }
2259
2305
 
2260
2306
  if (rd_rkb_is_dbg(rkb, CGRP)) {
2261
- char current_assignments_str[512] = "NULL";
2262
- char subscribe_topics_str[512] = "NULL";
2263
- const char *member_id_str = "NULL";
2264
- const char *group_instance_id_str = "NULL";
2265
- const char *remote_assignor_str = "NULL";
2307
+ char current_assignments_str[512] = "NULL";
2308
+ char subscribed_topics_str[512] = "NULL";
2309
+ const char *member_id_str = "NULL";
2310
+ const char *group_instance_id_str = "NULL";
2311
+ const char *remote_assignor_str = "NULL";
2312
+ const char *subscribed_topic_regex_to_send_str = "NULL";
2266
2313
 
2267
2314
  if (current_assignments) {
2268
2315
  rd_kafka_topic_partition_list_str(
2269
2316
  current_assignments, current_assignments_str,
2270
2317
  sizeof(current_assignments_str), 0);
2271
2318
  }
2272
- if (subscribe_topics) {
2319
+ if (subscribed_topics) {
2273
2320
  rd_kafka_topic_partition_list_str(
2274
- subscribe_topics, subscribe_topics_str,
2275
- sizeof(subscribe_topics_str), 0);
2321
+ subscribed_topics, subscribed_topics_str,
2322
+ sizeof(subscribed_topics_str), 0);
2276
2323
  }
2277
2324
  if (member_id)
2278
2325
  member_id_str = member_id->str;
@@ -2280,6 +2327,9 @@ void rd_kafka_ConsumerGroupHeartbeatRequest(
2280
2327
  group_instance_id_str = group_instance_id->str;
2281
2328
  if (remote_assignor)
2282
2329
  remote_assignor_str = remote_assignor->str;
2330
+ if (subscribed_topic_regex_to_send)
2331
+ subscribed_topic_regex_to_send_str =
2332
+ subscribed_topic_regex_to_send->str;
2283
2333
 
2284
2334
  rd_rkb_dbg(rkb, CGRP, "HEARTBEAT",
2285
2335
  "ConsumerGroupHeartbeat of member id \"%s\", group "
@@ -2287,19 +2337,27 @@ void rd_kafka_ConsumerGroupHeartbeatRequest(
2287
2337
  "generation id %" PRId32
2288
2338
  ", group instance id \"%s\""
2289
2339
  ", current assignment \"%s\""
2290
- ", subscribe topics \"%s\""
2340
+ ", subscribed topics \"%s\""
2341
+ ", subscribed topic regex \"%s\""
2291
2342
  ", remote assignor \"%s\"",
2292
2343
  member_id_str, group_id->str, member_epoch,
2293
2344
  group_instance_id_str, current_assignments_str,
2294
- subscribe_topics_str, remote_assignor_str);
2345
+ subscribed_topics_str,
2346
+ subscribed_topic_regex_to_send_str,
2347
+ remote_assignor_str);
2295
2348
  }
2296
2349
 
2297
2350
  size_t next_subscription_size = 0;
2298
2351
 
2299
- if (subscribe_topics) {
2352
+ if (!subscribed_topic_regex_to_send)
2353
+ subscribed_topic_regex_to_send = rd_kafkap_str_new(NULL, -1);
2354
+
2355
+ if (subscribed_topics) {
2300
2356
  next_subscription_size =
2301
- ((subscribe_topics->cnt * (4 + 50)) + 4);
2357
+ ((subscribed_topics->cnt * (4 + 50)) + 4);
2302
2358
  }
2359
+ next_subscription_size +=
2360
+ RD_KAFKAP_STR_SIZE(subscribed_topic_regex_to_send);
2303
2361
 
2304
2362
  if (group_id)
2305
2363
  rkbuf_size += RD_KAFKAP_STR_SIZE(group_id);
@@ -2329,23 +2387,23 @@ void rd_kafka_ConsumerGroupHeartbeatRequest(
2329
2387
  rd_kafka_buf_write_kstr(rkbuf, rack_id);
2330
2388
  rd_kafka_buf_write_i32(rkbuf, rebalance_timeout_ms);
2331
2389
 
2332
- if (subscribe_topics) {
2333
- size_t of_TopicsArrayCnt;
2334
- int topics_cnt = subscribe_topics->cnt;
2390
+ if (subscribed_topics) {
2391
+ int topics_cnt = subscribed_topics->cnt;
2335
2392
 
2336
2393
  /* write Topics */
2337
- of_TopicsArrayCnt = rd_kafka_buf_write_arraycnt_pos(rkbuf);
2338
- rd_kafka_buf_finalize_arraycnt(rkbuf, of_TopicsArrayCnt,
2339
- topics_cnt);
2394
+ rd_kafka_buf_write_arraycnt(rkbuf, topics_cnt);
2340
2395
  while (--topics_cnt >= 0)
2341
2396
  rd_kafka_buf_write_str(
2342
- rkbuf, subscribe_topics->elems[topics_cnt].topic,
2397
+ rkbuf, subscribed_topics->elems[topics_cnt].topic,
2343
2398
  -1);
2344
2399
 
2345
2400
  } else {
2346
2401
  rd_kafka_buf_write_arraycnt(rkbuf, -1);
2347
2402
  }
2348
2403
 
2404
+ if (ApiVersion >= 1)
2405
+ rd_kafka_buf_write_kstr(rkbuf, subscribed_topic_regex_to_send);
2406
+
2349
2407
  rd_kafka_buf_write_kstr(rkbuf, remote_assignor);
2350
2408
 
2351
2409
  if (current_assignments) {
@@ -2379,6 +2437,9 @@ void rd_kafka_ConsumerGroupHeartbeatRequest(
2379
2437
  }
2380
2438
 
2381
2439
  rd_kafka_broker_buf_enq_replyq(rkb, rkbuf, replyq, resp_cb, opaque);
2440
+
2441
+ if (!subscribed_topic_regex)
2442
+ rd_kafkap_str_destroy(subscribed_topic_regex_to_send);
2382
2443
  }
2383
2444
 
2384
2445
 
@@ -2531,9 +2592,11 @@ static void rd_kafka_handle_Metadata(rd_kafka_t *rk,
2531
2592
  rd_kafka_op_t *rko = opaque; /* Possibly NULL */
2532
2593
  rd_kafka_metadata_internal_t *mdi = NULL;
2533
2594
  const rd_list_t *topics = request->rkbuf_u.Metadata.topics;
2595
+ const int32_t cgrp_subscription_version =
2596
+ request->rkbuf_u.Metadata.cgrp_subscription_version;
2534
2597
  int actions;
2535
2598
 
2536
- rd_kafka_assert(NULL, err == RD_KAFKA_RESP_ERR__DESTROY ||
2599
+ rd_kafka_assert(NULL, rd_kafka_broker_is_any_err_destroy(err) ||
2537
2600
  thrd_is_current(rk->rk_thread));
2538
2601
 
2539
2602
  /* Avoid metadata updates when we're terminating. */
@@ -2561,12 +2624,15 @@ static void rd_kafka_handle_Metadata(rd_kafka_t *rk,
2561
2624
  if (err)
2562
2625
  goto err;
2563
2626
 
2627
+ rd_kafka_rebootstrap_tmr_stop(rk);
2564
2628
  if (rko && rko->rko_replyq.q) {
2565
2629
  /* Reply to metadata requester, passing on the metadata.
2566
2630
  * Reuse requesting rko for the reply. */
2567
2631
  rko->rko_err = err;
2568
2632
  rko->rko_u.metadata.md = &mdi->metadata;
2569
2633
  rko->rko_u.metadata.mdi = mdi;
2634
+ rko->rko_u.metadata.subscription_version =
2635
+ cgrp_subscription_version;
2570
2636
  rd_kafka_replyq_enq(&rko->rko_replyq, rko, 0);
2571
2637
  rko = NULL;
2572
2638
  } else {
@@ -2577,35 +2643,50 @@ static void rd_kafka_handle_Metadata(rd_kafka_t *rk,
2577
2643
  goto done;
2578
2644
 
2579
2645
  err:
2580
- actions = rd_kafka_err_action(rkb, err, request,
2646
+ actions = rd_kafka_err_action(
2647
+ rkb, err, request,
2581
2648
 
2582
- RD_KAFKA_ERR_ACTION_RETRY,
2583
- RD_KAFKA_RESP_ERR__PARTIAL,
2649
+ RD_KAFKA_ERR_ACTION_SPECIAL, RD_KAFKA_RESP_ERR_REBOOTSTRAP_REQUIRED,
2584
2650
 
2585
- RD_KAFKA_ERR_ACTION_END);
2651
+ RD_KAFKA_ERR_ACTION_RETRY, RD_KAFKA_RESP_ERR__PARTIAL,
2652
+
2653
+ RD_KAFKA_ERR_ACTION_END);
2654
+
2655
+ if (actions & RD_KAFKA_ERR_ACTION_SPECIAL) {
2656
+ rd_kafka_rebootstrap(rk);
2657
+ }
2586
2658
 
2587
2659
  if (actions & RD_KAFKA_ERR_ACTION_RETRY) {
2588
- if (rd_kafka_buf_retry(rkb, request))
2660
+ /* In case it's a brokers full refresh call,
2661
+ * avoid retrying it on this same broker.
2662
+ * This is to prevent client is hung
2663
+ * until it can connect to this broker again.
2664
+ * No need to acquire the lock here but
2665
+ * when decrementing the integer pointed
2666
+ * by `decr`. */
2667
+ if (!request->rkbuf_u.Metadata.decr &&
2668
+ rd_kafka_buf_retry(rkb, request))
2589
2669
  return;
2590
2670
  /* FALLTHRU */
2591
- } else {
2671
+ }
2672
+
2673
+ if (actions & RD_KAFKA_ERR_ACTION_PERMANENT) {
2592
2674
  rd_rkb_log(rkb, LOG_WARNING, "METADATA",
2593
2675
  "Metadata request failed: %s: %s (%dms): %s",
2594
2676
  request->rkbuf_u.Metadata.reason,
2595
2677
  rd_kafka_err2str(err),
2596
2678
  (int)(request->rkbuf_ts_sent / 1000),
2597
2679
  rd_kafka_actions2str(actions));
2598
- /* Respond back to caller on non-retriable errors */
2599
- if (rko && rko->rko_replyq.q) {
2600
- rko->rko_err = err;
2601
- rko->rko_u.metadata.md = NULL;
2602
- rko->rko_u.metadata.mdi = NULL;
2603
- rd_kafka_replyq_enq(&rko->rko_replyq, rko, 0);
2604
- rko = NULL;
2605
- }
2606
2680
  }
2607
2681
 
2608
-
2682
+ /* Respond back to caller on non-retriable errors */
2683
+ if (rko && rko->rko_replyq.q) {
2684
+ rko->rko_err = err;
2685
+ rko->rko_u.metadata.md = NULL;
2686
+ rko->rko_u.metadata.mdi = NULL;
2687
+ rd_kafka_replyq_enq(&rko->rko_replyq, rko, 0);
2688
+ rko = NULL;
2689
+ }
2609
2690
 
2610
2691
  /* FALLTHRU */
2611
2692
 
@@ -2668,6 +2749,18 @@ done:
2668
2749
  *
2669
2750
  * @sa rd_kafka_MetadataRequest().
2670
2751
  * @sa rd_kafka_MetadataRequest_resp_cb().
2752
+ *
2753
+ * @locality any
2754
+ * @locks none
2755
+ * @locks_acquired
2756
+ * - mtx_lock(&rkb->rkb_rk->rk_metadata_cache.rkmc_full_lock) in
2757
+ * this function
2758
+ * - rd_kafka_broker_lock() in
2759
+ * rd_kafka_broker_ApiVersion_supported()
2760
+ * - rd_kafka_timers_lock() in
2761
+ * rd_kafka_rebootstrap_tmr_start_maybe()
2762
+ * - mtx_lock(&rkq->rkq_lock) in
2763
+ * rd_kafka_broker_buf_enq_replyq()
2671
2764
  */
2672
2765
  static rd_kafka_resp_err_t
2673
2766
  rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
@@ -2678,6 +2771,7 @@ rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
2678
2771
  rd_bool_t include_cluster_authorized_operations,
2679
2772
  rd_bool_t include_topic_authorized_operations,
2680
2773
  rd_bool_t cgrp_update,
2774
+ int32_t cgrp_subscription_version,
2681
2775
  rd_bool_t force_racks,
2682
2776
  rd_kafka_op_t *rko,
2683
2777
  rd_kafka_resp_cb_t *resp_cb,
@@ -2694,7 +2788,7 @@ rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
2694
2788
  int *full_incr = NULL;
2695
2789
  void *handler_arg = NULL;
2696
2790
  rd_kafka_resp_cb_t *handler_cb = rd_kafka_handle_Metadata;
2697
- int16_t metadata_max_version = 12;
2791
+ int16_t metadata_max_version = 13;
2698
2792
  rd_kafka_replyq_t use_replyq = replyq;
2699
2793
 
2700
2794
  /* In case we want cluster authorized operations in the Metadata
@@ -2721,9 +2815,10 @@ rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
2721
2815
  if (!reason)
2722
2816
  reason = "";
2723
2817
 
2724
- rkbuf->rkbuf_u.Metadata.reason = rd_strdup(reason);
2725
- rkbuf->rkbuf_u.Metadata.cgrp_update = cgrp_update;
2726
- rkbuf->rkbuf_u.Metadata.force_racks = force_racks;
2818
+ rkbuf->rkbuf_u.Metadata.reason = rd_strdup(reason);
2819
+ rkbuf->rkbuf_u.Metadata.cgrp_update = cgrp_update;
2820
+ rkbuf->rkbuf_u.Metadata.force_racks = force_racks;
2821
+ rkbuf->rkbuf_u.Metadata.cgrp_subscription_version = -1;
2727
2822
 
2728
2823
  /* TopicArrayCnt */
2729
2824
  of_TopicArrayCnt = rd_kafka_buf_write_arraycnt_pos(rkbuf);
@@ -2799,9 +2894,28 @@ rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
2799
2894
  rkbuf->rkbuf_u.Metadata.decr = full_incr;
2800
2895
  rkbuf->rkbuf_u.Metadata.decr_lock =
2801
2896
  &rkb->rkb_rk->rk_metadata_cache.rkmc_full_lock;
2897
+ } else if (!resp_cb) {
2898
+ /*
2899
+ * Conditions for starting the rebootstrap timer:
2900
+ *
2901
+ * !full_incr:
2902
+ * In case it's a full request, forced or not, it won't be
2903
+ * retried on the same broker to avoid blocking metadata
2904
+ * requests, because of the lock, when that broker isn't
2905
+ * available. We don't start the timer as we cannot ensure the
2906
+ * request is retried for the duration of
2907
+ * `metadata.recovery.rebootstrap.trigger.ms`.
2908
+ *
2909
+ * !resp_cb:
2910
+ * Same reasoning applies when we use a custom callback, for the
2911
+ * AdminClient requests for example.
2912
+ *
2913
+ * Start the rebootstrap timer only if it's the first
2914
+ * metadata refresh request after last successful response,
2915
+ * so the timer is not reset if already scheduled. */
2916
+ rd_kafka_rebootstrap_tmr_start_maybe(rkb->rkb_rk);
2802
2917
  }
2803
2918
 
2804
-
2805
2919
  if (topic_cnt > 0) {
2806
2920
  char *topic;
2807
2921
  int i;
@@ -2898,6 +3012,13 @@ rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
2898
3012
  if (!use_replyq.q)
2899
3013
  use_replyq = RD_KAFKA_REPLYQ(rkb->rkb_rk->rk_ops, 0);
2900
3014
 
3015
+ if (cgrp_update && rkb->rkb_rk->rk_cgrp && total_topic_cnt > 0) {
3016
+ rkbuf->rkbuf_u.Metadata.cgrp_subscription_version =
3017
+ cgrp_subscription_version >= 0
3018
+ ? cgrp_subscription_version
3019
+ : rd_atomic32_get(
3020
+ &rkb->rkb_rk->rk_cgrp->rkcg_subscription_version);
3021
+ }
2901
3022
  rd_kafka_broker_buf_enq_replyq(
2902
3023
  rkb, rkbuf, use_replyq,
2903
3024
  /* The default response handler is rd_kafka_handle_Metadata, but we
@@ -2924,6 +3045,7 @@ rd_kafka_MetadataRequest0(rd_kafka_broker_t *rkb,
2924
3045
  * This is best-effort, depending on broker
2925
3046
  * config and version.
2926
3047
  * @param cgrp_update - Update cgrp in parse_Metadata (see comment there).
3048
+ * @param subscription_version - Consumer group subscription version.
2927
3049
  * @param force_racks - Force partition to rack mapping computation in
2928
3050
  * parse_Metadata (see comment there).
2929
3051
  * @param rko - (optional) rko with replyq for handling response.
@@ -2946,13 +3068,14 @@ rd_kafka_resp_err_t rd_kafka_MetadataRequest(rd_kafka_broker_t *rkb,
2946
3068
  const char *reason,
2947
3069
  rd_bool_t allow_auto_create_topics,
2948
3070
  rd_bool_t cgrp_update,
3071
+ int32_t cgrp_subscription_version,
2949
3072
  rd_bool_t force_racks,
2950
3073
  rd_kafka_op_t *rko) {
2951
3074
  return rd_kafka_MetadataRequest0(
2952
3075
  rkb, topics, topic_ids, reason, allow_auto_create_topics,
2953
3076
  rd_false /*don't include cluster authorized operations*/,
2954
3077
  rd_false /*don't include topic authorized operations*/, cgrp_update,
2955
- force_racks, rko,
3078
+ cgrp_subscription_version, force_racks, rko,
2956
3079
  /* We use the default rd_kafka_handle_Metadata rather than a custom
2957
3080
  resp_cb */
2958
3081
  NULL,
@@ -3011,6 +3134,7 @@ rd_kafka_resp_err_t rd_kafka_MetadataRequest_resp_cb(
3011
3134
  rd_bool_t include_cluster_authorized_operations,
3012
3135
  rd_bool_t include_topic_authorized_operations,
3013
3136
  rd_bool_t cgrp_update,
3137
+ int32_t cgrp_subscription_version,
3014
3138
  rd_bool_t force_racks,
3015
3139
  rd_kafka_resp_cb_t *resp_cb,
3016
3140
  rd_kafka_replyq_t replyq,
@@ -3019,7 +3143,8 @@ rd_kafka_resp_err_t rd_kafka_MetadataRequest_resp_cb(
3019
3143
  return rd_kafka_MetadataRequest0(
3020
3144
  rkb, topics, topics_ids, reason, allow_auto_create_topics,
3021
3145
  include_cluster_authorized_operations,
3022
- include_topic_authorized_operations, cgrp_update, force_racks,
3146
+ include_topic_authorized_operations, cgrp_update,
3147
+ cgrp_subscription_version, force_racks,
3023
3148
  NULL /* No op - using custom resp_cb. */, resp_cb, replyq, force,
3024
3149
  opaque);
3025
3150
  }
@@ -3244,6 +3369,9 @@ void rd_kafka_handle_SaslAuthenticate(rd_kafka_t *rk,
3244
3369
  rd_kafkap_bytes_t auth_data;
3245
3370
  char errstr[512];
3246
3371
 
3372
+ if (rd_kafka_broker_is_any_err_destroy(err))
3373
+ return;
3374
+
3247
3375
  if (err) {
3248
3376
  rd_snprintf(errstr, sizeof(errstr),
3249
3377
  "SaslAuthenticateRequest failed: %s",
@@ -5259,7 +5387,9 @@ rd_kafka_AlterConfigsRequest(rd_kafka_broker_t *rkb,
5259
5387
  int ei;
5260
5388
 
5261
5389
  /* ResourceType */
5262
- rd_kafka_buf_write_i8(rkbuf, config->restype);
5390
+ rd_kafka_buf_write_i8(
5391
+ rkbuf, rd_kafka_ResourceType_to_ConfigResourceType(
5392
+ config->restype));
5263
5393
 
5264
5394
  /* ResourceName */
5265
5395
  rd_kafka_buf_write_str(rkbuf, config->name, -1);
@@ -5341,7 +5471,9 @@ rd_kafka_resp_err_t rd_kafka_IncrementalAlterConfigsRequest(
5341
5471
  int ei;
5342
5472
 
5343
5473
  /* ResourceType */
5344
- rd_kafka_buf_write_i8(rkbuf, config->restype);
5474
+ rd_kafka_buf_write_i8(
5475
+ rkbuf, rd_kafka_ResourceType_to_ConfigResourceType(
5476
+ config->restype));
5345
5477
 
5346
5478
  /* ResourceName */
5347
5479
  rd_kafka_buf_write_str(rkbuf, config->name, -1);
@@ -5435,7 +5567,9 @@ rd_kafka_resp_err_t rd_kafka_DescribeConfigsRequest(
5435
5567
  int ei;
5436
5568
 
5437
5569
  /* resource_type */
5438
- rd_kafka_buf_write_i8(rkbuf, config->restype);
5570
+ rd_kafka_buf_write_i8(
5571
+ rkbuf, rd_kafka_ResourceType_to_ConfigResourceType(
5572
+ config->restype));
5439
5573
 
5440
5574
  /* resource_name */
5441
5575
  rd_kafka_buf_write_str(rkbuf, config->name, -1);
@@ -5973,6 +6107,61 @@ rd_kafka_resp_err_t rd_kafka_ElectLeadersRequest(
5973
6107
 
5974
6108
  return RD_KAFKA_RESP_ERR_NO_ERROR;
5975
6109
  }
6110
+
6111
+ /**
6112
+ * @brief Construct and send ConsumerGroupDescribe requests
6113
+ * to \p rkb with the groups (const char *) in \p groups.
6114
+ * Uses \p include_authorized_operations to get
6115
+ * group ACL authorized operations.
6116
+ *
6117
+ * The response (unparsed) will be enqueued on \p replyq
6118
+ * for handling by \p resp_cb (with \p opaque passed).
6119
+ *
6120
+ * @return NULL on success, a new error instance that must be
6121
+ * released with rd_kafka_error_destroy() in case of error.
6122
+ */
6123
+ rd_kafka_error_t *
6124
+ rd_kafka_ConsumerGroupDescribeRequest(rd_kafka_broker_t *rkb,
6125
+ char **groups,
6126
+ size_t group_cnt,
6127
+ rd_bool_t include_authorized_operations,
6128
+ rd_kafka_replyq_t replyq,
6129
+ rd_kafka_resp_cb_t *resp_cb,
6130
+ void *opaque) {
6131
+ rd_kafka_buf_t *rkbuf;
6132
+ size_t i;
6133
+
6134
+ int16_t ApiVersion = rd_kafka_broker_ApiVersion_supported(
6135
+ rkb, RD_KAFKAP_ConsumerGroupDescribe, 0, 0, NULL);
6136
+
6137
+ if (ApiVersion == -1) {
6138
+ return rd_kafka_error_new(
6139
+ RD_KAFKA_RESP_ERR__UNSUPPORTED_FEATURE,
6140
+ "ConsumerGroupDescribe (KIP-848) "
6141
+ "not supported by broker, "
6142
+ "requires broker version >= 4.0.0");
6143
+ }
6144
+
6145
+ rkbuf = rd_kafka_buf_new_flexver_request(
6146
+ rkb, RD_KAFKAP_ConsumerGroupDescribe, 1,
6147
+ 4 /* rd_kafka_buf_write_arraycnt_pos */ +
6148
+ 1 /* IncludeAuthorizedOperations */ + 1 /* tags */ +
6149
+ 32 * group_cnt /* Groups */,
6150
+ rd_true /* flexver */);
6151
+
6152
+ rd_kafka_buf_write_arraycnt(rkbuf, group_cnt);
6153
+
6154
+ for (i = 0; i < group_cnt; i++) {
6155
+ rd_kafka_buf_write_str(rkbuf, groups[i], -1);
6156
+ }
6157
+
6158
+ rd_kafka_buf_write_bool(rkbuf, include_authorized_operations);
6159
+ rd_kafka_buf_ApiVersion_set(rkbuf, ApiVersion, 0);
6160
+ rd_kafka_broker_buf_enq_replyq(rkb, rkbuf, replyq, resp_cb, opaque);
6161
+
6162
+ return NULL;
6163
+ }
6164
+
5976
6165
  /**
5977
6166
  * @brief Parses and handles an InitProducerId reply.
5978
6167
  *
@@ -6364,16 +6553,17 @@ rd_kafka_PushTelemetryRequest(rd_kafka_broker_t *rkb,
6364
6553
  }
6365
6554
 
6366
6555
  size_t len = sizeof(rd_kafka_Uuid_t) + sizeof(int32_t) +
6367
- sizeof(rd_bool_t) + sizeof(compression_type) +
6368
- metrics_size;
6556
+ sizeof(rd_bool_t) + sizeof(int8_t) + metrics_size;
6369
6557
  rkbuf = rd_kafka_buf_new_flexver_request(rkb, RD_KAFKAP_PushTelemetry,
6370
6558
  1, len, rd_true);
6371
6559
 
6372
6560
  rd_kafka_buf_write_uuid(rkbuf, client_instance_id);
6373
6561
  rd_kafka_buf_write_i32(rkbuf, subscription_id);
6374
6562
  rd_kafka_buf_write_bool(rkbuf, terminating);
6375
- rd_kafka_buf_write_i8(rkbuf, compression_type);
6563
+ rd_kafka_buf_write_i8(rkbuf, (int8_t)compression_type);
6376
6564
 
6565
+ rd_dassert(metrics != NULL);
6566
+ rd_dassert(metrics_size >= 0);
6377
6567
  rd_kafkap_bytes_t *metric_bytes =
6378
6568
  rd_kafkap_bytes_new(metrics, metrics_size);
6379
6569
  rd_kafka_buf_write_kbytes(rkbuf, metric_bytes);
@@ -6435,10 +6625,12 @@ void rd_kafka_handle_GetTelemetrySubscriptions(rd_kafka_t *rk,
6435
6625
  rk->rk_telemetry.accepted_compression_types =
6436
6626
  rd_calloc(arraycnt, sizeof(rd_kafka_compression_t));
6437
6627
 
6438
- for (i = 0; i < (size_t)arraycnt; i++)
6439
- rd_kafka_buf_read_i8(
6440
- rkbuf,
6441
- &rk->rk_telemetry.accepted_compression_types[i]);
6628
+ for (i = 0; i < (size_t)arraycnt; i++) {
6629
+ int8_t AcceptedCompressionType;
6630
+ rd_kafka_buf_read_i8(rkbuf, &AcceptedCompressionType);
6631
+ rk->rk_telemetry.accepted_compression_types[i] =
6632
+ AcceptedCompressionType;
6633
+ }
6442
6634
  } else {
6443
6635
  rk->rk_telemetry.accepted_compression_types_cnt = 1;
6444
6636
  rk->rk_telemetry.accepted_compression_types =
@@ -6478,7 +6670,7 @@ void rd_kafka_handle_GetTelemetrySubscriptions(rd_kafka_t *rk,
6478
6670
  rd_kafkap_str_t Metric;
6479
6671
  rd_kafka_buf_read_str(rkbuf, &Metric);
6480
6672
  rk->rk_telemetry.requested_metrics[i] =
6481
- rd_strdup(Metric.str);
6673
+ RD_KAFKAP_STR_DUP(&Metric);
6482
6674
  }
6483
6675
  }
6484
6676
 
@@ -6803,6 +6995,85 @@ static int unittest_idempotent_producer(void) {
6803
6995
  return 0;
6804
6996
  }
6805
6997
 
6998
+ /**
6999
+ * @brief Test for the GetTelemetrySubscriptions response handling.
7000
+ *
7001
+ * @returns 1 on failure, 0 on success.
7002
+ */
7003
+ static int unittest_handle_GetTelemetrySubscriptions(void) {
7004
+ rd_kafka_t *rk;
7005
+ rd_kafka_broker_t *rkb;
7006
+ rd_kafka_buf_t *rkbuf;
7007
+
7008
+ RD_UT_SAY("Verifying GetTelemetrySubscriptions response handling");
7009
+
7010
+ rk = rd_kafka_new(RD_KAFKA_CONSUMER, NULL, NULL, 0);
7011
+ rkb = rd_kafka_broker_add_logical(rk, "unittest");
7012
+
7013
+ rkbuf = rd_kafka_buf_new(0, 0);
7014
+ rkbuf->rkbuf_rkb = rkb;
7015
+ rd_kafka_buf_write_i32(rkbuf, 0); /* ThrottleTime */
7016
+ rd_kafka_buf_write_i16(rkbuf, 0); /* ErrorCode */
7017
+
7018
+ rd_kafka_buf_write_uuid(rkbuf, &rk->rk_telemetry.client_instance_id);
7019
+
7020
+ rd_kafka_buf_write_i32(rkbuf, 0); /* SubscriptionId */
7021
+
7022
+ rd_kafka_buf_write_arraycnt(rkbuf, 2); /* #AcceptedCompressionTypes */
7023
+ /* AcceptedCompressionTypes[0] */
7024
+ rd_kafka_buf_write_i8(rkbuf, RD_KAFKA_COMPRESSION_GZIP);
7025
+ /* AcceptedCompressionTypes[1] */
7026
+ rd_kafka_buf_write_i8(rkbuf, RD_KAFKA_COMPRESSION_LZ4);
7027
+
7028
+ rd_kafka_buf_write_i32(rkbuf, 0); /* PushIntervalMs */
7029
+ rd_kafka_buf_write_i32(rkbuf, 0); /* TelemetryMaxBytes */
7030
+ rd_kafka_buf_write_bool(rkbuf, 0); /* DeltaTemporality */
7031
+
7032
+ rd_kafka_buf_write_arraycnt(rkbuf, 2); /* #RequestedMetrics */
7033
+ /* RequestedMetrics[0] */
7034
+ rd_kafka_buf_write_str(rkbuf, "metric1", -1);
7035
+ /* RequestedMetrics[1] */
7036
+ rd_kafka_buf_write_str(rkbuf, "metric2", -1);
7037
+
7038
+ /* Set up a buffer reader for sending the buffer. */
7039
+ rd_slice_init_full(&rkbuf->rkbuf_reader, &rkbuf->rkbuf_buf);
7040
+
7041
+ /* Handle the response */
7042
+ rd_kafka_handle_GetTelemetrySubscriptions(
7043
+ rk, rkb, RD_KAFKA_RESP_ERR_NO_ERROR, rkbuf, NULL, NULL);
7044
+
7045
+
7046
+ RD_UT_ASSERT(rk->rk_telemetry.accepted_compression_types_cnt == 2,
7047
+ "Expected 2 accepted compression types, got %" PRIusz,
7048
+ rk->rk_telemetry.accepted_compression_types_cnt);
7049
+ RD_UT_ASSERT(rk->rk_telemetry.accepted_compression_types[0] ==
7050
+ RD_KAFKA_COMPRESSION_GZIP,
7051
+ "Expected 'gzip' compression type, got '%s'",
7052
+ rd_kafka_compression2str(
7053
+ rk->rk_telemetry.accepted_compression_types[0]));
7054
+ RD_UT_ASSERT(rk->rk_telemetry.accepted_compression_types[1] ==
7055
+ RD_KAFKA_COMPRESSION_LZ4,
7056
+ "Expected 'lz4' compression type, got '%s'",
7057
+ rd_kafka_compression2str(
7058
+ rk->rk_telemetry.accepted_compression_types[1]));
7059
+
7060
+ RD_UT_ASSERT(rk->rk_telemetry.requested_metrics_cnt == 2,
7061
+ "Expected 2 requested metrics, got %" PRIusz,
7062
+ rk->rk_telemetry.requested_metrics_cnt);
7063
+ RD_UT_ASSERT(
7064
+ rd_strcmp(rk->rk_telemetry.requested_metrics[0], "metric1") == 0,
7065
+ "Expected 'metric1', got '%s'",
7066
+ rk->rk_telemetry.requested_metrics[0]);
7067
+ RD_UT_ASSERT(
7068
+ rd_strcmp(rk->rk_telemetry.requested_metrics[1], "metric2") == 0,
7069
+ "Expected 'metric2', got '%s'",
7070
+ rk->rk_telemetry.requested_metrics[1]);
7071
+
7072
+ rd_kafka_buf_destroy(rkbuf);
7073
+ rd_kafka_destroy(rk);
7074
+ return 0;
7075
+ }
7076
+
6806
7077
  /**
6807
7078
  * @brief Request/response unit tests
6808
7079
  */
@@ -6810,6 +7081,7 @@ int unittest_request(void) {
6810
7081
  int fails = 0;
6811
7082
 
6812
7083
  fails += unittest_idempotent_producer();
7084
+ fails += unittest_handle_GetTelemetrySubscriptions();
6813
7085
 
6814
7086
  return fails;
6815
7087
  }