@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
@@ -252,24 +252,20 @@ int rd_kafka_metadata_partition_id_cmp(const void *_a, const void *_b) {
252
252
  return RD_CMP(a->id, b->id);
253
253
  }
254
254
 
255
-
256
255
  /**
257
- * @brief Add (and replace) cache entry for topic.
256
+ * @brief Creates a new metadata cache entry.
258
257
  *
259
- * This makes a copy of \p topic
258
+ * @param mdt Topic to insert in the cache entry.
259
+ * @param mdti Topic to insert in the cache entry (internal structure).
260
+ * @param include_racks Include partition racks.
260
261
  *
261
- * @locks_required rd_kafka_wrlock()
262
+ * @return The new metadata cache entry, to free with `rd_free`.
262
263
  */
263
- static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_insert(
264
- rd_kafka_t *rk,
264
+ static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_entry_new(
265
265
  const rd_kafka_metadata_topic_t *mtopic,
266
266
  const rd_kafka_metadata_topic_internal_t *metadata_internal_topic,
267
- rd_ts_t now,
268
- rd_ts_t ts_expires,
269
- rd_bool_t include_racks,
270
- rd_kafka_metadata_broker_internal_t *brokers_internal,
271
- size_t broker_cnt) {
272
- struct rd_kafka_metadata_cache_entry *rkmce, *old, *old_by_id = NULL;
267
+ rd_bool_t include_racks) {
268
+ struct rd_kafka_metadata_cache_entry *rkmce;
273
269
  rd_tmpabuf_t tbuf;
274
270
  int i;
275
271
 
@@ -363,6 +359,21 @@ static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_insert(
363
359
  rkmce->rkmce_mtopic.partitions[i].isrs = NULL;
364
360
  rkmce->rkmce_mtopic.partitions[i].isr_cnt = 0;
365
361
  }
362
+
363
+ return rkmce;
364
+ }
365
+
366
+ /**
367
+ * @brief Add (and replace) cache entry for topic.
368
+ *
369
+ * @locks_required rd_kafka_wrlock()
370
+ */
371
+ static struct rd_kafka_metadata_cache_entry *
372
+ rd_kafka_metadata_cache_insert(rd_kafka_t *rk,
373
+ struct rd_kafka_metadata_cache_entry *rkmce,
374
+ rd_ts_t now,
375
+ rd_ts_t ts_expires) {
376
+ struct rd_kafka_metadata_cache_entry *old, *old_by_id = NULL;
366
377
  TAILQ_INSERT_TAIL(&rk->rk_metadata_cache.rkmc_expiry, rkmce,
367
378
  rkmce_link);
368
379
  rk->rk_metadata_cache.rkmc_cnt++;
@@ -379,9 +390,14 @@ static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_insert(
379
390
  /* If topic id isn't zero insert cache entry into this tree */
380
391
  old_by_id = RD_AVL_INSERT(&rk->rk_metadata_cache.rkmc_avl_by_id,
381
392
  rkmce, rkmce_avlnode_by_id);
382
- } else if (old && !RD_KAFKA_UUID_IS_ZERO(
383
- old->rkmce_metadata_internal_topic.topic_id)) {
384
- /* If it had a topic id, remove it from the tree */
393
+ }
394
+ if (old &&
395
+ !RD_KAFKA_UUID_IS_ZERO(
396
+ old->rkmce_metadata_internal_topic.topic_id) &&
397
+ rd_kafka_Uuid_cmp(rkmce->rkmce_metadata_internal_topic.topic_id,
398
+ old->rkmce_metadata_internal_topic.topic_id) !=
399
+ 0) {
400
+ /* If it had a different topic id, remove it from the tree */
385
401
  RD_AVL_REMOVE_ELM(&rk->rk_metadata_cache.rkmc_avl_by_id, old);
386
402
  }
387
403
  if (old) {
@@ -389,10 +405,8 @@ static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_insert(
389
405
  rd_kafka_metadata_cache_delete(rk, old, 0);
390
406
  }
391
407
  if (old_by_id && old_by_id != old) {
392
- /* If there was a different cache entry in this tree,
393
- * remove and free it. */
394
- RD_AVL_REMOVE_ELM(&rk->rk_metadata_cache.rkmc_avl, old_by_id);
395
- rd_kafka_metadata_cache_delete(rk, old_by_id, 0);
408
+ rd_dassert(
409
+ !*"Different cache entries for topic name and topic id");
396
410
  }
397
411
 
398
412
  /* Explicitly not freeing the tmpabuf since rkmce points to its
@@ -400,6 +414,27 @@ static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_insert(
400
414
  return rkmce;
401
415
  }
402
416
 
417
+ /**
418
+ * @brief Add (and replace) cache entry for topic.
419
+ *
420
+ * This makes a copy of \p mtopic and \p metadata_internal_topic ,
421
+ *
422
+ * @locks_required rd_kafka_wrlock()
423
+ */
424
+ static struct rd_kafka_metadata_cache_entry *rd_kafka_metadata_cache_insert_new(
425
+ rd_kafka_t *rk,
426
+ const rd_kafka_metadata_topic_t *mtopic,
427
+ const rd_kafka_metadata_topic_internal_t *metadata_internal_topic,
428
+ rd_ts_t now,
429
+ rd_ts_t ts_expires,
430
+ rd_bool_t include_racks) {
431
+ /* Create entry */
432
+ struct rd_kafka_metadata_cache_entry *rkmce =
433
+ rd_kafka_metadata_cache_entry_new(mtopic, metadata_internal_topic,
434
+ include_racks);
435
+ /* Insert/replace entry */
436
+ return rd_kafka_metadata_cache_insert(rk, rkmce, now, ts_expires);
437
+ }
403
438
 
404
439
  /**
405
440
  * @brief Purge the metadata cache
@@ -440,6 +475,142 @@ void rd_kafka_metadata_cache_expiry_start(rd_kafka_t *rk) {
440
475
  rd_kafka_metadata_cache_evict_tmr_cb, rk);
441
476
  }
442
477
 
478
+ #define rd_kafka_metadata_cache_topic_update_replace_partition( \
479
+ current_partition, new_partition, current_partition_cnt, \
480
+ new_partition_cnt, partition) \
481
+ ((partition) < (current_partition_cnt) && \
482
+ (partition) >= (new_partition_cnt) \
483
+ ? rd_false \
484
+ : (partition) < (new_partition_cnt) && \
485
+ (partition) >= (current_partition_cnt) \
486
+ ? rd_true \
487
+ : (new_partition).leader_epoch == -1 || \
488
+ (new_partition).leader_epoch >= \
489
+ (current_partition.leader_epoch));
490
+
491
+
492
+ static struct rd_kafka_metadata_cache_entry *
493
+ rd_kafka_metadata_cache_topic_update_merge_partitions(
494
+ rd_kafka_t *rk,
495
+ struct rd_kafka_metadata_cache_entry *rkmce_current,
496
+ const rd_kafka_metadata_topic_t *mdt,
497
+ const rd_kafka_metadata_topic_internal_t *mdti,
498
+ rd_bool_t include_racks,
499
+ rd_bool_t has_reliable_epochs) {
500
+ rd_tmpabuf_t tbuf;
501
+ struct rd_kafka_metadata_cache_entry *rkmce;
502
+ size_t i, current_partition_cnt, new_partition_cnt, partition_cnt;
503
+
504
+ if (!has_reliable_epochs || !rkmce_current ||
505
+ /* Different topic ids */
506
+ rd_kafka_Uuid_cmp(
507
+ mdti->topic_id,
508
+ rkmce_current->rkmce_metadata_internal_topic.topic_id) != 0) {
509
+ return rd_kafka_metadata_cache_entry_new(mdt, mdti,
510
+ include_racks);
511
+ }
512
+
513
+ current_partition_cnt = rkmce_current->rkmce_mtopic.partition_cnt;
514
+ new_partition_cnt = mdt->partition_cnt;
515
+ partition_cnt = RD_MAX(current_partition_cnt, new_partition_cnt);
516
+
517
+ rd_tmpabuf_new(&tbuf, sizeof(*rkmce), rd_true /*assert on fail*/);
518
+ rd_tmpabuf_add_alloc(&tbuf, sizeof(*rkmce));
519
+ rd_tmpabuf_add_alloc(&tbuf, strlen(mdt->topic) + 1);
520
+ rd_tmpabuf_add_alloc(&tbuf, partition_cnt * sizeof(*mdt->partitions));
521
+ rd_tmpabuf_add_alloc(&tbuf, partition_cnt * sizeof(*mdti->partitions));
522
+
523
+ for (i = 0; include_racks && i < partition_cnt; i++) {
524
+ size_t j;
525
+ rd_kafka_metadata_partition_internal_t *partition_internal;
526
+ rd_bool_t replace_partition =
527
+ rd_kafka_metadata_cache_topic_update_replace_partition(
528
+ rkmce_current->rkmce_metadata_internal_topic
529
+ .partitions[i],
530
+ mdti->partitions[i], current_partition_cnt,
531
+ new_partition_cnt, i);
532
+
533
+ partition_internal =
534
+ replace_partition
535
+ ? &mdti->partitions[i]
536
+ : &rkmce_current->rkmce_metadata_internal_topic
537
+ .partitions[i];
538
+ rd_tmpabuf_add_alloc(&tbuf, partition_internal->racks_cnt *
539
+ sizeof(char *));
540
+ for (j = 0; j < partition_internal->racks_cnt; j++) {
541
+ rd_tmpabuf_add_alloc(
542
+ &tbuf, strlen(partition_internal->racks[j]) + 1);
543
+ }
544
+ }
545
+
546
+ rd_tmpabuf_finalize(&tbuf);
547
+
548
+ rkmce = rd_tmpabuf_alloc(&tbuf, sizeof(*rkmce));
549
+
550
+ rkmce->rkmce_mtopic = *mdt;
551
+
552
+ rkmce->rkmce_metadata_internal_topic = *mdti;
553
+
554
+ /* Copy topic name */
555
+ rkmce->rkmce_mtopic.topic = rd_tmpabuf_write_str(&tbuf, mdt->topic);
556
+
557
+ /* Allocate partition array */
558
+ rkmce->rkmce_mtopic.partitions =
559
+ rd_tmpabuf_alloc(&tbuf, partition_cnt * sizeof(*mdt->partitions));
560
+
561
+ /* Allocate partition array (internal) */
562
+ rkmce->rkmce_metadata_internal_topic.partitions =
563
+ rd_tmpabuf_alloc(&tbuf, partition_cnt * sizeof(*mdti->partitions));
564
+
565
+ for (i = 0; i < partition_cnt; i++) {
566
+ struct rd_kafka_metadata_partition *partition;
567
+ rd_kafka_metadata_partition_internal_t *partition_internal;
568
+
569
+ rd_bool_t replace_partition =
570
+ rd_kafka_metadata_cache_topic_update_replace_partition(
571
+ rkmce_current->rkmce_metadata_internal_topic
572
+ .partitions[i],
573
+ mdti->partitions[i], current_partition_cnt,
574
+ new_partition_cnt, i);
575
+
576
+ if (replace_partition) {
577
+ partition = &mdt->partitions[i];
578
+ partition_internal = &mdti->partitions[i];
579
+ } else {
580
+ partition = &rkmce_current->rkmce_mtopic.partitions[i];
581
+ partition_internal =
582
+ &rkmce_current->rkmce_metadata_internal_topic
583
+ .partitions[i];
584
+ }
585
+
586
+ rkmce->rkmce_mtopic.partitions[i] = *partition;
587
+ rkmce->rkmce_metadata_internal_topic.partitions[i] =
588
+ *partition_internal;
589
+
590
+ if (include_racks) {
591
+ size_t j;
592
+ rkmce->rkmce_metadata_internal_topic.partitions[i]
593
+ .racks = rd_tmpabuf_alloc(
594
+ &tbuf,
595
+ partition_internal->racks_cnt * sizeof(char *));
596
+ rkmce->rkmce_metadata_internal_topic.partitions[i]
597
+ .racks_cnt = partition_internal->racks_cnt;
598
+ for (j = 0; j < partition_internal->racks_cnt; j++) {
599
+ rkmce->rkmce_metadata_internal_topic
600
+ .partitions[i]
601
+ .racks[j] = rd_tmpabuf_write_str(
602
+ &tbuf, partition_internal->racks[j]);
603
+ }
604
+ } else {
605
+ rkmce->rkmce_metadata_internal_topic.partitions[i]
606
+ .racks = NULL;
607
+ rkmce->rkmce_metadata_internal_topic.partitions[i]
608
+ .racks_cnt = 0;
609
+ }
610
+ }
611
+ return rkmce;
612
+ }
613
+
443
614
  /**
444
615
  * @brief Update the metadata cache for a single topic
445
616
  * with the provided metadata.
@@ -456,8 +627,12 @@ void rd_kafka_metadata_cache_expiry_start(rd_kafka_t *rk) {
456
627
  * For permanent errors (authorization failures), we keep
457
628
  * the entry cached for metadata.max.age.ms.
458
629
  *
459
- * @param only_existing Update only existing metadata cache entries,
460
- * either valid or hinted.
630
+ * @param mdt Topic to insert in the cache entry.
631
+ * @param mdti Topic to insert in the cache entry (internal structure).
632
+ * @param propagate Propagate metadata cache changes now.
633
+ * @param include_racks Include partition racks.
634
+ * @param has_reliable_leader_epochs Comes from a broker with reliable leader
635
+ * epochs.
461
636
  *
462
637
  * @return 1 on metadata change, 0 when no change was applied
463
638
  *
@@ -469,47 +644,64 @@ void rd_kafka_metadata_cache_expiry_start(rd_kafka_t *rk) {
469
644
  int rd_kafka_metadata_cache_topic_update(
470
645
  rd_kafka_t *rk,
471
646
  const rd_kafka_metadata_topic_t *mdt,
472
- const rd_kafka_metadata_topic_internal_t *mdit,
647
+ const rd_kafka_metadata_topic_internal_t *mdti,
473
648
  rd_bool_t propagate,
474
649
  rd_bool_t include_racks,
475
- rd_kafka_metadata_broker_internal_t *brokers,
476
- size_t broker_cnt,
477
- rd_bool_t only_existing) {
478
- struct rd_kafka_metadata_cache_entry *rkmce = NULL;
479
- rd_ts_t now = rd_clock();
650
+ rd_bool_t has_reliable_leader_epochs) {
651
+ rd_ts_t now = rd_clock();
480
652
  rd_ts_t ts_expires = now + (rk->rk_conf.metadata_max_age_ms * 1000);
481
- int changed = 1;
482
- if (only_existing) {
483
- if (likely(mdt->topic != NULL)) {
484
- rkmce = rd_kafka_metadata_cache_find(rk, mdt->topic, 0);
485
- } else {
486
- rkmce = rd_kafka_metadata_cache_find_by_id(
487
- rk, mdit->topic_id, 1);
488
- }
489
- if (!rkmce)
490
- return 0;
491
- }
653
+ int changed = 0;
492
654
 
493
655
  if (likely(mdt->topic != NULL)) {
494
- /* Cache unknown topics for a short while (100ms) to allow the
495
- * cgrp logic to find negative cache hits. */
496
- if (mdt->err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART)
656
+ struct rd_kafka_metadata_cache_entry *rkmce,
657
+ *rkmce_current = NULL;
658
+ rd_kafka_metadata_topic_internal_t mdti_copy = *mdti;
659
+ switch (mdt->err) {
660
+ case RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART:
661
+ /* Cache unknown topics for metadata.propagation.max.ms
662
+ * to allow the cgrp logic to find negative cache hits.
663
+ * and to avoid false reappearances of the topic
664
+ * after deletion. */
497
665
  ts_expires = RD_MIN(ts_expires, now + (100 * 1000));
498
666
 
499
- if (!mdt->err ||
500
- mdt->err == RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED ||
501
- mdt->err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART)
502
- rd_kafka_metadata_cache_insert(
503
- rk, mdt, mdit, now, ts_expires, include_racks,
504
- brokers, broker_cnt);
505
- else
506
- changed = rd_kafka_metadata_cache_delete_by_name(
507
- rk, mdt->topic);
667
+ /* Continue */
668
+ case RD_KAFKA_RESP_ERR_NO_ERROR:
669
+ rkmce_current =
670
+ rd_kafka_metadata_cache_find(rk, mdt->topic, 1);
671
+ if (mdt->err ==
672
+ RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART &&
673
+ rkmce_current &&
674
+ RD_KAFKA_UUID_IS_ZERO(mdti->topic_id) &&
675
+ !RD_KAFKA_UUID_IS_ZERO(
676
+ rkmce_current->rkmce_metadata_internal_topic
677
+ .topic_id)) {
678
+ /* Keep the existing topic id to detect
679
+ * if the same id is received again
680
+ * as existing */
681
+ mdti_copy.topic_id =
682
+ rkmce_current->rkmce_metadata_internal_topic
683
+ .topic_id;
684
+ }
685
+
686
+ /* Continue */
687
+ case RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED:
688
+ rkmce =
689
+ rd_kafka_metadata_cache_topic_update_merge_partitions(
690
+ rk, rkmce_current, mdt, &mdti_copy,
691
+ include_racks, has_reliable_leader_epochs);
692
+ /* Insert/replace entry */
693
+ rd_kafka_metadata_cache_insert(rk, rkmce, now,
694
+ ts_expires);
695
+ changed = 1;
696
+ break;
697
+ default:
698
+ break;
699
+ }
508
700
  } else {
509
701
  /* Cache entry found but no topic name:
510
702
  * delete it. */
511
703
  changed = rd_kafka_metadata_cache_delete_by_topic_id(
512
- rk, mdit->topic_id);
704
+ rk, mdti->topic_id);
513
705
  }
