@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
@@ -354,6 +354,7 @@ rd_kafka_topic_t *rd_kafka_topic_new0(rd_kafka_t *rk,
354
354
  rkt->rkt_rk = rk;
355
355
 
356
356
  rkt->rkt_ts_create = rd_clock();
357
+ rkt->rkt_ts_state = rkt->rkt_ts_create;
357
358
 
358
359
  rkt->rkt_conf = *conf;
359
360
  rd_free(conf); /* explicitly not rd_kafka_topic_destroy()
@@ -538,7 +539,7 @@ rd_kafka_topic_t *rd_kafka_topic_new(rd_kafka_t *rk,
538
539
 
539
540
  /* Query for the topic leader (async) */
540
541
  if (!existing)
541
- rd_kafka_topic_leader_query(rk, rkt);
542
+ rd_kafka_topic_fast_leader_query(rk, rd_true /* force */);
542
543
 
543
544
  /* Drop our reference since there is already/now an app refcnt */
544
545
  rd_kafka_topic_destroy0(rkt);
@@ -565,7 +566,8 @@ static void rd_kafka_topic_set_state(rd_kafka_topic_t *rkt, int state) {
565
566
  if (rkt->rkt_state == RD_KAFKA_TOPIC_S_ERROR)
566
567
  rkt->rkt_err = RD_KAFKA_RESP_ERR_NO_ERROR;
567
568
 
568
- rkt->rkt_state = state;
569
+ rkt->rkt_state = state;
570
+ rkt->rkt_ts_state = rd_clock();
569
571
  }
570
572
 
571
573
  /**
@@ -643,6 +645,7 @@ int rd_kafka_toppar_broker_update(rd_kafka_toppar_t *rktp,
643
645
  * @remark If a toppar is currently delegated to a preferred replica,
644
646
  * it will not be delegated to the leader broker unless there
645
647
  * has been a leader change.
648
+ * @remark The new leader, if present, should not be terminating.
646
649
  *
647
650
  * @param leader_id The id of the new leader broker.
648
651
  * @param leader A reference to the leader broker or NULL if the
@@ -663,7 +666,8 @@ static int rd_kafka_toppar_leader_update(rd_kafka_topic_t *rkt,
663
666
  int32_t leader_epoch) {
664
667
  rd_kafka_toppar_t *rktp;
665
668
  rd_bool_t need_epoch_validation = rd_false;
666
- int r = 0;
669
+ rd_bool_t fetching_from_follower;
670
+ int r = 0;
667
671
 
668
672
  rktp = rd_kafka_toppar_get(rkt, partition, 0);
669
673
  if (unlikely(!rktp)) {
@@ -681,7 +685,11 @@ static int rd_kafka_toppar_leader_update(rd_kafka_topic_t *rkt,
681
685
 
682
686
  rd_kafka_toppar_lock(rktp);
683
687
 
684
- if (leader_epoch < rktp->rktp_leader_epoch) {
688
+ /* -1 (null) is excluded to allow to switch back to a
689
+ * leader not supporting KIP-320 still, for example
690
+ * during a cluster roll for upgrading brokers to
691
+ * a version supporting that KIP. */
692
+ if (leader_epoch != -1 && leader_epoch < rktp->rktp_leader_epoch) {
685
693
  rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
686
694
  "%s [%" PRId32
687
695
  "]: ignoring outdated metadata update with "
@@ -691,81 +699,69 @@ static int rd_kafka_toppar_leader_update(rd_kafka_topic_t *rkt,
691
699
  rktp->rktp_rkt->rkt_topic->str,
692
700
  rktp->rktp_partition, leader_epoch,
693
701
  rktp->rktp_leader_epoch);
694
- if (rktp->rktp_fetch_state !=
695
- RD_KAFKA_TOPPAR_FETCH_VALIDATE_EPOCH_WAIT) {
696
- rd_kafka_toppar_unlock(rktp);
697
- rd_kafka_toppar_destroy(rktp); /* from get() */
698
- return 0;
699
- }
702
+ rd_kafka_toppar_unlock(rktp);
703
+ rd_kafka_toppar_destroy(rktp); /* from get() */
704
+ return 0;
700
705
  }
701
706
 
702
- if (rktp->rktp_leader_epoch == -1 ||
703
- leader_epoch > rktp->rktp_leader_epoch) {
704
- rd_bool_t fetching_from_follower;
705
- rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
706
- "%s [%" PRId32 "]: leader %" PRId32
707
- " epoch %" PRId32 " -> leader %" PRId32
708
- " epoch %" PRId32,
709
- rktp->rktp_rkt->rkt_topic->str,
710
- rktp->rktp_partition, rktp->rktp_leader_id,
711
- rktp->rktp_leader_epoch, leader_id, leader_epoch);
712
- if (leader_epoch > rktp->rktp_leader_epoch)
713
- rktp->rktp_leader_epoch = leader_epoch;
707
+ rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
708
+ "%s [%" PRId32 "]: leader %" PRId32 " epoch %" PRId32
709
+ " -> leader %" PRId32 " epoch %" PRId32,
710
+ rktp->rktp_rkt->rkt_topic->str, rktp->rktp_partition,
711
+ rktp->rktp_leader_id, rktp->rktp_leader_epoch, leader_id,
712
+ leader_epoch);
713
+
714
+ if (leader_epoch > rktp->rktp_leader_epoch ||
715
+ rktp->rktp_fetch_state ==
716
+ RD_KAFKA_TOPPAR_FETCH_VALIDATE_EPOCH_WAIT) {
717
+ /* Epoch increased and needs to be validated (leader_epoch > -1)
718
+ * or we need to complete the validation. */
714
719
  need_epoch_validation = rd_true;
720
+ }
715
721
 
