@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
@@ -92,69 +92,85 @@ rd_kafka_metadata(rd_kafka_t *rk,
92
92
  rd_kafka_q_t *rkq;
93
93
  rd_kafka_broker_t *rkb;
94
94
  rd_kafka_op_t *rko;
95
+ rd_kafka_resp_err_t err;
95
96
  rd_ts_t ts_end = rd_timeout_init(timeout_ms);
96
97
  rd_list_t topics;
97
98
  rd_bool_t allow_auto_create_topics =
98
99
  rk->rk_conf.allow_auto_create_topics;
99
100
 
100
- /* Query any broker that is up, and if none are up pick the first one,
101
- * if we're lucky it will be up before the timeout */
102
- rkb = rd_kafka_broker_any_usable(rk, timeout_ms, RD_DO_LOCK, 0,
103
- "application metadata request");
104
- if (!rkb)
105
- return RD_KAFKA_RESP_ERR__TRANSPORT;
101
+ do {
102
+ /* Query any broker that is up, and if none are up pick the
103
+ * first one, if we're lucky it will be up before the timeout.
104
+ * Previous decommissioning brokers won't be returned by the
105
+ * function after receiving the _DESTROY_BROKER error
106
+ * below. */
107
+ rkb =
108
+ rd_kafka_broker_any_usable(rk, timeout_ms, RD_DO_LOCK, 0,
109
+ "application metadata request");
110
+ if (!rkb)
111
+ return RD_KAFKA_RESP_ERR__TRANSPORT;
106
112
 
107
- rkq = rd_kafka_q_new(rk);
113
+ rkq = rd_kafka_q_new(rk);
108
114
 
109
- rd_list_init(&topics, 0, rd_free);
110
- if (!all_topics) {
111
- if (only_rkt)
112
- rd_list_add(&topics,
115
+ rd_list_init(&topics, 0, rd_free);
116
+ if (!all_topics) {
117
+ if (only_rkt)
118
+ rd_list_add(
119
+ &topics,
113
120
  rd_strdup(rd_kafka_topic_name(only_rkt)));
114
- else {
115
- int cache_cnt;
116
- rd_kafka_local_topics_to_list(rkb->rkb_rk, &topics,
117
- &cache_cnt);
118
- /* Don't trigger auto-create for cached topics */
119
- if (rd_list_cnt(&topics) == cache_cnt)
120
- allow_auto_create_topics = rd_true;
121
+ else {
122
+ int cache_cnt;
123
+ rd_kafka_local_topics_to_list(
124
+ rkb->rkb_rk, &topics, &cache_cnt);
125
+ /* Don't trigger auto-create
126
+ * for cached topics */
127
+ if (rd_list_cnt(&topics) == cache_cnt)
128
+ allow_auto_create_topics = rd_true;
129
+ }
121
130
  }
122
- }
123
131
 
124
- /* Async: request metadata */
125
- rko = rd_kafka_op_new(RD_KAFKA_OP_METADATA);
126
- rd_kafka_op_set_replyq(rko, rkq, 0);
127
- rko->rko_u.metadata.force = 1; /* Force metadata request regardless
128
- * of outstanding metadata requests. */
129
- rd_kafka_MetadataRequest(rkb, &topics, NULL, "application requested",
130
- allow_auto_create_topics,
131
- /* cgrp_update:
132
- * Only update consumer group state
133
- * on response if this lists all
134
- * topics in the cluster, since a
135
- * partial request may make it seem
136
- * like some subscribed topics are missing. */
137
- all_topics ? rd_true : rd_false,
138
- rd_false /* force_racks */, rko);
132
+ /* Async: request metadata */
133
+ rko = rd_kafka_op_new(RD_KAFKA_OP_METADATA);
134
+ rd_kafka_op_set_replyq(rko, rkq, 0);
135
+ rko->rko_u.metadata.force =
136
+ 1; /* Force metadata request regardless
137
+ * of outstanding metadata requests. */
138
+ rd_kafka_MetadataRequest(
139
+ rkb, &topics, NULL, "application requested",
140
+ allow_auto_create_topics,
141
+ /* cgrp_update:
142
+ * Only update consumer group state
143
+ * on response if this lists all
144
+ * topics in the cluster, since a
145
+ * partial request may make it seem
146
+ * like some subscribed topics are missing. */
147
+ all_topics ? rd_true : rd_false,
148
+ -1 /* same subscription version */,
149
+ rd_false /* force_racks */, rko);
150
+
151
+ rd_list_destroy(&topics);
152
+ rd_kafka_broker_destroy(rkb);
139
153
 
140
- rd_list_destroy(&topics);
141
- rd_kafka_broker_destroy(rkb);
154
+ /* Wait for reply (or timeout) */
155
+ rko = rd_kafka_q_pop(rkq, rd_timeout_remains_us(ts_end), 0);
142
156
 
143
- /* Wait for reply (or timeout) */
144
- rko = rd_kafka_q_pop(rkq, rd_timeout_remains_us(ts_end), 0);
157
+ rd_kafka_q_destroy_owner(rkq);
145
158
 
146
- rd_kafka_q_destroy_owner(rkq);
159
+ /* Timeout */
160
+ if (!rko)
161
+ return RD_KAFKA_RESP_ERR__TIMED_OUT;
147
162
 
148
- /* Timeout */
149
- if (!rko)
150
- return RD_KAFKA_RESP_ERR__TIMED_OUT;
163
+ /* Error */
164
+ err = rko->rko_err;
165
+ if (err) {
166
+ rd_kafka_op_destroy(rko);
167
+ if (err != RD_KAFKA_RESP_ERR__DESTROY_BROKER)
168
+ return err;
169
+ }
151
170
 
152
- /* Error */
153
- if (rko->rko_err) {
154
- rd_kafka_resp_err_t err = rko->rko_err;
155
- rd_kafka_op_destroy(rko);
156
- return err;
157
- }
171
+ /* In case selected broker was decommissioned,
172
+ * try again with a different broker. */
173
+ } while (err == RD_KAFKA_RESP_ERR__DESTROY_BROKER);
158
174
 
159
175
  /* Reply: pass metadata pointer to application who now owns it*/
160
176
  rd_kafka_assert(rk, rko->rko_u.metadata.md);
@@ -391,13 +407,7 @@ static void rd_kafka_parse_Metadata_update_topic(
391
407
  * @locality rdkafka main thread
392
408
  */
393
409
  rd_bool_t rd_kafka_has_reliable_leader_epochs(rd_kafka_broker_t *rkb) {
394
- int features;
395
- int16_t ApiVersion = 0;
396
-
397
- ApiVersion = rd_kafka_broker_ApiVersion_supported(
398
- rkb, RD_KAFKAP_Metadata, 0, 9, &features);
399
-
400
- return ApiVersion >= 9;
410
+ return rd_kafka_broker_ApiVersion_at_least(rkb, RD_KAFKAP_Metadata, 9);
401
411
  }
402
412
 
403
413
  /* Populates the topic partition to rack mapping for the the topic given by
@@ -460,6 +470,71 @@ rd_kafka_populate_metadata_topic_racks(rd_tmpabuf_t *tbuf,
460
470
  }
461
471
  }
462
472
 
473
+ /**
474
+ * @brief Decommission brokers that are not in the metadata.
475
+ */
476
+ static void rd_kafka_metadata_decommission_unavailable_brokers(
477
+ rd_kafka_t *rk,
478
+ rd_kafka_metadata_t *md,
479
+ rd_kafka_broker_t *rkb_current) {
480
+ rd_kafka_broker_t *rkb;
481
+ rd_bool_t has_learned_brokers = rd_false;
482
+ rd_list_t brokers_to_decommission;
483
+ int i;
484
+
485
+ rd_kafka_wrlock(rk);
486
+ TAILQ_FOREACH(rkb, &rk->rk_brokers, rkb_link) {
487
+ if (rkb->rkb_source == RD_KAFKA_LEARNED) {
488
+ has_learned_brokers = rd_true;
489
+ break;
490
+ }
491
+ }
492
+ if (!has_learned_brokers) {
493
+ rd_kafka_wrunlock(rk);
494
+ return;
495
+ }
496
+
497
+ rd_list_init(&brokers_to_decommission,
498
+ rd_atomic32_get(&rk->rk_broker_cnt), NULL);
499
+ TAILQ_FOREACH(rkb, &rk->rk_brokers, rkb_link) {
500
+ rd_bool_t purge_broker;
501
+
502
+ if (rkb->rkb_source == RD_KAFKA_LOGICAL)
503
+ continue;
504
+
505
+ purge_broker = rd_true;
506
+ if (rkb->rkb_source == RD_KAFKA_LEARNED) {
507
+ /* Don't purge the broker if it's available in
508
+ * metadata. */
509
+ for (i = 0; i < md->broker_cnt; i++) {
510
+ if (md->brokers[i].id == rkb->rkb_nodeid) {
511
+ purge_broker = rd_false;
512
+ break;
513
+ }
514
+ }
515
+ }
516
+
517
+ if (!purge_broker)
518
+ continue;
519
+
520
+ /* Don't try to decommission already decommissioning brokers
521
+ * otherwise they could be already destroyed when
522
+ * `rd_kafka_broker_decommission` is called below. */
523
+ if (rd_list_find(&rk->wait_decommissioned_brokers, rkb,
524
+ rd_list_cmp_ptr) != NULL)
525
+ continue;
526
+
527
+ rd_list_add(&brokers_to_decommission, rkb);
528
+ }
529
+ RD_LIST_FOREACH(rkb, &brokers_to_decommission, i) {
530
+ rd_kafka_broker_decommission(rk, rkb,
531
+ &rk->wait_decommissioned_thrds);
532
+ rd_list_add(&rk->wait_decommissioned_brokers, rkb);
533
+ }
534
+ rd_list_destroy(&brokers_to_decommission);
535
+ rd_kafka_wrunlock(rk);
536
+ }
537
+
463
538
  /* Internal implementation for parsing Metadata. */
464
539
  static rd_kafka_resp_err_t
465
540
  rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
@@ -484,12 +559,14 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
484
559
  rd_bool_t cgrp_update = rd_false;
485
560
  rd_bool_t has_reliable_leader_epochs =
486
561
  rd_kafka_has_reliable_leader_epochs(rkb);
487
- int ApiVersion = rkbuf->rkbuf_reqhdr.ApiVersion;
488
- rd_kafkap_str_t cluster_id = RD_ZERO_INIT;
489
- int32_t controller_id = -1;
490
- rd_kafka_resp_err_t err = RD_KAFKA_RESP_ERR_NO_ERROR;
491
- int broker_changes = 0;
492
- int cache_changes = 0;
562
+ int ApiVersion = rkbuf->rkbuf_reqhdr.ApiVersion;
563
+ rd_kafkap_str_t cluster_id = RD_ZERO_INIT;
564
+ int32_t controller_id = -1;
565
+ rd_kafka_resp_err_t err = RD_KAFKA_RESP_ERR_NO_ERROR;
566
+ int broker_changes = 0;
567
+ int cache_changes = 0;
568
+ int cgrp_subscription_version = -1;
569
+ int16_t ErrorCode = 0;
493
570
 
494
571
  /* If client rack is present, the metadata cache (topic or full) needs
495
572
  * to contain the partition to rack map. */
@@ -504,6 +581,8 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
504
581
  cgrp_update =
505
582
  request->rkbuf_u.Metadata.cgrp_update && rk->rk_cgrp;
506
583
  compute_racks |= request->rkbuf_u.Metadata.force_racks;
584
+ cgrp_subscription_version =
585
+ request->rkbuf_u.Metadata.cgrp_subscription_version;
507
586
  }
508
587
 
509
588
  /* If there's reason is NULL, set it to a human-readable string. */
@@ -788,8 +867,21 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
788
867
  ClusterAuthorizedOperations;
789
868
  }
790
869
 
870
+ if (ApiVersion >= 13) {
871
+ rd_kafka_buf_read_i16(rkbuf, &ErrorCode);
872
+ }
873
+
791
874
  rd_kafka_buf_skip_tags(rkbuf);
792
875
 
876
+ if (ErrorCode) {
877
+ rd_rkb_dbg(rkb, METADATA, "METADATA",
878
+ "Metadata response: received top level "
879
+ "error code %" PRId16 ": %s",
880
+ ErrorCode, rd_kafka_err2str(ErrorCode));
881
+ err = ErrorCode;
882
+ goto err;
883
+ }
884
+
793
885
  /* Entire Metadata response now parsed without errors:
794
886
  * update our internal state according to the response. */
795
887
 
@@ -810,6 +902,8 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
810
902
  &md->brokers[i], NULL);
811
903
  }
