@platformatic/rdkafka 4.0.1 → 4.1.0-alpha.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 (292) 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 +4 -4
  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/configure +0 -0
  17. package/deps/librdkafka/debian/rules +0 -0
  18. package/deps/librdkafka/dev-conf.sh +0 -0
  19. package/deps/librdkafka/examples/consumer.c +18 -8
  20. package/deps/librdkafka/examples/describe_consumer_groups.c +25 -6
  21. package/deps/librdkafka/examples/incremental_alter_configs.c +4 -5
  22. package/deps/librdkafka/examples/kafkatest_verifiable_client.cpp +26 -42
  23. package/deps/librdkafka/examples/openssl_engine_example.cpp +3 -4
  24. package/deps/librdkafka/examples/producer.cpp +2 -2
  25. package/deps/librdkafka/examples/user_scram.c +4 -5
  26. package/deps/librdkafka/examples/win_ssl_cert_store.cpp +4 -3
  27. package/deps/librdkafka/lds-gen.py +0 -0
  28. package/deps/librdkafka/mklove/Makefile.base +0 -0
  29. package/deps/librdkafka/packaging/RELEASE.md +8 -0
  30. package/deps/librdkafka/packaging/alpine/build-alpine.sh +0 -0
  31. package/deps/librdkafka/packaging/cp/README.md +4 -1
  32. package/deps/librdkafka/packaging/cp/check_features.c +12 -4
  33. package/deps/librdkafka/packaging/cp/verify-deb.sh +6 -6
  34. package/deps/librdkafka/packaging/cp/verify-packages.sh +52 -31
  35. package/deps/librdkafka/packaging/cp/verify-rpm.sh +6 -13
  36. package/deps/librdkafka/packaging/debian/rules +0 -0
  37. package/deps/librdkafka/packaging/get_version.py +0 -0
  38. package/deps/librdkafka/packaging/homebrew/brew-update-pr.sh +0 -0
  39. package/deps/librdkafka/packaging/mingw-w64/{travis-before-install.sh → export-variables.sh} +0 -7
  40. package/deps/librdkafka/packaging/mingw-w64/semaphoreci-build.sh +1 -1
  41. package/deps/librdkafka/packaging/nuget/artifact.py +0 -0
  42. package/deps/librdkafka/packaging/nuget/cleanup-s3.py +0 -0
  43. package/deps/librdkafka/packaging/nuget/nuget.sh +0 -0
  44. package/deps/librdkafka/packaging/nuget/packaging.py +0 -0
  45. package/deps/librdkafka/packaging/nuget/push-to-nuget.sh +0 -0
  46. package/deps/librdkafka/packaging/nuget/release.py +0 -0
  47. package/deps/librdkafka/packaging/nuget/requirements.txt +3 -3
  48. package/deps/librdkafka/packaging/rpm/mock-on-docker.sh +0 -0
  49. package/deps/librdkafka/packaging/rpm/tests/run-test.sh +0 -0
  50. package/deps/librdkafka/packaging/rpm/tests/test-on-docker.sh +0 -0
  51. package/deps/librdkafka/packaging/tools/build-configurations-checks.sh +3 -1
  52. package/deps/librdkafka/packaging/tools/build-deb-package.sh +0 -0
  53. package/deps/librdkafka/packaging/tools/build-debian.sh +0 -0
  54. package/deps/librdkafka/packaging/tools/build-manylinux.sh +0 -0
  55. package/deps/librdkafka/packaging/tools/build-release-artifacts.sh +0 -0
  56. package/deps/librdkafka/packaging/tools/distro-build.sh +0 -0
  57. package/deps/librdkafka/packaging/tools/gh-release-checksums.py +0 -0
  58. package/deps/librdkafka/packaging/tools/rdutcoverage.sh +0 -0
  59. package/deps/librdkafka/packaging/tools/run-in-docker.sh +28 -0
  60. package/deps/librdkafka/packaging/tools/run-integration-tests.sh +31 -0
  61. package/deps/librdkafka/packaging/tools/run-style-check.sh +4 -0
  62. package/deps/librdkafka/packaging/tools/style-format.sh +6 -5
  63. package/deps/librdkafka/packaging/tools/update_rpcs_max_versions.py +100 -0
  64. package/deps/librdkafka/service.yml +154 -0
  65. package/deps/librdkafka/src/generate_proto.sh +0 -0
  66. package/deps/librdkafka/src/rd.h +145 -2
  67. package/deps/librdkafka/src/rdaddr.h +6 -7
  68. package/deps/librdkafka/src/rdatomic.h +15 -11
  69. package/deps/librdkafka/src/rdavg.h +3 -2
  70. package/deps/librdkafka/src/rdbase64.c +33 -2
  71. package/deps/librdkafka/src/rdbase64.h +2 -0
  72. package/deps/librdkafka/src/rdendian.h +10 -9
  73. package/deps/librdkafka/src/rdhttp.c +418 -100
  74. package/deps/librdkafka/src/rdhttp.h +23 -5
  75. package/deps/librdkafka/src/rdkafka.c +299 -145
  76. package/deps/librdkafka/src/rdkafka.h +89 -6
  77. package/deps/librdkafka/src/rdkafka_admin.c +482 -105
  78. package/deps/librdkafka/src/rdkafka_admin.h +42 -0
  79. package/deps/librdkafka/src/rdkafka_broker.c +463 -312
  80. package/deps/librdkafka/src/rdkafka_broker.h +68 -10
  81. package/deps/librdkafka/src/rdkafka_buf.c +8 -5
  82. package/deps/librdkafka/src/rdkafka_buf.h +4 -3
  83. package/deps/librdkafka/src/rdkafka_cert.c +25 -1
  84. package/deps/librdkafka/src/rdkafka_cert.h +4 -3
  85. package/deps/librdkafka/src/rdkafka_cgrp.c +468 -143
  86. package/deps/librdkafka/src/rdkafka_cgrp.h +36 -2
  87. package/deps/librdkafka/src/rdkafka_conf.c +526 -102
  88. package/deps/librdkafka/src/rdkafka_conf.h +68 -4
  89. package/deps/librdkafka/src/rdkafka_feature.c +472 -35
  90. package/deps/librdkafka/src/rdkafka_feature.h +2 -0
  91. package/deps/librdkafka/src/rdkafka_fetcher.c +22 -2
  92. package/deps/librdkafka/src/rdkafka_fetcher.h +2 -2
  93. package/deps/librdkafka/src/rdkafka_int.h +84 -46
  94. package/deps/librdkafka/src/rdkafka_metadata.c +221 -136
  95. package/deps/librdkafka/src/rdkafka_metadata.h +15 -11
  96. package/deps/librdkafka/src/rdkafka_metadata_cache.c +279 -73
  97. package/deps/librdkafka/src/rdkafka_mock.c +795 -19
  98. package/deps/librdkafka/src/rdkafka_mock.h +119 -0
  99. package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1298 -132
  100. package/deps/librdkafka/src/rdkafka_mock_handlers.c +345 -49
  101. package/deps/librdkafka/src/rdkafka_mock_int.h +180 -61
  102. package/deps/librdkafka/src/rdkafka_msg.c +35 -19
  103. package/deps/librdkafka/src/rdkafka_msg.h +3 -3
  104. package/deps/librdkafka/src/rdkafka_msgset_writer.c +14 -10
  105. package/deps/librdkafka/src/rdkafka_offset.c +33 -5
  106. package/deps/librdkafka/src/rdkafka_op.c +1 -1
  107. package/deps/librdkafka/src/rdkafka_op.h +45 -21
  108. package/deps/librdkafka/src/rdkafka_partition.c +118 -23
  109. package/deps/librdkafka/src/rdkafka_partition.h +16 -7
  110. package/deps/librdkafka/src/rdkafka_proto.h +4 -1
  111. package/deps/librdkafka/src/rdkafka_protocol.h +1 -0
  112. package/deps/librdkafka/src/rdkafka_queue.c +125 -48
  113. package/deps/librdkafka/src/rdkafka_queue.h +19 -0
  114. package/deps/librdkafka/src/rdkafka_range_assignor.c +1 -1
  115. package/deps/librdkafka/src/rdkafka_request.c +336 -64
  116. package/deps/librdkafka/src/rdkafka_request.h +24 -1
  117. package/deps/librdkafka/src/rdkafka_sasl.c +5 -3
  118. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +14 -10
  119. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1166 -89
  120. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +13 -3
  121. package/deps/librdkafka/src/rdkafka_sasl_plain.c +3 -3
  122. package/deps/librdkafka/src/rdkafka_sasl_scram.c +4 -3
  123. package/deps/librdkafka/src/rdkafka_ssl.c +306 -81
  124. package/deps/librdkafka/src/rdkafka_ssl.h +22 -0
  125. package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4 -0
  126. package/deps/librdkafka/src/rdkafka_telemetry.c +80 -23
  127. package/deps/librdkafka/src/rdkafka_telemetry_encode.c +5 -1
  128. package/deps/librdkafka/src/rdkafka_telemetry_encode.h +20 -20
  129. package/deps/librdkafka/src/rdkafka_topic.c +220 -137
  130. package/deps/librdkafka/src/rdkafka_topic.h +14 -8
  131. package/deps/librdkafka/src/rdkafka_transport.c +59 -47
  132. package/deps/librdkafka/src/rdkafka_transport.h +5 -0
  133. package/deps/librdkafka/src/rdkafka_txnmgr.c +6 -1
  134. package/deps/librdkafka/src/rdmap.c +6 -1
  135. package/deps/librdkafka/src/rdrand.c +11 -1
  136. package/deps/librdkafka/src/rdtime.h +48 -17
  137. package/deps/librdkafka/src/rdunittest.c +42 -25
  138. package/deps/librdkafka/src/rdunittest.h +2 -0
  139. package/deps/librdkafka/src/rdwin32.h +1 -1
  140. package/deps/librdkafka/src/regexp.c +47 -42
  141. package/deps/librdkafka/src/tinycthread_extra.c +45 -21
  142. package/deps/librdkafka/src/tinycthread_extra.h +7 -3
  143. package/deps/librdkafka/src-cpp/rdkafkacpp.h +28 -2
  144. package/deps/librdkafka/tests/0001-multiobj.c +4 -0
  145. package/deps/librdkafka/tests/0004-conf.c +103 -36
  146. package/deps/librdkafka/tests/0009-mock_cluster.c +1 -0
  147. package/deps/librdkafka/tests/0011-produce_batch.c +2 -1
  148. package/deps/librdkafka/tests/0016-client_swname.c +18 -3
  149. package/deps/librdkafka/tests/0017-compression.c +6 -8
  150. package/deps/librdkafka/tests/0018-cgrp_term.c +8 -3
  151. package/deps/librdkafka/tests/0021-rkt_destroy.c +1 -0
  152. package/deps/librdkafka/tests/0022-consume_batch.c +4 -1
  153. package/deps/librdkafka/tests/0026-consume_pause.c +12 -14
  154. package/deps/librdkafka/tests/0028-long_topicnames.c +1 -1
  155. package/deps/librdkafka/tests/0029-assign_offset.c +6 -8
  156. package/deps/librdkafka/tests/0030-offset_commit.c +2 -2
  157. package/deps/librdkafka/tests/0033-regex_subscribe.c +33 -17
  158. package/deps/librdkafka/tests/0034-offset_reset.c +25 -4
  159. package/deps/librdkafka/tests/0036-partial_fetch.c +1 -0
  160. package/deps/librdkafka/tests/0038-performance.c +1 -0
  161. package/deps/librdkafka/tests/0040-io_event.c +11 -5
  162. package/deps/librdkafka/tests/0041-fetch_max_bytes.c +1 -0
  163. package/deps/librdkafka/tests/0044-partition_cnt.c +3 -2
  164. package/deps/librdkafka/tests/0045-subscribe_update.c +284 -20
  165. package/deps/librdkafka/tests/0047-partial_buf_tmout.c +1 -0
  166. package/deps/librdkafka/tests/0048-partitioner.c +1 -1
  167. package/deps/librdkafka/tests/0050-subscribe_adds.c +1 -0
  168. package/deps/librdkafka/tests/0051-assign_adds.c +1 -0
  169. package/deps/librdkafka/tests/0052-msg_timestamps.c +22 -4
  170. package/deps/librdkafka/tests/0053-stats_cb.cpp +12 -20
  171. package/deps/librdkafka/tests/0055-producer_latency.c +176 -3
  172. package/deps/librdkafka/tests/0056-balanced_group_mt.c +6 -2
  173. package/deps/librdkafka/tests/0058-log.cpp +3 -3
  174. package/deps/librdkafka/tests/0059-bsearch.cpp +8 -4
  175. package/deps/librdkafka/tests/0061-consumer_lag.cpp +25 -5
  176. package/deps/librdkafka/tests/0067-empty_topic.cpp +3 -0
  177. package/deps/librdkafka/tests/0068-produce_timeout.c +21 -23
  178. package/deps/librdkafka/tests/0069-consumer_add_parts.c +3 -7
  179. package/deps/librdkafka/tests/0075-retry.c +38 -1
  180. package/deps/librdkafka/tests/0076-produce_retry.c +2 -0
  181. package/deps/librdkafka/tests/0077-compaction.c +8 -2
  182. package/deps/librdkafka/tests/0080-admin_ut.c +34 -4
  183. package/deps/librdkafka/tests/0081-admin.c +455 -155
  184. package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +4 -0
  185. package/deps/librdkafka/tests/0083-cb_event.c +8 -3
  186. package/deps/librdkafka/tests/0084-destroy_flags.c +14 -18
  187. package/deps/librdkafka/tests/0085-headers.cpp +4 -0
  188. package/deps/librdkafka/tests/0086-purge.c +40 -7
  189. package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +1 -1
  190. package/deps/librdkafka/tests/0089-max_poll_interval.c +12 -7
  191. package/deps/librdkafka/tests/0090-idempotence.c +1 -2
  192. package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +5 -7
  193. package/deps/librdkafka/tests/0092-mixed_msgver.c +6 -0
  194. package/deps/librdkafka/tests/0093-holb.c +8 -5
  195. package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +1 -0
  196. package/deps/librdkafka/tests/0097-ssl_verify.cpp +262 -70
  197. package/deps/librdkafka/tests/0098-consumer-txn.cpp +16 -16
  198. package/deps/librdkafka/tests/0099-commit_metadata.c +1 -1
  199. package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +1 -1
  200. package/deps/librdkafka/tests/0102-static_group_rebalance.c +317 -16
  201. package/deps/librdkafka/tests/0103-transactions.c +7 -7
  202. package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +1 -0
  203. package/deps/librdkafka/tests/0105-transactions_mock.c +18 -11
  204. package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +35 -14
  205. package/deps/librdkafka/tests/0107-topic_recreate.c +2 -2
  206. package/deps/librdkafka/tests/0109-auto_create_topics.cpp +86 -26
  207. package/deps/librdkafka/tests/0110-batch_size.cpp +1 -2
  208. package/deps/librdkafka/tests/0112-assign_unknown_part.c +3 -14
  209. package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +248 -104
  210. package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +3 -3
  211. package/deps/librdkafka/tests/0115-producer_auth.cpp +4 -1
  212. package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +7 -5
  213. package/deps/librdkafka/tests/0117-mock_errors.c +15 -5
  214. package/deps/librdkafka/tests/0118-commit_rebalance.c +41 -8
  215. package/deps/librdkafka/tests/0119-consumer_auth.cpp +20 -1
  216. package/deps/librdkafka/tests/0120-asymmetric_subscription.c +8 -3
  217. package/deps/librdkafka/tests/0125-immediate_flush.c +1 -1
  218. package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +323 -8
  219. package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +1 -0
  220. package/deps/librdkafka/tests/0132-strategy_ordering.c +12 -4
  221. package/deps/librdkafka/tests/0133-ssl_keys.c +28 -6
  222. package/deps/librdkafka/tests/0137-barrier_batch_consume.c +24 -14
  223. package/deps/librdkafka/tests/0139-offset_validation_mock.c +510 -2
  224. package/deps/librdkafka/tests/0140-commit_metadata.cpp +1 -1
  225. package/deps/librdkafka/tests/0142-reauthentication.c +37 -17
  226. package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +39 -40
  227. package/deps/librdkafka/tests/0146-metadata_mock.c +76 -15
  228. package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +952 -0
  229. package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +563 -0
  230. package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
  231. package/deps/librdkafka/tests/0150-telemetry_mock.c +9 -6
  232. package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
  233. package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
  234. package/deps/librdkafka/tests/0153-memberid.c +128 -0
  235. package/deps/librdkafka/tests/CMakeLists.txt +6 -0
  236. package/deps/librdkafka/tests/LibrdkafkaTestApp.py +34 -9
  237. package/deps/librdkafka/tests/autotest.sh +0 -0
  238. package/deps/librdkafka/tests/broker_version_tests.py +0 -0
  239. package/deps/librdkafka/tests/buildbox.sh +0 -0
  240. package/deps/librdkafka/tests/cleanup-checker-tests.sh +0 -0
  241. package/deps/librdkafka/tests/cluster_testing.py +0 -0
  242. package/deps/librdkafka/tests/delete-test-topics.sh +0 -0
  243. package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
  244. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
  245. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
  246. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
  247. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +42 -101
  248. package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
  249. package/deps/librdkafka/tests/fixtures/ssl/client2.key +41 -29
  250. package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +112 -37
  251. package/deps/librdkafka/tests/gen-ssl-certs.sh +0 -0
  252. package/deps/librdkafka/tests/interactive_broker_version.py +0 -0
  253. package/deps/librdkafka/tests/java/Makefile +2 -1
  254. package/deps/librdkafka/tests/java/run-class.sh +0 -0
  255. package/deps/librdkafka/tests/lz4_manual_test.sh +0 -0
  256. package/deps/librdkafka/tests/multi-broker-version-test.sh +0 -0
  257. package/deps/librdkafka/tests/parse-refcnt.sh +0 -0
  258. package/deps/librdkafka/tests/performance_plot.py +0 -0
  259. package/deps/librdkafka/tests/requirements.txt +1 -1
  260. package/deps/librdkafka/tests/run-all-tests.sh +79 -0
  261. package/deps/librdkafka/tests/run-consumer-tests.sh +0 -0
  262. package/deps/librdkafka/tests/run-producer-tests.sh +0 -0
  263. package/deps/librdkafka/tests/run-test-batches.py +157 -0
  264. package/deps/librdkafka/tests/run-test.sh +0 -0
  265. package/deps/librdkafka/tests/sasl_test.py +0 -0
  266. package/deps/librdkafka/tests/test.c +478 -18
  267. package/deps/librdkafka/tests/test.h +62 -13
  268. package/deps/librdkafka/tests/testcpp.cpp +6 -1
  269. package/deps/librdkafka/tests/testcpp.h +30 -2
  270. package/deps/librdkafka/tests/testshared.h +16 -2
  271. package/deps/librdkafka/tests/tools/stats/graph.py +0 -0
  272. package/deps/librdkafka/tests/tools/stats/to_csv.py +1 -1
  273. package/deps/librdkafka/tests/trivup/trivup-0.14.0.tar.gz +0 -0
  274. package/deps/librdkafka/tests/until-fail.sh +0 -0
  275. package/deps/librdkafka/tests/xxxx-metadata.cpp +1 -1
  276. package/deps/librdkafka/vcpkg.json +1 -1
  277. package/deps/librdkafka/win32/setup-msys2.ps1 +24 -8
  278. package/deps/librdkafka/win32/setup-vcpkg.ps1 +28 -6
  279. package/deps/librdkafka/win32/tests/tests.vcxproj +6 -0
  280. package/deps/librdkafka/win32/wingetopt.h +5 -4
  281. package/errors.d.ts +27 -1
  282. package/lib/error.js +29 -3
  283. package/make_docs.sh +0 -0
  284. package/package.json +10 -11
  285. package/run_docker.sh +0 -0
  286. package/src/callbacks.cc +6 -9
  287. package/src/callbacks.h +1 -5
  288. package/test/kafka-consumer-worker.js +10 -7
  289. package/test/kafka-consumer.spec.js +32 -21
  290. package/deps/librdkafka/.semaphore/project.yml +0 -43
  291. package/deps/librdkafka/.semaphore/project_public.yml +0 -20
  292. package/deps/librdkafka/win32/install-openssl.ps1 +0 -33