722
+ rktp->rktp_leader_epoch = leader_epoch;
716
723
 
717
- fetching_from_follower =
718
- leader != NULL && rktp->rktp_broker != NULL &&
719
- rktp->rktp_broker->rkb_source != RD_KAFKA_INTERNAL &&
720
- rktp->rktp_broker != leader;
721
-
722
- if (fetching_from_follower &&
723
- rktp->rktp_leader_id == leader_id) {
724
- rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
725
- "Topic %s [%" PRId32 "]: leader %" PRId32
726
- " unchanged, "
727
- "not migrating away from preferred "
728
- "replica %" PRId32,
729
- rktp->rktp_rkt->rkt_topic->str,
730
- rktp->rktp_partition, leader_id,
731
- rktp->rktp_broker_id);
732
- r = 0;
724
+ fetching_from_follower =
725
+ leader != NULL && rktp->rktp_broker != NULL &&
726
+ rktp->rktp_broker->rkb_source != RD_KAFKA_INTERNAL &&
727
+ rktp->rktp_broker != leader;
733
728
 
734
- } else {
729
+ if (fetching_from_follower && rktp->rktp_leader_id == leader_id) {
730
+ rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
731
+ "Topic %s [%" PRId32 "]: leader %" PRId32
732
+ " unchanged, "
733
+ "not migrating away from preferred "
734
+ "replica %" PRId32,
735
+ rktp->rktp_rkt->rkt_topic->str,
736
+ rktp->rktp_partition, leader_id,
737
+ rktp->rktp_broker_id);
738
+ r = 0;
735
739
 
736
- if (rktp->rktp_leader_id != leader_id ||
737
- rktp->rktp_leader != leader) {
738
- /* Update leader if it has changed */
739
- rktp->rktp_leader_id = leader_id;
740
- if (rktp->rktp_leader)
741
- rd_kafka_broker_destroy(
742
- rktp->rktp_leader);
743
- if (leader)
744
- rd_kafka_broker_keep(leader);
745
- rktp->rktp_leader = leader;
746
- }
740
+ } else {
747
741
 
748
- /* Update handling broker */
749
- r = rd_kafka_toppar_broker_update(
750
- rktp, leader_id, leader, "leader updated");
742
+ if (rktp->rktp_leader_id != leader_id ||
743
+ rktp->rktp_leader != leader) {
744
+ /* Update leader if it has changed */
745
+ rktp->rktp_leader_id = leader_id;
746
+ if (rktp->rktp_leader)
747
+ rd_kafka_broker_destroy(rktp->rktp_leader);
748
+ if (leader)
749
+ rd_kafka_broker_keep(leader);
750
+ rktp->rktp_leader = leader;
751
751
  }
752
752
 
753
- } else if (rktp->rktp_fetch_state ==
754
- RD_KAFKA_TOPPAR_FETCH_VALIDATE_EPOCH_WAIT)
755
- need_epoch_validation = rd_true;
753
+ /* Update handling broker */
754
+ r = rd_kafka_toppar_broker_update(rktp, leader_id, leader,
755
+ "leader updated");
756
+ }
756
757
 