812
904
 
905
+ rd_kafka_metadata_decommission_unavailable_brokers(rk, md, rkb);
906
+
813
907
  for (i = 0; i < md->topic_cnt; i++) {
814
908
 
815
909
  /* Ignore topics in blacklist */
@@ -854,19 +948,15 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
854
948
  * for all topics or cache entry
855
949
  * already exists. */
856
950
  rd_kafka_wrlock(rk);
857
- cache_changes +=
858
- rd_kafka_metadata_cache_topic_update(
859
- rk, &md->topics[i], &mdi->topics[i],
860
- rd_false /*propagate later*/,
861
- /* use has_client_rack rather than
862
- compute_racks. We need cached rack ids
863
- only in case we need to rejoin the group
864
- if they change and client.rack is set
865
- (KIP-881). */
866
- has_client_rack, mdi->brokers,
867
- md->broker_cnt,
868
- all_topics /*cache entry needs to exist
869
- *if all_topics*/);
951
+ cache_changes += rd_kafka_metadata_cache_topic_update(
952
+ rk, &md->topics[i], &mdi->topics[i],
953
+ rd_false /*propagate later*/,
954
+ /* use has_client_rack rather than
955
+ compute_racks. We need cached rack ids
956
+ only in case we need to rejoin the group
957
+ if they change and client.rack is set
958
+ (KIP-881). */
959
+ has_client_rack, rd_kafka_has_reliable_leader_epochs(rkb));
870
960
  rd_kafka_wrunlock(rk);
871
961
  }