@@ -231,11 +231,12 @@ static const char *rd_kafka_admin_state_desc[] = {
231
231
  * @enum Admin request target broker. Must be negative values since the field
232
232
  * used is broker_id.
233
233
  */
234
- enum { RD_KAFKA_ADMIN_TARGET_CONTROLLER = -1, /**< Cluster controller */
235
- RD_KAFKA_ADMIN_TARGET_COORDINATOR = -2, /**< (Group) Coordinator */
236
- RD_KAFKA_ADMIN_TARGET_FANOUT = -3, /**< This rko is a fanout and
237
- * and has no target broker */
238
- RD_KAFKA_ADMIN_TARGET_ALL = -4, /**< All available brokers */
234
+ enum {
235
+ RD_KAFKA_ADMIN_TARGET_CONTROLLER = -1, /**< Cluster controller */
236
+ RD_KAFKA_ADMIN_TARGET_COORDINATOR = -2, /**< (Group) Coordinator */
237
+ RD_KAFKA_ADMIN_TARGET_FANOUT = -3, /**< This rko is a fanout and
238
+ * and has no target broker */
239
+ RD_KAFKA_ADMIN_TARGET_ALL = -4, /**< All available brokers */
239
240
  };
240
241
 
241
242
  /**
@@ -381,6 +382,8 @@ static rd_kafka_op_t *rd_kafka_admin_result_new(rd_kafka_op_t *rko_req) {
381
382
 
382
383
  rko_result->rko_evtype = rko_req->rko_u.admin_request.reply_event_type;
383
384
 
385
+ rko_result->rko_u.admin_result.cbs = rko_req->rko_u.admin_request.cbs;
386
+
384
387
  return rko_result;
385
388
  }
386
389
 
@@ -495,8 +498,8 @@ rd_kafka_admin_coord_request(rd_kafka_broker_t *rkb,
495
498
  rkb, &rko->rko_u.admin_request.args,
496
499
  &rko->rko_u.admin_request.options, errstr, sizeof(errstr), replyq,
497
500
  rd_kafka_admin_handle_response, eonce);
501
+
498
502
  if (err) {
499
- rd_kafka_enq_once_del_source(eonce, "coordinator response");
500
503
  rd_kafka_admin_result_fail(
501
504
  rko, err, "%s worker failed to send request: %s",
502
505
  rd_kafka_op2str(rko->rko_type), errstr);
@@ -1511,8 +1514,9 @@ rd_kafka_admin_MetadataRequest(rd_kafka_broker_t *rkb,
1511
1514
  rd_false /* No admin operation requires topic creation. */,
1512
1515
  include_cluster_authorized_operations,
1513
1516
  include_topic_authorized_operations,
1514
- rd_false /* No admin operation should update cgrp. */, force_racks,
1515
- resp_cb, replyq,
1517
+ rd_false /* No admin operation should update cgrp. */,
1518
+ -1 /* No subscription version is used */, force_racks, resp_cb,
1519
+ replyq,
1516
1520
  rd_true /* Admin operation metadata requests are always forced. */,
1517
1521
  opaque);
1518
1522
  }