757
758
  if (need_epoch_validation) {
758
759
  /* Set offset validation position,
759
760
  * depending it if should continue with current position or
760
761
  * with next fetch start position. */
761
- if (rd_kafka_toppar_fetch_decide_start_from_next_fetch_start(
762
- rktp)) {
763
- rd_kafka_toppar_set_offset_validation_position(
764
- rktp, rktp->rktp_next_fetch_start);
765
- } else {
766
- rd_kafka_toppar_set_offset_validation_position(
767
- rktp, rktp->rktp_offsets.fetch_pos);
768
- }
762
+ rd_kafka_toppar_set_offset_validation_position(
763
+ rktp,
764
+ rd_kafka_toppar_fetch_decide_next_fetch_start_pos(rktp));
769
765
  rd_kafka_offset_validate(rktp, "epoch updated from metadata");
770
766
  }
771
767
 
@@ -794,7 +790,12 @@ int rd_kafka_toppar_delegate_to_leader(rd_kafka_toppar_t *rktp) {
794
790
  rd_kafka_rdlock(rktp->rktp_rkt->rkt_rk);
795
791
  rd_kafka_toppar_lock(rktp);
796
792
 
797
- rd_assert(rktp->rktp_leader_id != rktp->rktp_broker_id);
793
+ if (rktp->rktp_leader_id == rktp->rktp_broker_id) {
794
+ /* Given lock was released we need to check again */
795
+ rd_kafka_toppar_unlock(rktp);
796
+ rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
797
+ return 0;
798
+ }
798
799
 
799
800
  rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
800
801
  "Topic %s [%" PRId32
@@ -822,6 +823,45 @@ int rd_kafka_toppar_delegate_to_leader(rd_kafka_toppar_t *rktp) {
822
823
  }
823
824
 
824
825
 
826
+ /**
827
+ * @brief Forgets current rktp leader, to reduce reference count
828
+ * and allow the broker to be destroyed.
829
+ *
830
+ * @locks none
831
+ * @locks_acquired rk rdlock, rktp
832
+ * @locality any
833
+ */
834
+ void rd_kafka_toppar_forget_leader(rd_kafka_toppar_t *rktp) {
835
+ rd_kafka_rdlock(rktp->rktp_rkt->rkt_rk);
836
+ rd_kafka_toppar_lock(rktp);
837
+
838
+ if (rktp->rktp_leader) {
839
+ rd_kafka_broker_destroy(rktp->rktp_leader);
840
+ rktp->rktp_leader = NULL;
841
+ rktp->rktp_leader_id = -1;
842
+ rktp->rktp_leader_epoch = -1;
843
+ }
844
+
845
+ rd_kafka_toppar_unlock(rktp);
846
+ rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
847
+ }
848
+
849
+ /**
850
+ * @brief Revert the topic+partition delegation to the internal broker.
851
+ *
852
+ * @locks none
853
+ * @locks_acquired rk rdlock, rktp
854
+ * @locality any
855
+ */
856
+ void rd_kafka_toppar_undelegate(rd_kafka_toppar_t *rktp) {
857
+ rd_kafka_rdlock(rktp->rktp_rkt->rkt_rk);
858
+ rd_kafka_toppar_lock(rktp);
859
+
860
+ rd_kafka_toppar_broker_delegate(rktp, NULL);
861
+
862
+ rd_kafka_toppar_unlock(rktp);
863
+ rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
864
+ }
825
865
 
826
866
  /**
827
867
  * @brief Save idempotent producer state for a partition that is about to
@@ -1188,11 +1228,14 @@ rd_bool_t rd_kafka_topic_set_notexists(rd_kafka_topic_t *rkt,
1188
1228
  rd_assert(err != RD_KAFKA_RESP_ERR_NO_ERROR);
1189
1229
 
1190
1230
  remains_us =
1191
- (rkt->rkt_ts_create +
1231
+ (rkt->rkt_ts_state +
1192
1232
  (rkt->rkt_rk->rk_conf.metadata_propagation_max_ms * 1000)) -
1193
1233
  rkt->rkt_ts_metadata;
1194
1234
 
1195
- if (!permanent && rkt->rkt_state == RD_KAFKA_TOPIC_S_UNKNOWN &&
1235
+ if (!permanent &&
1236
+ (rkt->rkt_state == RD_KAFKA_TOPIC_S_UNKNOWN ||
1237
+ rkt->rkt_state == RD_KAFKA_TOPIC_S_ERROR ||
1238
+ rkt->rkt_state == RD_KAFKA_TOPIC_S_EXISTS) &&
1196
1239
  remains_us > 0) {
1197
1240
  /* Still allowing topic metadata to propagate. */
1198
1241
  rd_kafka_dbg(
@@ -1220,6 +1263,47 @@ rd_bool_t rd_kafka_topic_set_notexists(rd_kafka_topic_t *rkt,
1220
1263
  return rd_true;
1221
1264
  }
1222
1265
 
1266
+ /**
1267
+ * @brief Mark topic as existent, unless metadata propagation configuration
1268
+ * disallows it.
1269
+ *
1270
+ * @returns true if the topic was marked as existent, else false.
1271
+ *
1272
+ * @locks topic_wrlock() MUST be held.
1273
+ */
1274
+ rd_bool_t rd_kafka_topic_set_exists(rd_kafka_topic_t *rkt,
1275
+ rd_kafka_Uuid_t topic_id) {
1276
+ rd_ts_t remains_us;
1277
+
1278
+ if (unlikely(rd_kafka_terminating(rkt->rkt_rk))) {
1279
+ /* Dont update metadata while terminating. */
1280
+ return rd_false;
1281
+ }
1282
+
1283
+ remains_us =
1284
+ (rkt->rkt_ts_state +
1285
+ (rkt->rkt_rk->rk_conf.metadata_propagation_max_ms * 1000)) -
1286
+ rkt->rkt_ts_metadata;
1287
+
1288
+ if (/* Same topic id */
1289
+ rd_kafka_Uuid_cmp(rkt->rkt_topic_id, topic_id) == 0 &&
1290
+ rkt->rkt_state == RD_KAFKA_TOPIC_S_NOTEXISTS && remains_us > 0) {
1291
+ /* Still allowing topic metadata to propagate. */
1292
+ rd_kafka_dbg(
1293
+ rkt->rkt_rk, TOPIC | RD_KAFKA_DBG_METADATA, "TOPICPROP",
1294
+ "Topic %.*s exists after being deleted, "
1295
+ " allowing %dms for metadata propagation before marking "
1296
+ "topic "
1297
+ "as existent",
1298
+ RD_KAFKAP_STR_PR(rkt->rkt_topic), (int)(remains_us / 1000));
1299
+ return rd_false;
1300
+ }
1301
+
1302
+ rd_kafka_topic_set_state(rkt, RD_KAFKA_TOPIC_S_EXISTS);
1303
+
1304
+ return rd_true;
1305
+ }
1306
+
1223
1307
  /**
1224
1308
  * @brief Mark topic as errored, such as when topic authorization fails.
1225
1309
  *
@@ -1327,18 +1411,24 @@ rd_kafka_topic_metadata_update(rd_kafka_topic_t *rkt,
1327
1411
  mdt->err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART ||
1328
1412
  mdt->err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_ID)
1329
1413
  rd_kafka_topic_set_notexists(rkt, mdt->err);
1330
- else if (mdt->partition_cnt > 0)
1331
- rd_kafka_topic_set_state(rkt, RD_KAFKA_TOPIC_S_EXISTS);
1332
- else if (mdt->err)
1414
+ else if (mdt->err == RD_KAFKA_RESP_ERR_NO_ERROR &&
1415
+ mdt->partition_cnt > 0)
1416
+ rd_kafka_topic_set_exists(rkt, mdit->topic_id);
1417
+ else if (mdt->err == RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED)
1418
+ /* Only set an error when it's permanent and it needs
1419
+ * to be surfaced to the application. */
1333
1420
  rd_kafka_topic_set_error(rkt, mdt->err);
1334
1421
 
1335
1422
  /* Update number of partitions, but not if there are
1336
1423
  * (possibly intermittent) errors (e.g., "Leader not available"). */
1337
1424
  if (mdt->err == RD_KAFKA_RESP_ERR_NO_ERROR) {
1338
- upd += rd_kafka_topic_partition_cnt_update(rkt,
1339
- mdt->partition_cnt);
1340
- if (rd_kafka_Uuid_cmp(mdit->topic_id, RD_KAFKA_UUID_ZERO) &&
1341
- rd_kafka_Uuid_cmp(mdit->topic_id, rkt->rkt_topic_id)) {
1425
+ rd_bool_t different_topic_id =
1426
+ rd_kafka_Uuid_cmp(mdit->topic_id, rkt->rkt_topic_id) != 0;
1427
+ if (different_topic_id ||
1428
+ mdt->partition_cnt > rkt->rkt_partition_cnt)
1429
+ upd += rd_kafka_topic_partition_cnt_update(
1430
+ rkt, mdt->partition_cnt);
1431
+ if (different_topic_id) {
1342
1432
  /* FIXME: an offset reset must be triggered.
1343
1433
  * when rkt_topic_id wasn't zero.
1344
1434
  * There are no problems
@@ -1364,71 +1454,63 @@ rd_kafka_topic_metadata_update(rd_kafka_topic_t *rkt,
1364
1454
  * Issue #1985. */
1365
1455
  if (old_state == RD_KAFKA_TOPIC_S_UNKNOWN)
1366
1456
  upd++;
1367
- }
1368
1457
 
1369
- /* Update leader for each partition */
1370
- for (j = 0; j < mdt->partition_cnt; j++) {
1371
- int r = 0;
1372
- rd_kafka_broker_t *leader;
1373
- int32_t leader_epoch = mdit->partitions[j].leader_epoch;
1374
- rd_kafka_toppar_t *rktp =
1375
- rd_kafka_toppar_get(rkt, mdt->partitions[j].id, 0);
1458
+ /* Update leader for each partition
1459
+ * only when topic response has no errors. */
1460
+ for (j = 0;
1461
+ j < mdt->partition_cnt && j < rkt->rkt_partition_cnt;
1462
+ j++) {
1463
+ int r = 0;
1464
+ rd_kafka_broker_t *leader;
1465
+ int32_t leader_epoch = mdit->partitions[j].leader_epoch;
1466
+ rd_kafka_toppar_t *rktp =
1467
+ rd_kafka_toppar_get(rkt, mdt->partitions[j].id, 0);
1468
+
1469
+ rd_kafka_dbg(rk, TOPIC | RD_KAFKA_DBG_METADATA,
1470
+ "METADATA",
1471
+ "Topic %s [%" PRId32 "] Leader %" PRId32
1472
+ " Epoch %" PRId32,
1473
+ rkt->rkt_topic->str, mdt->partitions[j].id,
1474
+ mdt->partitions[j].leader, leader_epoch);
1475
+
1476
+ leader = partbrokers[j];
1477
+ partbrokers[j] = NULL;
1376
1478
 
1377
- rd_kafka_dbg(rk, TOPIC | RD_KAFKA_DBG_METADATA, "METADATA",
1378
- "Topic %s [%" PRId32 "] Leader %" PRId32
1379
- " Epoch %" PRId32,
1380
- rkt->rkt_topic->str, mdt->partitions[j].id,
1381
- mdt->partitions[j].leader, leader_epoch);
1382
-
1383
- leader = partbrokers[j];
1384
- partbrokers[j] = NULL;
1385
-
1386
- /* If broker does not support leaderEpoch(KIP 320) then it is
1387
- * set to -1, we assume that metadata is not stale. */
1388
- if (leader_epoch == -1)
1389
- partition_exists_with_no_leader_epoch = rd_true;
1390
- else if (leader_epoch < rktp->rktp_leader_epoch)
1391
- partition_exists_with_stale_leader_epoch = rd_true;
1392
-
1393
-
1394
- /* Update leader for partition */
1395
- r = rd_kafka_toppar_leader_update(rkt, mdt->partitions[j].id,
1396
- mdt->partitions[j].leader,
1397
- leader, leader_epoch);
1398
-
1399
- upd += (r != 0 ? 1 : 0);
1400
-
1401
- if (leader) {
1402
- if (r != -1)
1403
- leader_cnt++;
1404
- /* Drop reference to broker (from find()) */
1405
- rd_kafka_broker_destroy(leader);
1479
+ /* If broker does not support leaderEpoch(KIP 320) then
1480
+ * it is set to -1, we assume that metadata is not
1481
+ * stale. */
1482
+ if (leader_epoch == -1)
1483
+ partition_exists_with_no_leader_epoch = rd_true;
1484
+ else if (rktp && leader_epoch < rktp->rktp_leader_epoch)
1485
+ partition_exists_with_stale_leader_epoch =
1486
+ rd_true;
1487
+
1488
+
1489
+ /* Update leader for partition */
1490
+ r = rd_kafka_toppar_leader_update(
1491
+ rkt, mdt->partitions[j].id,
1492
+ mdt->partitions[j].leader, leader, leader_epoch);
1493
+
1494
+ upd += (r != 0 ? 1 : 0);
1495
+
1496
+ if (leader) {
1497
+ if (r != -1)
1498
+ leader_cnt++;
1499
+ /* Drop reference to broker (from find()) */
1500
+ rd_kafka_broker_destroy(leader);
1501
+ }
1502
+ RD_IF_FREE(rktp, rd_kafka_toppar_destroy);
1406
1503
  }
1407
- RD_IF_FREE(rktp, rd_kafka_toppar_destroy);
1408
1504
  }
1409
1505
 
1410
1506
  /* If all partitions have leaders, and this metadata update was not
1411
1507
  * stale, we can turn off fast leader query. */
1412
- if (mdt->partition_cnt > 0 && leader_cnt == mdt->partition_cnt &&
1508
+ if (rkt->rkt_partition_cnt > 0 &&
1509
+ leader_cnt == rkt->rkt_partition_cnt &&
1413
1510
  (partition_exists_with_no_leader_epoch ||
1414
1511
  !partition_exists_with_stale_leader_epoch))
1415
1512
  rkt->rkt_flags &= ~RD_KAFKA_TOPIC_F_LEADER_UNAVAIL;
1416
1513
 
1417
- if (mdt->err != RD_KAFKA_RESP_ERR_NO_ERROR && rkt->rkt_partition_cnt) {
1418
- /* (Possibly intermittent) topic-wide error:
1419
- * remove leaders for partitions */
1420
-
1421
- for (j = 0; j < rkt->rkt_partition_cnt; j++) {
1422
- rd_kafka_toppar_t *rktp;
1423
- if (!rkt->rkt_p[j])
1424
- continue;
1425
-
1426
- rktp = rkt->rkt_p[j];
1427
- rd_kafka_toppar_lock(rktp);
1428
- rd_kafka_toppar_broker_delegate(rktp, NULL);
1429
- rd_kafka_toppar_unlock(rktp);
1430
- }
1431
- }
1432
1514
 
1433
1515
  /* If there was an update to the partitions try to assign
1434
1516
  * unassigned messages to new partitions, or fail them */
@@ -1647,8 +1729,8 @@ void rd_kafka_topic_scan_all(rd_kafka_t *rk, rd_ts_t now) {
1647
1729
 
1648
1730
  /* Check if metadata information has timed out. */
1649
1731
  if (rkt->rkt_state != RD_KAFKA_TOPIC_S_UNKNOWN &&
1650
- !rd_kafka_metadata_cache_topic_get(rk, rkt->rkt_topic->str,
1651
- 1 /*only valid*/)) {
1732
+ !rd_kafka_metadata_cache_topic_get(
1733
+ rk, rkt->rkt_topic->str, NULL, 1 /*only valid*/)) {
1652
1734
  rd_kafka_dbg(rk, TOPIC, "NOINFO",
1653
1735
  "Topic %s metadata information timed out "
1654
1736
  "(%" PRId64 "ms old)",
@@ -1766,7 +1848,8 @@ void rd_kafka_topic_scan_all(rd_kafka_t *rk, rd_ts_t now) {
1766
1848
  * info exists*/
1767
1849
  ,
1768
1850
  rk->rk_conf.allow_auto_create_topics,
1769
- rd_false /*!cgrp_update*/, "refresh unavailable topics");
1851
+ rd_false /*!cgrp_update*/, -1,
1852
+ "refresh unavailable topics");
1770
1853
  rd_list_destroy(&query_topics);
1771
1854
  }
1772
1855
 
@@ -1965,7 +2048,7 @@ rd_kafka_topic_info_t *rd_kafka_topic_info_new_with_rack(
1965
2048
  /**
1966
2049
  * Destroy/free topic_info
1967
2050
  */
1968
- void rd_kafka_topic_info_destroy(rd_kafka_topic_info_t *ti) {
2051
+ void rd_kafka_topic_info_destroy_free(void *ti) {
1969
2052
  rd_free(ti);
1970
2053
  }
1971
2054
 
@@ -2013,7 +2096,7 @@ void rd_kafka_topic_leader_query0(rd_kafka_t *rk,
2013
2096
 
2014
2097
  rd_kafka_metadata_refresh_topics(
2015
2098
  rk, NULL, &topics, force, rk->rk_conf.allow_auto_create_topics,
2016
- rd_false /*!cgrp_update*/, "leader query");
2099
+ rd_false /*!cgrp_update*/, -1, "leader query");
2017
2100
 
2018
2101
  rd_list_destroy(&topics);
2019
2102
  }
@@ -2039,7 +2122,7 @@ void rd_kafka_local_topics_to_list(rd_kafka_t *rk,
2039
2122
  rd_list_grow(topics, rk->rk_topic_cnt);
2040
2123
  TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link)
2041
2124
  rd_list_add(topics, rd_strdup(rkt->rkt_topic->str));
2042
- cache_cnt = rd_kafka_metadata_cache_topics_to_list(rk, topics);
2125
+ cache_cnt = rd_kafka_metadata_cache_topics_to_list(rk, topics, rd_true);
2043
2126
  if (cache_cntp)
2044
2127
  *cache_cntp = cache_cnt;
2045
2128
  rd_kafka_rdunlock(rk);
@@ -2056,8 +2139,8 @@ void rd_ut_kafka_topic_set_topic_exists(rd_kafka_topic_t *rkt,
2056
2139
  rd_kafka_metadata_partition_internal_t *partitions =
2057
2140
  rd_calloc(partition_cnt, sizeof(*partitions));
2058
2141
  struct rd_kafka_metadata_topic mdt = {.topic =
2059
- (char *)rkt->rkt_topic->str,
2060
- .partition_cnt = partition_cnt};
2142
+ (char *)rkt->rkt_topic->str,
2143
+ .partition_cnt = partition_cnt};
2061
2144
  rd_kafka_metadata_topic_internal_t mdit = {.partitions = partitions};
2062
2145
  int i;
2063
2146
 
@@ -2071,7 +2154,7 @@ void rd_ut_kafka_topic_set_topic_exists(rd_kafka_topic_t *rkt,
2071
2154
 
2072
2155
  rd_kafka_wrlock(rkt->rkt_rk);
2073
2156
  rd_kafka_metadata_cache_topic_update(rkt->rkt_rk, &mdt, &mdit, rd_true,
2074
- rd_false, NULL, 0, rd_false);
2157
+ rd_false, rd_true);
2075
2158
  rd_kafka_topic_metadata_update(rkt, &mdt, &mdit, rd_clock());
2076
2159
  rd_kafka_wrunlock(rkt->rkt_rk);
2077
2160
  rd_free(partitions);
@@ -159,12 +159,14 @@ struct rd_kafka_topic_s {
159
159
  rd_refcnt_t rkt_app_refcnt; /**< Number of active rkt's new()ed
160
160
  * by application. */
161
161
 
162
- enum { RD_KAFKA_TOPIC_S_UNKNOWN, /* No cluster information yet */
163
- RD_KAFKA_TOPIC_S_EXISTS, /* Topic exists in cluster */
164
- RD_KAFKA_TOPIC_S_NOTEXISTS, /* Topic is not known in cluster */
165
- RD_KAFKA_TOPIC_S_ERROR, /* Topic exists but is in an errored
166
- * state, such as auth failure. */
162
+ enum {
163
+ RD_KAFKA_TOPIC_S_UNKNOWN, /* No cluster information yet */
164
+ RD_KAFKA_TOPIC_S_EXISTS, /* Topic exists in cluster */
165
+ RD_KAFKA_TOPIC_S_NOTEXISTS, /* Topic is not known in cluster */
166
+ RD_KAFKA_TOPIC_S_ERROR, /* Topic exists but is in an errored
167
+ * state, such as auth failure. */
167
168
  } rkt_state;
169
+ rd_ts_t rkt_ts_state; /**< State change time. */
168
170
 
169
171
  int rkt_flags;
170
172
  #define RD_KAFKA_TOPIC_F_LEADER_UNAVAIL \
@@ -289,7 +291,7 @@ rd_kafka_topic_info_t *rd_kafka_topic_info_new_with_rack(
289
291
  const char *topic,
290
292
  int partition_cnt,
291
293
  const rd_kafka_metadata_partition_internal_t *mdpi);
292
- void rd_kafka_topic_info_destroy(rd_kafka_topic_info_t *ti);
294
+ void rd_kafka_topic_info_destroy_free(void *ti);
293
295
 
294
296
  int rd_kafka_topic_match(rd_kafka_t *rk,
295
297
  const char *pattern,
@@ -302,6 +304,10 @@ int rd_kafka_toppar_broker_update(rd_kafka_toppar_t *rktp,
302
304
 
303
305
  int rd_kafka_toppar_delegate_to_leader(rd_kafka_toppar_t *rktp);
304
306
 
307
+ void rd_kafka_toppar_undelegate(rd_kafka_toppar_t *rktp);
308
+
309
+ void rd_kafka_toppar_forget_leader(rd_kafka_toppar_t *rktp);
310
+
305
311
  rd_kafka_resp_err_t rd_kafka_topics_leader_query_sync(rd_kafka_t *rk,
306
312
  int all_topics,
307
313
  const rd_list_t *topics,
@@ -314,8 +320,8 @@ void rd_kafka_topic_leader_query0(rd_kafka_t *rk,
314
320
  rd_kafka_topic_leader_query0(rk, rkt, 1 /*lock*/, \
315
321
  rd_false /*dont force*/)
316
322
 
317
- #define rd_kafka_topic_fast_leader_query(rk) \
318
- rd_kafka_metadata_fast_leader_query(rk)
323
+ #define rd_kafka_topic_fast_leader_query(rk, force) \
324
+ rd_kafka_metadata_fast_leader_query(rk, force)
319
325
 
320
326
  void rd_kafka_local_topics_to_list(rd_kafka_t *rk,
321
327
  rd_list_t *topics,