872
962
 
@@ -980,29 +1070,11 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
980
1070
  }
981
1071
 
982
1072
  if (all_topics) {
983
- /* All hints have been replaced by the corresponding entry.
984
- * Rest of hints can be removed as topics aren't present
985
- * in full metadata. */
986
- rd_kafka_metadata_cache_purge_all_hints(rkb->rkb_rk);
987
- if (rkb->rkb_rk->rk_full_metadata)
988
- rd_kafka_metadata_destroy(
989
- &rkb->rkb_rk->rk_full_metadata->metadata);
990
-
991
- /* use has_client_rack rather than compute_racks. We need cached
992
- * rack ids only in case we need to rejoin the group if they
993
- * change and client.rack is set (KIP-881). */
994
- if (has_client_rack)
995
- rkb->rkb_rk->rk_full_metadata =
996
- rd_kafka_metadata_copy_add_racks(mdi, tbuf.of);
997
- else
998
- rkb->rkb_rk->rk_full_metadata =
999
- rd_kafka_metadata_copy(mdi, tbuf.of);
1000
-
1001
1073
  rkb->rkb_rk->rk_ts_full_metadata = rkb->rkb_rk->rk_ts_metadata;
1002
1074
  rd_rkb_dbg(rkb, METADATA, "METADATA",
1003
- "Caching full metadata with "
1004
- "%d broker(s) and %d topic(s): %s",
1005
- md->broker_cnt, md->topic_cnt, reason);
1075
+ "Cached full metadata with "
1076
+ " %d topic(s): %s",
1077
+ md->topic_cnt, reason);
1006
1078
  }