@@ -2151,7 +2155,7 @@ rd_kafka_CreateTopicsResponse_parse(rd_kafka_op_t *rko_req,
2151
2155
  * does not maintain ordering unfortunately. */
2152
2156
  skel.topic = terr->topic;
2153
2157
  orig_pos = rd_list_index(&rko_result->rko_u.admin_result.args,
2154
- &skel, rd_kafka_NewTopic_cmp);
2158
+ &skel, rd_kafka_NewTopic_cmp);
2155
2159
  if (orig_pos == -1) {
2156
2160
  rd_kafka_topic_result_destroy(terr);
2157
2161
  rd_kafka_buf_parse_fail(
@@ -2360,7 +2364,7 @@ rd_kafka_DeleteTopicsResponse_parse(rd_kafka_op_t *rko_req,
2360
2364
  * does not maintain ordering unfortunately. */
2361
2365
  skel.topic = terr->topic;
2362
2366
  orig_pos = rd_list_index(&rko_result->rko_u.admin_result.args,
2363
- &skel, rd_kafka_DeleteTopic_cmp);
2367
+ &skel, rd_kafka_DeleteTopic_cmp);
2364
2368
  if (orig_pos == -1) {
2365
2369
  rd_kafka_topic_result_destroy(terr);
2366
2370
  rd_kafka_buf_parse_fail(
@@ -2645,7 +2649,7 @@ rd_kafka_CreatePartitionsResponse_parse(rd_kafka_op_t *rko_req,
2645
2649
  * does not maintain ordering unfortunately. */
2646
2650
  skel.topic = terr->topic;
2647
2651
  orig_pos = rd_list_index(&rko_result->rko_u.admin_result.args,
2648
- &skel, rd_kafka_NewPartitions_cmp);
2652
+ &skel, rd_kafka_NewPartitions_cmp);
2649
2653
  if (orig_pos == -1) {
2650
2654
  rd_kafka_topic_result_destroy(terr);
2651
2655
  rd_kafka_buf_parse_fail(
@@ -2864,9 +2868,15 @@ rd_kafka_ConfigEntry_synonyms(const rd_kafka_ConfigEntry_t *entry,
2864
2868
 
2865
2869
  const char *rd_kafka_ConfigSource_name(rd_kafka_ConfigSource_t confsource) {
2866
2870
  static const char *names[] = {
2867
- "UNKNOWN_CONFIG", "DYNAMIC_TOPIC_CONFIG",
2868
- "DYNAMIC_BROKER_CONFIG", "DYNAMIC_DEFAULT_BROKER_CONFIG",
2869
- "STATIC_BROKER_CONFIG", "DEFAULT_CONFIG",
2871
+ "UNKNOWN_CONFIG",
2872
+ "DYNAMIC_TOPIC_CONFIG",
2873
+ "DYNAMIC_BROKER_CONFIG",
2874
+ "DYNAMIC_DEFAULT_BROKER_CONFIG",
2875
+ "STATIC_BROKER_CONFIG",
2876
+ "DEFAULT_CONFIG",
2877
+ "DYNAMIC_BROKER_LOGGER_CONFIG",
2878
+ "CLIENT_METRICS_CONFIG",
2879
+ "GROUP_CONFIG",
2870
2880
  };
2871
2881
 
2872
2882
  if ((unsigned int)confsource >=
@@ -2911,6 +2921,35 @@ const char *rd_kafka_ResourceType_name(rd_kafka_ResourceType_t restype) {
2911
2921
  }
2912
2922
 
2913
2923
 
2924
+ rd_kafka_ConfigResourceType_t
2925
+ rd_kafka_ResourceType_to_ConfigResourceType(rd_kafka_ResourceType_t restype) {
2926
+ switch (restype) {
2927
+ case RD_KAFKA_RESOURCE_TOPIC:
2928
+ return RD_KAFKA_CONFIG_RESOURCE_TOPIC;
2929
+ case RD_KAFKA_RESOURCE_BROKER:
2930
+ return RD_KAFKA_CONFIG_RESOURCE_BROKER;
2931
+ case RD_KAFKA_RESOURCE_GROUP:
2932
+ return RD_KAFKA_CONFIG_RESOURCE_GROUP;
2933
+ default:
2934
+ return RD_KAFKA_CONFIG_RESOURCE_UNKNOWN;
2935
+ }
2936
+ }
2937
+
2938
+ rd_kafka_ResourceType_t rd_kafka_ConfigResourceType_to_ResourceType(
2939
+ rd_kafka_ConfigResourceType_t config_resource_type) {
2940
+ switch (config_resource_type) {
2941
+ case RD_KAFKA_CONFIG_RESOURCE_TOPIC:
2942
+ return RD_KAFKA_RESOURCE_TOPIC;
2943
+ case RD_KAFKA_CONFIG_RESOURCE_BROKER:
2944
+ return RD_KAFKA_RESOURCE_BROKER;
2945
+ case RD_KAFKA_CONFIG_RESOURCE_GROUP:
2946
+ return RD_KAFKA_RESOURCE_GROUP;
2947
+ default:
2948
+ return RD_KAFKA_RESOURCE_UNKNOWN;
2949
+ }
2950
+ }
2951
+
2952
+
2914
2953
  rd_kafka_ConfigResource_t *
2915
2954
  rd_kafka_ConfigResource_new(rd_kafka_ResourceType_t restype,
2916
2955
  const char *resname) {
@@ -3175,6 +3214,7 @@ rd_kafka_AlterConfigsResponse_parse(rd_kafka_op_t *rko_req,
3175
3214
  int16_t error_code;
3176
3215
  rd_kafkap_str_t error_msg;
3177
3216
  int8_t res_type;
3217
+ int8_t config_resource_type;
3178
3218
  rd_kafkap_str_t kres_name;
3179
3219
  char *res_name;
3180
3220
  char *this_errstr = NULL;
@@ -3184,11 +3224,14 @@ rd_kafka_AlterConfigsResponse_parse(rd_kafka_op_t *rko_req,
3184
3224
 
3185
3225
  rd_kafka_buf_read_i16(reply, &error_code);
3186
3226
  rd_kafka_buf_read_str(reply, &error_msg);
3187
- rd_kafka_buf_read_i8(reply, &res_type);
3227
+ rd_kafka_buf_read_i8(reply, &config_resource_type);
3188
3228
  rd_kafka_buf_read_str(reply, &kres_name);
3189
3229
  RD_KAFKAP_STR_DUPA(&res_name, &kres_name);
3190
3230
  rd_kafka_buf_skip_tags(reply);
3191
3231
 
3232
+ res_type = rd_kafka_ConfigResourceType_to_ResourceType(
3233
+ config_resource_type);
3234
+
3192
3235
  if (error_code) {
3193
3236
  if (RD_KAFKAP_STR_IS_NULL(&error_msg) ||
3194
3237
  RD_KAFKAP_STR_LEN(&error_msg) == 0)
@@ -3368,6 +3411,7 @@ rd_kafka_IncrementalAlterConfigsResponse_parse(rd_kafka_op_t *rko_req,
3368
3411
  int16_t error_code;
3369
3412
  rd_kafkap_str_t error_msg;
3370
3413
  int8_t res_type;
3414
+ int8_t config_resource_type;
3371
3415
  rd_kafkap_str_t kres_name;
3372
3416
  char *res_name;
3373
3417
  char *this_errstr = NULL;
@@ -3377,11 +3421,14 @@ rd_kafka_IncrementalAlterConfigsResponse_parse(rd_kafka_op_t *rko_req,
3377
3421
 
3378
3422
  rd_kafka_buf_read_i16(reply, &error_code);
3379
3423
  rd_kafka_buf_read_str(reply, &error_msg);
3380
- rd_kafka_buf_read_i8(reply, &res_type);
3424
+ rd_kafka_buf_read_i8(reply, &config_resource_type);
3381
3425
  rd_kafka_buf_read_str(reply, &kres_name);
3382
3426
  RD_KAFKAP_STR_DUPA(&res_name, &kres_name);
3383
3427
  rd_kafka_buf_skip_tags(reply);
3384
3428
 
3429
+ res_type = rd_kafka_ConfigResourceType_to_ResourceType(
3430
+ config_resource_type);
3431
+
3385
3432
  if (error_code) {
3386
3433
  if (RD_KAFKAP_STR_IS_NULL(&error_msg) ||
3387
3434
  RD_KAFKAP_STR_LEN(&error_msg) == 0)
@@ -3638,6 +3685,7 @@ rd_kafka_DescribeConfigsResponse_parse(rd_kafka_op_t *rko_req,
3638
3685
  for (i = 0; i < (int)res_cnt; i++) {
3639
3686
  int16_t error_code;
3640
3687
  rd_kafkap_str_t error_msg;
3688
+ int8_t config_resource_type;
3641
3689
  int8_t res_type;
3642
3690
  rd_kafkap_str_t kres_name;
3643
3691
  char *res_name;
@@ -3649,10 +3697,13 @@ rd_kafka_DescribeConfigsResponse_parse(rd_kafka_op_t *rko_req,
3649
3697
 
3650
3698
  rd_kafka_buf_read_i16(reply, &error_code);
3651
3699
  rd_kafka_buf_read_str(reply, &error_msg);
3652
- rd_kafka_buf_read_i8(reply, &res_type);
3700
+ rd_kafka_buf_read_i8(reply, &config_resource_type);
3653
3701
  rd_kafka_buf_read_str(reply, &kres_name);
3654
3702
  RD_KAFKAP_STR_DUPA(&res_name, &kres_name);
3655
3703
 
3704
+ res_type = rd_kafka_ConfigResourceType_to_ResourceType(
3705
+ config_resource_type);
3706
+
3656
3707
  if (error_code) {
3657
3708
  if (RD_KAFKAP_STR_IS_NULL(&error_msg) ||
3658
3709
  RD_KAFKAP_STR_LEN(&error_msg) == 0)
@@ -7501,8 +7552,8 @@ err_parse:
7501
7552
  error = rd_kafka_error_new(
7502
7553
  error_code,
7503
7554
  "Broker [%d"
7504
- "] "
7505
- "ListConsumerGroups response protocol parse failure: %s",
7555
+ "] "
7556
+ "ListConsumerGroups response protocol parse failure: %s",
7506
7557
  rd_kafka_broker_id(rkb), rd_kafka_err2str(error_code));
7507
7558
  rd_list_add(&errors, error);
7508
7559
  }
@@ -7748,7 +7799,8 @@ static rd_kafka_MemberDescription_t *rd_kafka_MemberDescription_new(
7748
7799
  const char *consumer_id,
7749
7800
  const char *group_instance_id,
7750
7801
  const char *host,
7751
- const rd_kafka_topic_partition_list_t *assignment) {
7802
+ const rd_kafka_topic_partition_list_t *assignment,
7803
+ const rd_kafka_topic_partition_list_t *target_assignment) {
7752
7804
  rd_kafka_MemberDescription_t *member;
7753
7805
  member = rd_calloc(1, sizeof(*member));
7754
7806
  member->client_id = rd_strdup(client_id);
@@ -7762,6 +7814,12 @@ static rd_kafka_MemberDescription_t *rd_kafka_MemberDescription_new(
7762
7814
  else
7763
7815
  member->assignment.partitions =
7764
7816
  rd_kafka_topic_partition_list_new(0);
7817
+ if (target_assignment) {
7818
+ member->target_assignment =
7819
+ rd_calloc(1, sizeof(rd_kafka_MemberAssignment_t));
7820
+ member->target_assignment->partitions =
7821
+ rd_kafka_topic_partition_list_copy(target_assignment);
7822
+ }
7765
7823
  return member;
7766
7824
  }
7767
7825
 
@@ -7775,9 +7833,10 @@ static rd_kafka_MemberDescription_t *rd_kafka_MemberDescription_new(
7775
7833
  */
7776
7834
  static rd_kafka_MemberDescription_t *
7777
7835
  rd_kafka_MemberDescription_copy(const rd_kafka_MemberDescription_t *src) {
7778
- return rd_kafka_MemberDescription_new(src->client_id, src->consumer_id,
7779
- src->group_instance_id, src->host,
7780
- src->assignment.partitions);
7836
+ return rd_kafka_MemberDescription_new(
7837
+ src->client_id, src->consumer_id, src->group_instance_id, src->host,
7838
+ src->assignment.partitions,
7839
+ src->target_assignment ? src->target_assignment->partitions : NULL);
7781
7840
  }
7782
7841
 
7783
7842
  /**
@@ -7796,11 +7855,14 @@ rd_kafka_MemberDescription_destroy(rd_kafka_MemberDescription_t *member) {
7796
7855
  rd_free(member->client_id);
7797
7856
  rd_free(member->consumer_id);
7798
7857
  rd_free(member->host);
7799
- if (member->group_instance_id != NULL)
7800
- rd_free(member->group_instance_id);
7801
- if (member->assignment.partitions)
7802
- rd_kafka_topic_partition_list_destroy(
7803
- member->assignment.partitions);
7858
+ RD_IF_FREE(member->group_instance_id, rd_free);
7859
+ RD_IF_FREE(member->assignment.partitions,
7860
+ rd_kafka_topic_partition_list_destroy);
7861
+ if (member->target_assignment) {
7862
+ RD_IF_FREE(member->target_assignment->partitions,
7863
+ rd_kafka_topic_partition_list_destroy);
7864
+ rd_free(member->target_assignment);
7865
+ }
7804
7866
  rd_free(member);
7805
7867
  }
7806
7868
 
@@ -7838,6 +7900,11 @@ const rd_kafka_topic_partition_list_t *rd_kafka_MemberAssignment_partitions(
7838
7900
  return assignment->partitions;
7839
7901
  }
7840
7902
 
7903
+ const rd_kafka_MemberAssignment_t *rd_kafka_MemberDescription_target_assignment(
7904
+ const rd_kafka_MemberDescription_t *member) {
7905
+ return member->target_assignment;
7906
+ }
7907
+
7841
7908
 
7842
7909
  /**
7843
7910
  * @brief Create a new ConsumerGroupDescription object.
@@ -7863,6 +7930,7 @@ rd_kafka_ConsumerGroupDescription_new(
7863
7930
  const rd_kafka_AclOperation_t *authorized_operations,
7864
7931
  int authorized_operations_cnt,
7865
7932
  rd_kafka_consumer_group_state_t state,
7933
+ rd_kafka_consumer_group_type_t type,
7866
7934
  const rd_kafka_Node_t *coordinator,
7867
7935
  rd_kafka_error_t *error) {
7868
7936
  rd_kafka_ConsumerGroupDescription_t *grpdesc;
@@ -7886,6 +7954,7 @@ rd_kafka_ConsumerGroupDescription_new(
7886
7954
  authorized_operations, authorized_operations_cnt);
7887
7955
 
7888
7956
  grpdesc->state = state;
7957
+ grpdesc->type = type;
7889
7958
  if (coordinator != NULL)
7890
7959
  grpdesc->coordinator = rd_kafka_Node_copy(coordinator);
7891
7960
  grpdesc->error =
@@ -7908,7 +7977,8 @@ rd_kafka_ConsumerGroupDescription_new_error(const char *group_id,
7908
7977
  rd_kafka_error_t *error) {
7909
7978
  return rd_kafka_ConsumerGroupDescription_new(
7910
7979
  group_id, rd_false, NULL, NULL, NULL, 0,
7911
- RD_KAFKA_CONSUMER_GROUP_STATE_UNKNOWN, NULL, error);
7980
+ RD_KAFKA_CONSUMER_GROUP_STATE_UNKNOWN,
7981
+ RD_KAFKA_CONSUMER_GROUP_TYPE_UNKNOWN, NULL, error);
7912
7982
  }
7913
7983
 
7914
7984
  /**
@@ -7924,7 +7994,8 @@ rd_kafka_ConsumerGroupDescription_copy(
7924
7994
  grpdesc->group_id, grpdesc->is_simple_consumer_group,
7925
7995
  &grpdesc->members, grpdesc->partition_assignor,
7926
7996
  grpdesc->authorized_operations, grpdesc->authorized_operations_cnt,
7927
- grpdesc->state, grpdesc->coordinator, grpdesc->error);
7997
+ grpdesc->state, grpdesc->type, grpdesc->coordinator,
7998
+ grpdesc->error);
7928
7999
  }
7929
8000
 
7930
8001
  /**
@@ -7996,6 +8067,11 @@ const rd_kafka_Node_t *rd_kafka_ConsumerGroupDescription_coordinator(
7996
8067
  return grpdesc->coordinator;
7997
8068
  }
7998
8069
 
8070
+ rd_kafka_consumer_group_type_t rd_kafka_ConsumerGroupDescription_type(
8071
+ const rd_kafka_ConsumerGroupDescription_t *grpdesc) {
8072
+ return grpdesc->type;
8073
+ }
8074
+
7999
8075
  size_t rd_kafka_ConsumerGroupDescription_member_count(
8000
8076
  const rd_kafka_ConsumerGroupDescription_t *grpdesc) {
8001
8077
  return rd_list_cnt(&grpdesc->members);
@@ -8015,51 +8091,6 @@ static int rd_kafka_DescribeConsumerGroups_cmp(const void *a, const void *b) {
8015
8091
  return strcmp(a, b);
8016
8092
  }
8017
8093
 
8018
- /** @brief Merge the DescribeConsumerGroups response from a single broker
8019
- * into the user response list.
8020
- */
8021
- static void rd_kafka_DescribeConsumerGroups_response_merge(
8022
- rd_kafka_op_t *rko_fanout,
8023
- const rd_kafka_op_t *rko_partial) {
8024
- rd_kafka_ConsumerGroupDescription_t *groupres = NULL;
8025
- rd_kafka_ConsumerGroupDescription_t *newgroupres;
8026
- const char *grp = rko_partial->rko_u.admin_result.opaque;
8027
- int orig_pos;
8028
-
8029
- rd_assert(rko_partial->rko_evtype ==
8030
- RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT);
8031
-
8032
- if (!rko_partial->rko_err) {
8033
- /* Proper results.
8034
- * We only send one group per request, make sure it matches */
8035
- groupres =
8036
- rd_list_elem(&rko_partial->rko_u.admin_result.results, 0);
8037
- rd_assert(groupres);
8038
- rd_assert(!strcmp(groupres->group_id, grp));
8039
- newgroupres = rd_kafka_ConsumerGroupDescription_copy(groupres);
8040
- } else {
8041
- /* Op errored, e.g. timeout */
8042
- rd_kafka_error_t *error =
8043
- rd_kafka_error_new(rko_partial->rko_err, NULL);
8044
- newgroupres =
8045
- rd_kafka_ConsumerGroupDescription_new_error(grp, error);
8046
- rd_kafka_error_destroy(error);
8047
- }
8048
-
8049
- /* As a convenience to the application we insert group result
8050
- * in the same order as they were requested. */
8051
- orig_pos = rd_list_index(&rko_fanout->rko_u.admin_request.args, grp,
8052
- rd_kafka_DescribeConsumerGroups_cmp);
8053
- rd_assert(orig_pos != -1);
8054
-
8055
- /* Make sure result is not already set */
8056
- rd_assert(rd_list_elem(&rko_fanout->rko_u.admin_request.fanout.results,
8057
- orig_pos) == NULL);
8058
-
8059
- rd_list_set(&rko_fanout->rko_u.admin_request.fanout.results, orig_pos,
8060
- newgroupres);
8061
- }
8062
-
8063
8094
 
8064
8095
  /**
8065
8096
  * @brief Construct and send DescribeConsumerGroupsRequest to \p rkb
@@ -8112,6 +8143,50 @@ static rd_kafka_resp_err_t rd_kafka_admin_DescribeConsumerGroupsRequest(
8112
8143
  return RD_KAFKA_RESP_ERR_NO_ERROR;
8113
8144
  }
8114
8145
 
8146
+ /**
8147
+ * @brief Construct and send ConsumerGroupDescribeRequest to \p rkb
8148
+ * with the groups (char *) in \p groups, using
8149
+ * \p options.
8150
+ *
8151
+ * The response (unparsed) will be enqueued on \p replyq
8152
+ * for handling by \p resp_cb (with \p opaque passed).
8153
+ *
8154
+ * @returns RD_KAFKA_RESP_ERR_NO_ERROR if the request was enqueued for
8155
+ * transmission, otherwise an error code and errstr will be
8156
+ * updated with a human readable error string.
8157
+ */
8158
+ static rd_kafka_resp_err_t
8159
+ rd_kafka_admin_ConsumerGroupDescribeRequest(rd_kafka_broker_t *rkb,
8160
+ const rd_list_t *groups /*(char*)*/,
8161
+ rd_kafka_AdminOptions_t *options,
8162
+ char *errstr,
8163
+ size_t errstr_size,
8164
+ rd_kafka_replyq_t replyq,
8165
+ rd_kafka_resp_cb_t *resp_cb,
8166
+ void *opaque) {
8167
+
8168
+ int include_authorized_operations;
8169
+ rd_kafka_resp_err_t err;
8170
+ int groups_cnt = rd_list_cnt(groups);
8171
+ rd_kafka_error_t *error = NULL;
8172
+
8173
+ include_authorized_operations =
8174
+ rd_kafka_confval_get_int(&options->include_authorized_operations);
8175
+
8176
+ error = rd_kafka_ConsumerGroupDescribeRequest(
8177
+ rkb, (char **)groups->rl_elems, groups_cnt,
8178
+ include_authorized_operations, replyq, resp_cb, opaque);
8179
+
8180
+ if (error) {
8181
+ rd_snprintf(errstr, errstr_size, "%s",
8182
+ rd_kafka_error_string(error));
8183
+ err = rd_kafka_error_code(error);
8184
+ rd_kafka_error_destroy(error);
8185
+ return err;
8186
+ }
8187
+
8188
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
8189
+ }
8115
8190
  /**
8116
8191
  * @brief Parse DescribeConsumerGroupsResponse and create ADMIN_RESULT op.
8117
8192
  */
@@ -8146,10 +8221,10 @@ rd_kafka_DescribeConsumerGroupsResponse_parse(rd_kafka_op_t *rko_req,
8146
8221
  rd_list_init(&rko_result->rko_u.admin_result.results, cnt,
8147
8222
  rd_kafka_ConsumerGroupDescription_free);
8148
8223
 
8149
- rd_kafka_broker_lock(rkb);
8150
8224
  nodeid = rkb->rkb_nodeid;
8151
- host = rd_strdup(rkb->rkb_origname);
8152
- port = rkb->rkb_port;
8225
+ rd_kafka_broker_lock(rkb);
8226
+ host = rd_strdup(rkb->rkb_origname);
8227
+ port = rkb->rkb_port;
8153
8228
  rd_kafka_broker_unlock(rkb);
8154
8229
 
8155
8230
  node = rd_kafka_Node_new(nodeid, host, port, NULL);
@@ -8248,9 +8323,13 @@ rd_kafka_DescribeConsumerGroupsResponse_parse(rd_kafka_op_t *rko_req,
8248
8323
  client_id = RD_KAFKAP_STR_DUP(&ClientId);
8249
8324
  client_host = RD_KAFKAP_STR_DUP(&ClientHost);
8250
8325
 
8326
+ /* Target Assignment is `NULL` for the `classic`
8327
+ * protocol as there is no concept of Target Assignment
8328
+ * there. */
8251
8329
  member = rd_kafka_MemberDescription_new(
8252
8330
  client_id, member_id, group_instance_id,
8253
- client_host, partitions);
8331
+ client_host, partitions,
8332
+ NULL /* target assignment */);
8254
8333
  if (partitions)
8255
8334
  rd_kafka_topic_partition_list_destroy(
8256
8335
  partitions);
@@ -8279,7 +8358,7 @@ rd_kafka_DescribeConsumerGroupsResponse_parse(rd_kafka_op_t *rko_req,
8279
8358
  group_id, is_simple_consumer_group, &members, proto,
8280
8359
  operations, operation_cnt,
8281
8360
  rd_kafka_consumer_group_state_code(group_state),
8282
- node, error);
8361
+ RD_KAFKA_CONSUMER_GROUP_TYPE_CLASSIC, node, error);
8283
8362
  } else
8284
8363
  grpdesc = rd_kafka_ConsumerGroupDescription_new_error(
8285
8364
  group_id, error);
@@ -8336,6 +8415,325 @@ err_parse:
8336
8415
  return reply->rkbuf_err;
8337
8416
  }
8338
8417
 
8418
+ /**
8419
+ * @brief Parse ConsumerGroupDescriberesponse and create ADMIN_RESULT op.
8420
+ */
8421
+ static rd_kafka_resp_err_t
8422
+ rd_kafka_ConsumerGroupDescribeResponse_parse(rd_kafka_op_t *rko_req,
8423
+ rd_kafka_op_t **rko_resultp,
8424
+ rd_kafka_buf_t *reply,
8425
+ char *errstr,
8426
+ size_t errstr_size) {
8427
+ const int log_decode_errors = LOG_ERR;
8428
+ int32_t groups_cnt;
8429
+ rd_kafka_op_t *rko_result = NULL;
8430
+ rd_kafka_broker_t *rkb = reply->rkbuf_rkb;
8431
+ rd_kafka_error_t *error = NULL;
8432
+ char *group_id = NULL, *group_state = NULL, *assignor_name = NULL,
8433
+ *host = NULL;
8434
+ rd_kafka_AclOperation_t *operations = NULL;
8435
+ rd_kafka_Node_t *node = NULL;
8436
+ rd_kafka_topic_partition_list_t *assignment = NULL,
8437
+ *target_assignment = NULL;
8438
+ int32_t nodeid;
8439
+ uint16_t port;
8440
+ int operation_cnt = -1;
8441
+ int32_t i;
8442
+
8443
+ rd_kafka_buf_read_throttle_time(reply);
8444
+
8445
+ rd_kafka_buf_read_arraycnt(reply, &groups_cnt, RD_KAFKAP_GROUPS_MAX);
8446
+
8447
+ nodeid = rkb->rkb_nodeid;
8448
+ rd_kafka_broker_lock(rkb);
8449
+ host = rd_strdup(rkb->rkb_origname);
8450
+ port = rkb->rkb_port;
8451
+ rd_kafka_broker_unlock(rkb);
8452
+
8453
+ node = rd_kafka_Node_new(nodeid, host, port, NULL);
8454
+
8455
+ rko_result = rd_kafka_admin_result_new(rko_req);
8456
+ rd_list_init(&rko_result->rko_u.admin_result.results, groups_cnt,
8457
+ rd_kafka_ConsumerGroupDescription_free);
8458
+
8459
+ for (i = 0; i < groups_cnt; i++) {
8460
+ int16_t ErrorCode;
8461
+ int32_t authorized_operations = -1;
8462
+ int32_t MemberCnt, j;
8463
+ int32_t GroupEpoch, AssignmentEpoch;
8464
+ rd_kafkap_str_t GroupId, GroupState, AssignorName, ErrorString;
8465
+ rd_list_t members;
8466
+ rd_kafka_ConsumerGroupDescription_t *grpdesc = NULL;
8467
+
8468
+ rd_kafka_buf_read_i16(reply, &ErrorCode);
8469
+ rd_kafka_buf_read_str(reply, &ErrorString);
8470
+ rd_kafka_buf_read_str(reply, &GroupId);
8471
+ rd_kafka_buf_read_str(reply, &GroupState);
8472
+ rd_kafka_buf_read_i32(reply, &GroupEpoch);
8473
+ rd_kafka_buf_read_i32(reply, &AssignmentEpoch);
8474
+ rd_kafka_buf_read_str(reply, &AssignorName);
8475
+ rd_kafka_buf_read_arraycnt(reply, &MemberCnt, 100000);
8476
+
8477
+ group_id = RD_KAFKAP_STR_DUP(&GroupId);
8478
+ group_state = RD_KAFKAP_STR_DUP(&GroupState);
8479
+ assignor_name = RD_KAFKAP_STR_DUP(&AssignorName);
8480
+
8481
+ if (ErrorCode) {
8482
+ error = rd_kafka_error_new(
8483
+ ErrorCode, "ConsumerGroupDescribe: %.*s",
8484
+ RD_KAFKAP_STR_PR(&ErrorString));
8485
+ }
8486
+
8487
+ rd_list_init(&members, MemberCnt,
8488
+ rd_kafka_MemberDescription_free);
8489
+
8490
+ for (j = 0; j < MemberCnt; j++) {
8491
+ char *member_id = NULL, *instance_id = NULL,
8492
+ *client_id = NULL, *client_host = NULL;
8493
+ rd_kafkap_str_t MemberId, InstanceId, RackId, ClientId,
8494
+ ClientHost, SubscribedTopicRegex;
8495
+ int32_t MemberEpoch, idx;
8496
+ rd_kafka_MemberDescription_t *member;
8497
+ int32_t SubscribedTopicNamesArrayCnt;
8498
+
8499
+ rd_kafka_buf_read_str(reply, &MemberId);
8500
+ rd_kafka_buf_read_str(reply, &InstanceId);
8501
+ rd_kafka_buf_read_str(reply, &RackId);
8502
+ rd_kafka_buf_read_i32(reply, &MemberEpoch);
8503
+ rd_kafka_buf_read_str(reply, &ClientId);
8504
+ rd_kafka_buf_read_str(reply, &ClientHost);
8505
+ rd_kafka_buf_read_arraycnt(
8506
+ reply, &SubscribedTopicNamesArrayCnt, 100000);
8507
+
8508
+ for (idx = 0; idx < SubscribedTopicNamesArrayCnt;
8509
+ idx++) {
8510
+ rd_kafkap_str_t SubscribedTopicName;
8511
+ rd_kafka_buf_read_str(reply,
8512
+ &SubscribedTopicName);
8513
+ }
8514
+ rd_kafka_buf_read_str(reply, &SubscribedTopicRegex);
8515
+ const rd_kafka_topic_partition_field_t fields[] = {
8516
+ RD_KAFKA_TOPIC_PARTITION_FIELD_PARTITION,
8517
+ RD_KAFKA_TOPIC_PARTITION_FIELD_END};
8518
+
8519
+ assignment = rd_kafka_buf_read_topic_partitions(
8520
+ reply, rd_true /* use topic_id */,
8521
+ rd_true /* use topic name*/, 0, fields);
8522
+
8523
+ /* Assignment tags */
8524
+ rd_kafka_buf_skip_tags(reply);
8525
+
8526
+ target_assignment = rd_kafka_buf_read_topic_partitions(
8527
+ reply, rd_true /* use topic_id */,
8528
+ rd_true /* use topic name*/, 0, fields);
8529
+
8530
+ /* TargetAssignment tags */
8531
+ rd_kafka_buf_skip_tags(reply);
8532
+
8533
+ /* Member tags */
8534
+ rd_kafka_buf_skip_tags(reply);
8535
+
8536
+ member_id = RD_KAFKAP_STR_DUP(&MemberId);
8537
+ if (!RD_KAFKAP_STR_IS_NULL(&InstanceId)) {
8538
+ instance_id = RD_KAFKAP_STR_DUP(&InstanceId);
8539
+ }
8540
+ client_id = RD_KAFKAP_STR_DUP(&ClientId);
8541
+ client_host = RD_KAFKAP_STR_DUP(&ClientHost);
8542
+
8543
+ member = rd_kafka_MemberDescription_new(
8544
+ client_id, member_id, instance_id, client_host,
8545
+ assignment, target_assignment);
8546
+
8547
+
8548
+ rd_list_add(&members, member);
8549
+
8550
+ RD_IF_FREE(assignment,
8551
+ rd_kafka_topic_partition_list_destroy);
8552
+ RD_IF_FREE(target_assignment,
8553
+ rd_kafka_topic_partition_list_destroy);
8554
+
8555
+ RD_IF_FREE(member_id, rd_free);
8556
+ RD_IF_FREE(instance_id, rd_free);
8557
+ RD_IF_FREE(client_id, rd_free);
8558
+ RD_IF_FREE(client_host, rd_free);
8559
+ member_id = NULL;
8560
+ instance_id = NULL;
8561
+ client_id = NULL;
8562
+ client_host = NULL;
8563
+ }
8564
+ rd_kafka_buf_read_i32(reply, &authorized_operations);
8565
+ operations = rd_kafka_AuthorizedOperations_parse(
8566
+ authorized_operations, &operation_cnt);
8567
+ rd_kafka_buf_skip_tags(reply);
8568
+
8569
+ /* If the error code is Group ID Not Found or Unsupported
8570
+ Version, we will set the ConsumerGroupType to Consumer to
8571
+ identify it for further processing with the old protocol and
8572
+ eventually in rd_kafka_DescribeConsumerGroupsResponse_parse
8573
+ we will set the ConsumerGroupType to Unknown */
8574
+ if (!error) {
8575
+ grpdesc = rd_kafka_ConsumerGroupDescription_new(
8576
+ group_id, rd_false, &members, assignor_name,
8577
+ operations, operation_cnt,
8578
+ rd_kafka_consumer_group_state_code(group_state),
8579
+ RD_KAFKA_CONSUMER_GROUP_TYPE_CONSUMER, node, error);
8580
+ } else {
8581
+ grpdesc = rd_kafka_ConsumerGroupDescription_new_error(
8582
+ group_id, error);
8583
+ }
8584
+
8585
+ rd_list_add(&rko_result->rko_u.admin_result.results, grpdesc);
8586
+
8587
+ rd_list_destroy(&members);
8588
+ rd_free(group_id);
8589
+ rd_free(group_state);
8590
+ rd_free(assignor_name);
8591
+ RD_IF_FREE(error, rd_kafka_error_destroy);
8592
+ RD_IF_FREE(operations, rd_free);
8593
+
8594
+ error = NULL;
8595
+ group_id = NULL;
8596
+ group_state = NULL;
8597
+ assignor_name = NULL;
8598
+ operations = NULL;
8599
+ }
8600
+ rd_kafka_buf_skip_tags(reply);
8601
+ RD_IF_FREE(host, rd_free);
8602
+ RD_IF_FREE(node, rd_kafka_Node_destroy);
8603
+ *rko_resultp = rko_result;
8604
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
8605
+ err_parse:
8606
+ RD_IF_FREE(group_id, rd_free);
8607
+ RD_IF_FREE(group_state, rd_free);
8608
+ RD_IF_FREE(assignor_name, rd_free);
8609
+ RD_IF_FREE(host, rd_free);
8610
+ RD_IF_FREE(node, rd_kafka_Node_destroy);
8611
+ RD_IF_FREE(error, rd_kafka_error_destroy);
8612
+ RD_IF_FREE(operations, rd_free);
8613
+ RD_IF_FREE(assignment, rd_kafka_topic_partition_list_destroy);
8614
+ RD_IF_FREE(target_assignment, rd_kafka_topic_partition_list_destroy);
8615
+ RD_IF_FREE(rko_result, rd_kafka_op_destroy);
8616
+
8617
+ rd_snprintf(
8618
+ errstr, errstr_size,
8619
+ "DescribeConsumerGroups response protocol parse failure: %s",
8620
+ rd_kafka_err2str(reply->rkbuf_err));
8621
+ return reply->rkbuf_err;
8622
+ }
8623
+
8624
+ /**
8625
+ * @brief In case if we get an Unsupported Feature error or if it is a consumer
8626
+ group and we get errors GROUP_ID_NOT_FOUND(69) or
8627
+ UNSUPPORTED_VERSION(35) we need to send a request to the old
8628
+ protocol.
8629
+ */
8630
+ static rd_bool_t rd_kafka_admin_describe_consumer_group_do_fallback_to_classic(
8631
+ rd_kafka_ConsumerGroupDescription_t *groupres) {
8632
+ return groupres->error &&
8633
+ (groupres->error->code == RD_KAFKA_RESP_ERR_GROUP_ID_NOT_FOUND ||
8634
+ groupres->error->code ==
8635
+ RD_KAFKA_RESP_ERR_UNSUPPORTED_VERSION ||
8636
+ groupres->error->code ==
8637
+ RD_KAFKA_RESP_ERR__UNSUPPORTED_FEATURE);
8638
+ }
8639
+
8640
+ static void rd_kafka_admin_describe_consumer_group_request(
8641
+ rd_kafka_op_t *rko_fanout,
8642
+ rd_kafka_t *rk,
8643
+ const char *group_id,
8644
+ const struct rd_kafka_admin_worker_cbs *cbs,
8645
+ const rd_kafka_AdminOptions_t *options,
8646
+ rd_kafka_q_t *rkq) {
8647
+ rd_kafka_op_t *rko = rd_kafka_admin_request_op_new(
8648
+ rk, RD_KAFKA_OP_DESCRIBECONSUMERGROUPS,
8649
+ RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT, cbs, options, rkq);
8650
+
8651
+ rko->rko_u.admin_request.fanout_parent = rko_fanout;
8652
+ rko->rko_u.admin_request.broker_id = RD_KAFKA_ADMIN_TARGET_COORDINATOR;
8653
+ rko->rko_u.admin_request.coordtype = RD_KAFKA_COORD_GROUP;
8654
+ rko->rko_u.admin_request.coordkey = rd_strdup(group_id);
8655
+
8656
+ /* Set the group name as the opaque so the fanout worker use it
8657
+ * to fill in errors.
8658
+ * References rko_fanout's memory, which will always outlive
8659
+ * the fanned out op. */
8660
+ rd_kafka_AdminOptions_set_opaque(&rko->rko_u.admin_request.options,
8661
+ (void *)group_id);
8662
+
8663
+ rd_list_init(&rko->rko_u.admin_request.args, 1, rd_free);
8664
+ rd_list_add(&rko->rko_u.admin_request.args, rd_strdup(group_id));
8665
+
8666
+ rd_kafka_q_enq(rko_fanout->rko_rk->rk_ops, rko);
8667
+ }
8668
+
8669
+ /** @brief Merge the DescribeConsumerGroups response from a single broker
8670
+ * into the user response list.
8671
+ */
8672
+ static void rd_kafka_DescribeConsumerGroups_response_merge(
8673
+ rd_kafka_op_t *rko_fanout,
8674
+ const rd_kafka_op_t *rko_partial) {
8675
+ rd_kafka_ConsumerGroupDescription_t *groupres = NULL;
8676
+ rd_kafka_ConsumerGroupDescription_t *newgroupres;
8677
+ const char *grp = rko_partial->rko_u.admin_result.opaque;
8678
+ int orig_pos;
8679
+
8680
+ rd_assert(rko_partial->rko_evtype ==
8681
+ RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT);
8682
+
8683
+ if (!rko_partial->rko_err) {
8684
+ /* Proper results.
8685
+ * We only send one group per request, make sure it matches */
8686
+ groupres =
8687
+ rd_list_elem(&rko_partial->rko_u.admin_result.results, 0);
8688
+ rd_assert(groupres);
8689
+ rd_assert(!strcmp(groupres->group_id, grp));
8690
+ newgroupres = rd_kafka_ConsumerGroupDescription_copy(groupres);
8691
+ } else {
8692
+ /* Op errored, e.g. timeout */
8693
+ rd_kafka_error_t *error =
8694
+ rd_kafka_error_new(rko_partial->rko_err, NULL);
8695
+ newgroupres =
8696
+ rd_kafka_ConsumerGroupDescription_new_error(grp, error);
8697
+ rd_kafka_error_destroy(error);
8698
+ }
8699
+
8700
+ rd_bool_t is_consumer_group_response =
8701
+ rko_partial->rko_u.admin_result.cbs->request ==
8702
+ rd_kafka_admin_ConsumerGroupDescribeRequest;
8703
+
8704
+ if (is_consumer_group_response &&
8705
+ rd_kafka_admin_describe_consumer_group_do_fallback_to_classic(
8706
+ newgroupres)) {
8707
+ /* We need to send a request to the old protocol */
8708
+ rko_fanout->rko_u.admin_request.fanout.outstanding++;
8709
+ static const struct rd_kafka_admin_worker_cbs cbs = {
8710
+ rd_kafka_admin_DescribeConsumerGroupsRequest,
8711
+ rd_kafka_DescribeConsumerGroupsResponse_parse,
8712
+ };
8713
+ rd_kafka_admin_describe_consumer_group_request(
8714
+ rko_fanout, rko_fanout->rko_rk, grp, &cbs,
8715
+ &rko_fanout->rko_u.admin_request.options,
8716
+ rko_fanout->rko_rk->rk_ops);
8717
+
8718
+ rd_kafka_ConsumerGroupDescription_destroy(newgroupres);
8719
+ } else {
8720
+ /* As a convenience to the application we insert group result
8721
+ * in the same order as they were requested. */
8722
+ orig_pos =
8723
+ rd_list_index(&rko_fanout->rko_u.admin_request.args, grp,
8724
+ rd_kafka_DescribeConsumerGroups_cmp);
8725
+ rd_assert(orig_pos != -1);
8726
+
8727
+ /* Make sure result is not already set */
8728
+ rd_assert(rd_list_elem(
8729
+ &rko_fanout->rko_u.admin_request.fanout.results,
8730
+ orig_pos) == NULL);
8731
+
8732
+ rd_list_set(&rko_fanout->rko_u.admin_request.fanout.results,
8733
+ orig_pos, newgroupres);
8734
+ }
8735
+ }
8736
+
8339
8737
  void rd_kafka_DescribeConsumerGroups(rd_kafka_t *rk,
8340
8738
  const char **groups,
8341
8739
  size_t groups_cnt,
@@ -8405,34 +8803,13 @@ void rd_kafka_DescribeConsumerGroups(rd_kafka_t *rk,
8405
8803
  * coordinator into one op. */
8406
8804
  for (i = 0; i < groups_cnt; i++) {
8407
8805
  static const struct rd_kafka_admin_worker_cbs cbs = {
8408
- rd_kafka_admin_DescribeConsumerGroupsRequest,
8409
- rd_kafka_DescribeConsumerGroupsResponse_parse,
8806
+ rd_kafka_admin_ConsumerGroupDescribeRequest,
8807
+ rd_kafka_ConsumerGroupDescribeResponse_parse,
8410
8808
  };
8411
8809
  char *grp =
8412
8810
  rd_list_elem(&rko_fanout->rko_u.admin_request.args, (int)i);
8413
- rd_kafka_op_t *rko = rd_kafka_admin_request_op_new(
8414
- rk, RD_KAFKA_OP_DESCRIBECONSUMERGROUPS,
8415
- RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT, &cbs, options,
8416
- rk->rk_ops);
8417
-
8418
- rko->rko_u.admin_request.fanout_parent = rko_fanout;
8419
- rko->rko_u.admin_request.broker_id =
8420
- RD_KAFKA_ADMIN_TARGET_COORDINATOR;
8421
- rko->rko_u.admin_request.coordtype = RD_KAFKA_COORD_GROUP;
8422
- rko->rko_u.admin_request.coordkey = rd_strdup(grp);
8423
-
8424
- /* Set the group name as the opaque so the fanout worker use it
8425
- * to fill in errors.
8426
- * References rko_fanout's memory, which will always outlive
8427
- * the fanned out op. */
8428
- rd_kafka_AdminOptions_set_opaque(
8429
- &rko->rko_u.admin_request.options, grp);
8430
-
8431
- rd_list_init(&rko->rko_u.admin_request.args, 1, rd_free);
8432
- rd_list_add(&rko->rko_u.admin_request.args,
8433
- rd_strdup(groups[i]));
8434
-
8435
- rd_kafka_q_enq(rk->rk_ops, rko);
8811
+ rd_kafka_admin_describe_consumer_group_request(
8812
+ rko_fanout, rk, grp, &cbs, options, rk->rk_ops);
8436
8813
  }
8437
8814
  }
8438
8815