514
706
 
515
707
  if (changed && propagate)
@@ -603,7 +795,6 @@ void rd_kafka_metadata_cache_purge_hints_by_id(rd_kafka_t *rk,
603
795
  * @param dst rd_list_t(char *topicname)
604
796
  * @param err is the error to set on hint cache entries,
605
797
  * typically ERR__WAIT_CACHE.
606
- * @param replace replace existing valid entries
607
798
  *
608
799
  * @returns the number of topic hints inserted.
609
800
  *
@@ -612,8 +803,7 @@ void rd_kafka_metadata_cache_purge_hints_by_id(rd_kafka_t *rk,
612
803
  int rd_kafka_metadata_cache_hint(rd_kafka_t *rk,
613
804
  const rd_list_t *topics,
614
805
  rd_list_t *dst,
615
- rd_kafka_resp_err_t err,
616
- rd_bool_t replace) {
806
+ rd_kafka_resp_err_t err) {
617
807
  const char *topic;
618
808
  rd_ts_t now = rd_clock();
619
809
  rd_ts_t ts_expires = now + (rk->rk_conf.socket_timeout_ms * 1000);
@@ -627,9 +817,8 @@ int rd_kafka_metadata_cache_hint(rd_kafka_t *rk,
627
817
  RD_ZERO_INIT;
628
818
  /*const*/ struct rd_kafka_metadata_cache_entry *rkmce;
629
819
 
630
- /* !replace: Dont overwrite valid entries */
631
- if (!replace && (rkmce = rd_kafka_metadata_cache_find(
632
- rk, topic, 0 /*any*/))) {
820
+ if ((rkmce =
821
+ rd_kafka_metadata_cache_find(rk, topic, 0 /*any*/))) {
633
822
  if (RD_KAFKA_METADATA_CACHE_VALID(rkmce) ||
634
823
  (dst && rkmce->rkmce_mtopic.err !=
635
824
  RD_KAFKA_RESP_ERR__NOENT))
@@ -638,9 +827,9 @@ int rd_kafka_metadata_cache_hint(rd_kafka_t *rk,
638
827
  /* FALLTHRU */
639
828
  }
640
829
 
641
- rd_kafka_metadata_cache_insert(rk, &mtopic,
642
- &metadata_internal_topic, now,
643
- ts_expires, rd_false, NULL, 0);
830
+ rd_kafka_metadata_cache_insert_new(rk, &mtopic,
831
+ &metadata_internal_topic,
832
+ now, ts_expires, rd_false);
644
833
  cnt++;
645
834
 
646
835
  if (dst)
@@ -665,8 +854,7 @@ int rd_kafka_metadata_cache_hint(rd_kafka_t *rk,
665
854
  int rd_kafka_metadata_cache_hint_rktparlist(
666
855
  rd_kafka_t *rk,
667
856
  const rd_kafka_topic_partition_list_t *rktparlist,
668
- rd_list_t *dst,
669
- int replace) {
857
+ rd_list_t *dst) {
670
858
  rd_list_t topics;
671
859
  int r;
672
860
 
@@ -674,8 +862,8 @@ int rd_kafka_metadata_cache_hint_rktparlist(
674
862
  rd_kafka_topic_partition_list_get_topic_names(rktparlist, &topics,
675
863
  0 /*dont include regex*/);
676
864
  rd_kafka_wrlock(rk);
677
- r = rd_kafka_metadata_cache_hint(
678
- rk, &topics, dst, RD_KAFKA_RESP_ERR__WAIT_CACHE, replace);
865
+ r = rd_kafka_metadata_cache_hint(rk, &topics, dst,
866
+ RD_KAFKA_RESP_ERR__WAIT_CACHE);
679
867
  rd_kafka_wrunlock(rk);
680
868
 
681
869
  rd_list_destroy(&topics);
@@ -811,20 +999,27 @@ void rd_kafka_metadata_cache_propagate_changes(rd_kafka_t *rk) {
811
999
  }
812
1000
 
813
1001
  /**
1002
+ * @param mdtip If non NULL, it's set to a pointer to internal topic metadata,
1003
+ * or to NULL if not found in cache.
814
1004
  * @returns the shared metadata for a topic, or NULL if not found in
815
1005
  * cache.
816
1006
  *
817
1007
  * @locks rd_kafka_*lock()
818
1008
  */
819
- const rd_kafka_metadata_topic_t *
820
- rd_kafka_metadata_cache_topic_get(rd_kafka_t *rk,
821
- const char *topic,
822
- int valid) {
1009
+ const rd_kafka_metadata_topic_t *rd_kafka_metadata_cache_topic_get(
1010
+ rd_kafka_t *rk,
1011
+ const char *topic,
1012
+ const rd_kafka_metadata_topic_internal_t **mdtip,
1013
+ int valid) {
823
1014
  struct rd_kafka_metadata_cache_entry *rkmce;
824
1015
 
825
- if (!(rkmce = rd_kafka_metadata_cache_find(rk, topic, valid)))
1016
+ if (!(rkmce = rd_kafka_metadata_cache_find(rk, topic, valid))) {
1017
+ if (mdtip)
1018
+ *mdtip = NULL;
826
1019
  return NULL;
827
-
1020
+ }
1021
+ if (mdtip)
1022
+ *mdtip = &rkmce->rkmce_metadata_internal_topic;
828
1023
  return &rkmce->rkmce_mtopic;
829
1024
  }
830
1025
 
@@ -838,6 +1033,7 @@ rd_kafka_metadata_cache_topic_get(rd_kafka_t *rk,
838
1033
  *
839
1034
  * @param mtopicp: pointer to topic metadata
840
1035
  * @param mpartp: pointer to partition metadata
1036
+ * @param mdpip: pointer to internal partition metadata
841
1037
  * @param valid: only return valid entries (no hints)
842
1038
  *
843
1039
  * @returns -1 if topic was not found in cache, 0 if topic was found
@@ -849,18 +1045,22 @@ int rd_kafka_metadata_cache_topic_partition_get(
849
1045
  rd_kafka_t *rk,
850
1046
  const rd_kafka_metadata_topic_t **mtopicp,
851
1047
  const rd_kafka_metadata_partition_t **mpartp,
1048
+ const rd_kafka_metadata_partition_internal_t **mdpip,
852
1049
  const char *topic,
853
1050
  int32_t partition,
854
1051
  int valid) {
855
1052
 
856
1053
  const rd_kafka_metadata_topic_t *mtopic;
1054
+ const rd_kafka_metadata_topic_internal_t *mdti;
857
1055
  const rd_kafka_metadata_partition_t *mpart;
858
1056
  rd_kafka_metadata_partition_t skel = {.id = partition};
859
1057
 
860
1058
  *mtopicp = NULL;
861
1059
  *mpartp = NULL;
1060
+ *mdpip = NULL;
862
1061
 
863
- if (!(mtopic = rd_kafka_metadata_cache_topic_get(rk, topic, valid)))
1062
+ if (!(mtopic =
1063
+ rd_kafka_metadata_cache_topic_get(rk, topic, &mdti, valid)))
864
1064
  return -1;
865
1065
 
866
1066
  *mtopicp = mtopic;
@@ -877,6 +1077,8 @@ int rd_kafka_metadata_cache_topic_partition_get(
877
1077
  return 0;
878
1078
 
879
1079
  *mpartp = mpart;
1080
+ if (mdpip)
1081
+ *mdpip = &mdti->partitions[mpart->id];
880
1082
 
881
1083
  return 1;
882
1084
  }
@@ -923,17 +1125,21 @@ int rd_kafka_metadata_cache_topics_count_exists(rd_kafka_t *rk,
923
1125
  *
924
1126
  * Element type is (char *topic_name).
925
1127
  *
1128
+ * @param exclude_valid Exclude topics that have up to date metadata info.
1129
+ *
926
1130
  * @returns the number of elements added to \p topics
927
1131
  *
928
1132
  * @locks_required rd_kafka_*lock()
929
1133
  */
930
- int rd_kafka_metadata_cache_topics_to_list(rd_kafka_t *rk, rd_list_t *topics) {
1134
+ int rd_kafka_metadata_cache_topics_to_list(rd_kafka_t *rk,
1135
+ rd_list_t *topics,
1136
+ rd_bool_t exclude_valid) {
931
1137
  const struct rd_kafka_metadata_cache_entry *rkmce;
932
1138
  int precnt = rd_list_cnt(topics);
933
1139
 
934
1140
  TAILQ_FOREACH(rkmce, &rk->rk_metadata_cache.rkmc_expiry, rkmce_link) {
935
1141
  /* Ignore topics that have up to date metadata info */
936
- if (RD_KAFKA_METADATA_CACHE_VALID(rkmce))
1142
+ if (exclude_valid && RD_KAFKA_METADATA_CACHE_VALID(rkmce))
937
1143
  continue;
938
1144
 
939
1145
  if (rd_list_find(topics, rkmce->rkmce_mtopic.topic,