1007
1079
  /* Remove cache hints for the originally requested topics. */
1008
1080
  if (requested_topics)
@@ -1031,10 +1103,17 @@ rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
1031
1103
  * the effective subscription of available topics) as to not
1032
1104
  * propagate non-included topics as non-existent. */
1033
1105
  if (cgrp_update &&
1034
- (requested_topics || requested_topic_ids || all_topics))
1106
+ (all_topics ||
1107
+ ((requested_topics || requested_topic_ids) &&
1108
+ rd_kafka_cgrp_same_subscription_version(
1109
+ rkb->rkb_rk->rk_cgrp, cgrp_subscription_version))))
1035
1110
  rd_kafka_cgrp_metadata_update_check(rkb->rkb_rk->rk_cgrp,
1036
1111
  rd_true /*do join*/);
1037
1112
 
1113
+ if (rk->rk_type == RD_KAFKA_CONSUMER && rk->rk_cgrp &&
1114
+ rk->rk_cgrp->rkcg_group_protocol == RD_KAFKA_GROUP_PROTOCOL_CLASSIC)
1115
+ rd_interval_reset(&rk->rk_cgrp->rkcg_join_intvl);
1116
+
1038
1117
  /* Try to acquire a Producer ID from this broker if we
1039
1118
  * don't have one. */
1040
1119
  if (rd_kafka_is_idempotent(rkb->rkb_rk)) {
@@ -1159,19 +1238,11 @@ rd_kafka_metadata_topic_match(rd_kafka_t *rk,
1159
1238
  rd_kafka_topic_partition_list_t *errored) {
1160
1239
  int ti, i;
1161
1240
  size_t cnt = 0;
1162
- rd_kafka_metadata_internal_t *mdi;
1163
- struct rd_kafka_metadata *metadata;
1164
1241
  rd_kafka_topic_partition_list_t *unmatched;
1242
+ rd_list_t cached_topics;
1243
+ const char *topic;
1165
1244
 
1166
1245
  rd_kafka_rdlock(rk);
1167
- mdi = rk->rk_full_metadata;
1168
- metadata = &mdi->metadata;
1169
-
1170
- if (!mdi) {
1171
- rd_kafka_rdunlock(rk);
1172
- return 0;
1173
- }
1174
-
1175
1246
  /* To keep track of which patterns and topics in `match` that
1176
1247
  * did not match any topic (or matched an errored topic), we
1177
1248
  * create a set of all topics to match in `unmatched` and then
@@ -1182,8 +1253,15 @@ rd_kafka_metadata_topic_match(rd_kafka_t *rk,
1182
1253
 
1183
1254
  /* For each topic in the cluster, scan through the match list
1184
1255
  * to find matching topic. */
1185
- for (ti = 0; ti < metadata->topic_cnt; ti++) {
1186
- const char *topic = metadata->topics[ti].topic;
1256
+ rd_list_init(&cached_topics, rk->rk_metadata_cache.rkmc_cnt, rd_free);
1257
+ rd_kafka_metadata_cache_topics_to_list(rk, &cached_topics, rd_false);
1258
+ RD_LIST_FOREACH(topic, &cached_topics, ti) {
1259
+ const rd_kafka_metadata_topic_internal_t *mdti;
1260
+ const rd_kafka_metadata_topic_t *mdt =
1261
+ rd_kafka_metadata_cache_topic_get(rk, topic, &mdti,
1262
+ rd_true /* valid */);
1263
+ if (!mdt)
1264
+ continue;
1187
1265
 
1188
1266
  /* Ignore topics in blacklist */
1189
1267
  if (rk->rk_conf.topic_blacklist &&
@@ -1201,18 +1279,16 @@ rd_kafka_metadata_topic_match(rd_kafka_t *rk,
1201
1279
  unmatched, match->elems[i].topic,
1202
1280
  RD_KAFKA_PARTITION_UA);
1203
1281
 
1204
- if (metadata->topics[ti].err) {
1282
+ if (mdt->err) {
1205
1283
  rd_kafka_topic_partition_list_add(
1206
1284
  errored, topic, RD_KAFKA_PARTITION_UA)
1207
- ->err = metadata->topics[ti].err;
1285
+ ->err = mdt->err;
1208
1286
  continue; /* Skip errored topics */
1209
1287
  }
1210
1288
 
1211
- rd_list_add(tinfos,
1212
- rd_kafka_topic_info_new_with_rack(
1213
- topic,
1214
- metadata->topics[ti].partition_cnt,
1215
- mdi->topics[ti].partitions));
1289
+ rd_list_add(tinfos, rd_kafka_topic_info_new_with_rack(
1290
+ topic, mdt->partition_cnt,
1291
+ mdti->partitions));
1216
1292
 
1217
1293
  cnt++;
1218
1294
  }
@@ -1230,6 +1306,7 @@ rd_kafka_metadata_topic_match(rd_kafka_t *rk,
1230
1306
  }
1231
1307
 
1232
1308
  rd_kafka_topic_partition_list_destroy(unmatched);
1309
+ rd_list_destroy(&cached_topics);
1233
1310
 
1234
1311
  return cnt;
1235
1312
  }
@@ -1347,6 +1424,7 @@ rd_kafka_metadata_refresh_topics(rd_kafka_t *rk,
1347
1424
  rd_bool_t force,
1348
1425
  rd_bool_t allow_auto_create,
1349
1426
  rd_bool_t cgrp_update,
1427
+ int32_t cgrp_subscription_version,
1350
1428
  const char *reason) {
1351
1429
  rd_list_t q_topics;
1352
1430
  int destroy_rkb = 0;
@@ -1365,8 +1443,7 @@ rd_kafka_metadata_refresh_topics(rd_kafka_t *rk,
1365
1443
  * these topics so that they will be included in
1366
1444
  * a future all known_topics query. */
1367
1445
  rd_kafka_metadata_cache_hint(rk, topics, NULL,
1368
- RD_KAFKA_RESP_ERR__NOENT,
1369
- 0 /*dont replace*/);
1446
+ RD_KAFKA_RESP_ERR__NOENT);
1370
1447
 
1371
1448
  rd_kafka_wrunlock(rk);
1372
1449
  rd_kafka_dbg(rk, METADATA, "METADATA",
@@ -1387,8 +1464,7 @@ rd_kafka_metadata_refresh_topics(rd_kafka_t *rk,
1387
1464
  * out any topics that are already being requested.
1388
1465
  * q_topics will contain remaining topics to query. */
1389
1466
  rd_kafka_metadata_cache_hint(rk, topics, &q_topics,
1390
- RD_KAFKA_RESP_ERR__WAIT_CACHE,
1391
- rd_false /*dont replace*/);
1467
+ RD_KAFKA_RESP_ERR__WAIT_CACHE);
1392
1468
  rd_kafka_wrunlock(rk);
1393
1469
 
1394
1470
  if (rd_list_cnt(&q_topics) == 0) {
@@ -1413,9 +1489,9 @@ rd_kafka_metadata_refresh_topics(rd_kafka_t *rk,
1413
1489
  "Requesting metadata for %d/%d topics: %s",
1414
1490
  rd_list_cnt(&q_topics), rd_list_cnt(topics), reason);
1415
1491
 
1416
- rd_kafka_MetadataRequest(rkb, &q_topics, NULL, reason,
1417
- allow_auto_create, cgrp_update,
1418
- rd_false /* force_racks */, NULL);
1492
+ rd_kafka_MetadataRequest(
1493
+ rkb, &q_topics, NULL, reason, allow_auto_create, cgrp_update,
1494
+ cgrp_subscription_version, rd_false /* force_racks */, NULL);
1419
1495
 
1420
1496
  rd_list_destroy(&q_topics);
1421
1497
 
@@ -1464,7 +1540,7 @@ rd_kafka_metadata_refresh_known_topics(rd_kafka_t *rk,
1464
1540
  else
1465
1541
  err = rd_kafka_metadata_refresh_topics(
1466
1542
  rk, rkb, &topics, force, allow_auto_create_topics,
1467
- rd_false /*!cgrp_update*/, reason);
1543
+ rd_false /*!cgrp_update*/, -1, reason);
1468
1544
 
1469
1545
  rd_list_destroy(&topics);
1470
1546
 
@@ -1504,7 +1580,8 @@ rd_kafka_metadata_refresh_consumer_topics(rd_kafka_t *rk,
1504
1580
  rkcg = rk->rk_cgrp;
1505
1581
  rd_assert(rkcg != NULL);
1506
1582
 
1507
- if (rkcg->rkcg_flags & RD_KAFKA_CGRP_F_WILDCARD_SUBSCRIPTION) {
1583
+ if (rkcg->rkcg_group_protocol == RD_KAFKA_GROUP_PROTOCOL_CLASSIC &&
1584
+ rkcg->rkcg_flags & RD_KAFKA_CGRP_F_WILDCARD_SUBSCRIPTION) {
1508
1585
  /* If there is a wildcard subscription we need to request
1509
1586
  * all topics in the cluster so that we can perform
1510
1587
  * regexp matching. */
@@ -1530,7 +1607,8 @@ rd_kafka_metadata_refresh_consumer_topics(rd_kafka_t *rk,
1530
1607
  else
1531
1608
  err = rd_kafka_metadata_refresh_topics(
1532
1609
  rk, rkb, &topics, rd_true /*force*/,
1533
- allow_auto_create_topics, rd_true /*cgrp_update*/, reason);
1610
+ allow_auto_create_topics, rd_true /*cgrp_update*/,
1611
+ rd_atomic32_get(&rkcg->rkcg_subscription_version), reason);
1534
1612
 
1535
1613
  rd_list_destroy(&topics);
1536
1614
 
@@ -1557,8 +1635,9 @@ rd_kafka_resp_err_t rd_kafka_metadata_refresh_brokers(rd_kafka_t *rk,
1557
1635
  const char *reason) {
1558
1636
  return rd_kafka_metadata_request(rk, rkb, NULL /*brokers only*/,
1559
1637
  rd_false /*!allow auto create topics*/,
1560
- rd_false /*no cgrp update */, reason,
1561
- NULL);
1638
+ rd_false /*no cgrp update */,
1639
+ -1 /* same subscription version */,
1640
+ reason, NULL);
1562
1641
  }
1563
1642
 
1564
1643
 
@@ -1592,7 +1671,8 @@ rd_kafka_resp_err_t rd_kafka_metadata_refresh_all(rd_kafka_t *rk,
1592
1671
  rd_list_init(&topics, 0, NULL); /* empty list = all topics */
1593
1672
  rd_kafka_MetadataRequest(
1594
1673
  rkb, &topics, NULL, reason, rd_false /*no auto create*/,
1595
- rd_true /*cgrp update*/, rd_false /* force_rack */, NULL);
1674
+ rd_true /*cgrp update*/, -1 /* same subscription version */,
1675
+ rd_false /* force_rack */, NULL);
1596
1676
  rd_list_destroy(&topics);
1597
1677
 
1598
1678
  if (destroy_rkb)
@@ -1618,6 +1698,7 @@ rd_kafka_metadata_request(rd_kafka_t *rk,
1618
1698
  const rd_list_t *topics,
1619
1699
  rd_bool_t allow_auto_create_topics,
1620
1700
  rd_bool_t cgrp_update,
1701
+ int32_t cgrp_subscription_version,
1621
1702
  const char *reason,
1622
1703
  rd_kafka_op_t *rko) {
1623
1704
  int destroy_rkb = 0;
@@ -1629,9 +1710,9 @@ rd_kafka_metadata_request(rd_kafka_t *rk,
1629
1710
  destroy_rkb = 1;
1630
1711
  }
1631
1712
 
1632
- rd_kafka_MetadataRequest(rkb, topics, NULL, reason,
1633
- allow_auto_create_topics, cgrp_update,
1634
- rd_false /* force racks */, rko);
1713
+ rd_kafka_MetadataRequest(
1714
+ rkb, topics, NULL, reason, allow_auto_create_topics, cgrp_update,
1715
+ cgrp_subscription_version, rd_false /* force racks */, rko);
1635
1716
 
1636
1717
  if (destroy_rkb)
1637
1718
  rd_kafka_broker_destroy(rkb);
@@ -1695,7 +1776,7 @@ static void rd_kafka_metadata_leader_query_tmr_cb(rd_kafka_timers_t *rkts,
1695
1776
  rd_kafka_metadata_refresh_topics(
1696
1777
  rk, NULL, &topics, rd_true /*force*/,
1697
1778
  rk->rk_conf.allow_auto_create_topics,
1698
- rd_false /*!cgrp_update*/, "partition leader query");
1779
+ rd_false /*!cgrp_update*/, -1, "partition leader query");
1699
1780
 
1700
1781
  /* Back off next query exponentially till we reach
1701
1782
  * the retry backoff max ms */
@@ -1716,16 +1797,19 @@ static void rd_kafka_metadata_leader_query_tmr_cb(rd_kafka_timers_t *rkts,
1716
1797
  * exponentially increased intervals until no topics are missing
1717
1798
  * leaders.
1718
1799
  *
1800
+ * @param force If true, run the query immediately without waiting for the
1801
+ * interval.
1802
+ *
1719
1803
  * @locks none
1720
1804
  * @locality any
1721
1805
  */
1722
- void rd_kafka_metadata_fast_leader_query(rd_kafka_t *rk) {
1806
+ void rd_kafka_metadata_fast_leader_query(rd_kafka_t *rk, rd_bool_t force) {
1723
1807
  rd_ts_t next;
1724
1808
 
1725
- /* Restart the timer if it will speed things up. */
1809
+ /* Restart the timer if it will speed things up, or if forced. */
1726
1810
  next = rd_kafka_timer_next(
1727
1811
  &rk->rk_timers, &rk->rk_metadata_cache.rkmc_query_tmr, 1 /*lock*/);
1728
- if (next == -1 /* not started */ ||
1812
+ if (force || next == -1 /* not started */ ||
1729
1813
  next >
1730
1814
  (rd_ts_t)rk->rk_conf.metadata_refresh_fast_interval_ms * 1000) {
1731
1815
  rd_kafka_dbg(rk, METADATA | RD_KAFKA_DBG_TOPIC, "FASTQUERY",
@@ -2067,7 +2151,8 @@ rd_kafka_metadata_update_op(rd_kafka_t *rk, rd_kafka_metadata_internal_t *mdi) {
2067
2151
  .partitions[part]
2068
2152
  .leader_epoch;
2069
2153
 
2070
- if (current_leader_epoch >= mdpi->leader_epoch) {
2154
+ if (mdpi->leader_epoch != -1 &&
2155
+ current_leader_epoch > mdpi->leader_epoch) {
2071
2156
  rd_kafka_broker_destroy(rkb);
2072
2157
  rd_kafka_dbg(
2073
2158
  rk, METADATA, "METADATAUPDATE",
@@ -147,6 +147,7 @@ rd_kafka_metadata_refresh_topics(rd_kafka_t *rk,
147
147
  rd_bool_t force,
148
148
  rd_bool_t allow_auto_create,
149
149
  rd_bool_t cgrp_update,
150
+ int32_t cgrp_subscription_version,
150
151
  const char *reason);
151
152
  rd_kafka_resp_err_t
152
153
  rd_kafka_metadata_refresh_known_topics(rd_kafka_t *rk,
@@ -170,6 +171,7 @@ rd_kafka_metadata_request(rd_kafka_t *rk,
170
171
  const rd_list_t *topics,
171
172
  rd_bool_t allow_auto_create_topics,
172
173
  rd_bool_t cgrp_update,
174
+ int32_t cgrp_subscription_version,
173
175
  const char *reason,
174
176
  rd_kafka_op_t *rko);
175
177
 
@@ -281,9 +283,7 @@ int rd_kafka_metadata_cache_topic_update(
281
283
  const rd_kafka_metadata_topic_internal_t *mdit,
282
284
  rd_bool_t propagate,
283
285
  rd_bool_t include_metadata,
284
- rd_kafka_metadata_broker_internal_t *brokers,
285
- size_t broker_cnt,
286
- rd_bool_t only_existing);
286
+ rd_bool_t has_reliable_leader_epochs);
287
287
  void rd_kafka_metadata_cache_propagate_changes(rd_kafka_t *rk);
288
288
  struct rd_kafka_metadata_cache_entry *
289
289
  rd_kafka_metadata_cache_find(rd_kafka_t *rk, const char *topic, int valid);
@@ -298,21 +298,23 @@ void rd_kafka_metadata_cache_purge_hints_by_id(rd_kafka_t *rk,
298
298
  int rd_kafka_metadata_cache_hint(rd_kafka_t *rk,
299
299
  const rd_list_t *topics,
300
300
  rd_list_t *dst,
301
- rd_kafka_resp_err_t err,
302
- rd_bool_t replace);
301
+ rd_kafka_resp_err_t err);
303
302
 
304
303
  int rd_kafka_metadata_cache_hint_rktparlist(
305
304
  rd_kafka_t *rk,
306
305
  const rd_kafka_topic_partition_list_t *rktparlist,
307
- rd_list_t *dst,
308
- int replace);
306
+ rd_list_t *dst);
309
307
 
310
- const rd_kafka_metadata_topic_t *
311
- rd_kafka_metadata_cache_topic_get(rd_kafka_t *rk, const char *topic, int valid);
308
+ const rd_kafka_metadata_topic_t *rd_kafka_metadata_cache_topic_get(
309
+ rd_kafka_t *rk,
310
+ const char *topic,
311
+ const rd_kafka_metadata_topic_internal_t **mdtip,
312
+ int valid);
312
313
  int rd_kafka_metadata_cache_topic_partition_get(
313
314
  rd_kafka_t *rk,
314
315
  const rd_kafka_metadata_topic_t **mtopicp,
315
316
  const rd_kafka_metadata_partition_t **mpartp,
317
+ const rd_kafka_metadata_partition_internal_t **mdpip,
316
318
  const char *topic,
317
319
  int32_t partition,
318
320
  int valid);
@@ -321,7 +323,7 @@ int rd_kafka_metadata_cache_topics_count_exists(rd_kafka_t *rk,
321
323
  const rd_list_t *topics,
322
324
  int *metadata_agep);
323
325
 
324
- void rd_kafka_metadata_fast_leader_query(rd_kafka_t *rk);
326
+ void rd_kafka_metadata_fast_leader_query(rd_kafka_t *rk, rd_bool_t force);
325
327
 
326
328
  void rd_kafka_metadata_cache_init(rd_kafka_t *rk);
327
329
  void rd_kafka_metadata_cache_destroy(rd_kafka_t *rk);
@@ -329,7 +331,9 @@ void rd_kafka_metadata_cache_purge(rd_kafka_t *rk, rd_bool_t purge_observers);
329
331
  int rd_kafka_metadata_cache_wait_change(rd_kafka_t *rk, int timeout_ms);
330
332
  void rd_kafka_metadata_cache_dump(FILE *fp, rd_kafka_t *rk);
331
333
 
332
- int rd_kafka_metadata_cache_topics_to_list(rd_kafka_t *rk, rd_list_t *topics);
334
+ int rd_kafka_metadata_cache_topics_to_list(rd_kafka_t *rk,
335
+ rd_list_t *topics,
336
+ rd_bool_t exclude_valid);
333
337
 
334
338
  void rd_kafka_metadata_cache_wait_state_change_async(
335
339
  rd_kafka_t *rk,