@platformatic/rdkafka 4.0.0 → 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 (293) hide show
  1. package/README.md +5 -5
  2. package/bench/seed.sh +0 -0
  3. package/binding.gyp +3 -3
  4. package/ci/prepublish.js +4 -3
  5. package/ci/update-version.js +123 -0
  6. package/config.d.ts +126 -10
  7. package/configure +0 -0
  8. package/deps/librdkafka/.semaphore/run-all-tests.yml +77 -0
  9. package/deps/librdkafka/.semaphore/semaphore-integration.yml +250 -0
  10. package/deps/librdkafka/.semaphore/semaphore.yml +67 -44
  11. package/deps/librdkafka/.semaphore/verify-linux-packages.yml +41 -0
  12. package/deps/librdkafka/CHANGELOG.md +471 -1
  13. package/deps/librdkafka/CONFIGURATION.md +29 -9
  14. package/deps/librdkafka/INTRODUCTION.md +909 -601
  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/docs +5 -0
  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 +12 -13
  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/deps/librdkafka/.semaphore/project.yml +0 -43
  292. package/deps/librdkafka/.semaphore/project_public.yml +0 -20
  293. package/deps/librdkafka/win32/install-openssl.ps1 +0 -33
@@ -290,13 +290,26 @@ void rd_kafka_mock_Fetch_reply_tags_partition_write(
290
290
  rd_kafka_mock_partition_t *mpart) {
291
291
  switch (tagtype) {
292
292
  case 1: /* CurrentLeader */
293
+ {
294
+ int32_t leader_id = mpart->leader->id,
295
+ leader_epoch = mpart->leader_epoch;
296
+ rd_kafka_mock_partition_leader_t *mpart_leader =
297
+ rd_kafka_mock_partition_next_leader_response(mpart);
298
+ if (mpart_leader) {
299
+ leader_id = mpart_leader->leader_id;
300
+ leader_epoch = mpart_leader->leader_epoch;
301
+ rd_kafka_mock_partition_leader_destroy(mpart,
302
+ mpart_leader);
303
+ }
304
+
293
305
  /* Leader id */
294
- rd_kafka_buf_write_i32(rkbuf, mpart->leader->id);
306
+ rd_kafka_buf_write_i32(rkbuf, leader_id);
295
307
  /* Leader epoch */
296
- rd_kafka_buf_write_i32(rkbuf, mpart->leader_epoch);
308
+ rd_kafka_buf_write_i32(rkbuf, leader_epoch);
297
309
  /* Field tags */
298
310
  rd_kafka_buf_write_tags_empty(rkbuf);
299
311
  break;
312
+ }
300
313
  default:
301
314
  break;
302
315
  }
@@ -989,7 +1002,7 @@ static int rd_kafka_mock_handle_OffsetCommit(rd_kafka_mock_connection_t *mconn,
989
1002
  rd_kafka_buf_t *resp = rd_kafka_mock_buf_new_response(rkbuf);
990
1003
  rd_kafka_mock_broker_t *mrkb;
991
1004
  rd_kafka_resp_err_t all_err;
992
- int32_t GenerationId = -1, TopicsCnt;
1005
+ int32_t GenerationIdOrMemberEpoch = -1, TopicsCnt;
993
1006
  rd_kafkap_str_t GroupId, MemberId, GroupInstanceId;
994
1007
 
995
1008
  if (rkbuf->rkbuf_reqhdr.ApiVersion >= 3) {
@@ -1000,7 +1013,7 @@ static int rd_kafka_mock_handle_OffsetCommit(rd_kafka_mock_connection_t *mconn,
1000
1013
  rd_kafka_buf_read_str(rkbuf, &GroupId);
1001
1014
 
1002
1015
  if (rkbuf->rkbuf_reqhdr.ApiVersion >= 1) {
1003
- rd_kafka_buf_read_i32(rkbuf, &GenerationId);
1016
+ rd_kafka_buf_read_i32(rkbuf, &GenerationIdOrMemberEpoch);
1004
1017
  rd_kafka_buf_read_str(rkbuf, &MemberId);
1005
1018
  }
1006
1019
 
@@ -1024,24 +1037,50 @@ static int rd_kafka_mock_handle_OffsetCommit(rd_kafka_mock_connection_t *mconn,
1024
1037
 
1025
1038
 
1026
1039
  if (!all_err) {
1027
- rd_kafka_mock_cgrp_t *mcgrp;
1040
+ rd_kafka_mock_cgrp_classic_t *mcgrp_classic;
1028
1041
 
1029
- mcgrp = rd_kafka_mock_cgrp_find(mcluster, &GroupId);
1030
- if (mcgrp) {
1031
- rd_kafka_mock_cgrp_member_t *member = NULL;
1042
+ mcgrp_classic =
1043
+ rd_kafka_mock_cgrp_classic_find(mcluster, &GroupId);
1044
+ if (mcgrp_classic) {
1045
+ rd_kafka_mock_cgrp_classic_member_t *member = NULL;
1032
1046
 
1033
1047
  if (!RD_KAFKAP_STR_IS_NULL(&MemberId))
1034
- member = rd_kafka_mock_cgrp_member_find(
1035
- mcgrp, &MemberId);
1048
+ member = rd_kafka_mock_cgrp_classic_member_find(
1049
+ mcgrp_classic, &MemberId);
1036
1050
 
1037
1051
  if (!member)
1038
1052
  all_err = RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID;
1039
1053
  else
1040
- all_err = rd_kafka_mock_cgrp_check_state(
1041
- mcgrp, member, rkbuf, GenerationId);
1054
+ all_err =
1055
+ rd_kafka_mock_cgrp_classic_check_state(
1056
+ mcgrp_classic, member, rkbuf,
1057
+ GenerationIdOrMemberEpoch);
1058
+ } else {
1059
+ rd_kafka_mock_cgrp_consumer_t *mcgrp_consumer;
1060
+ rd_kafka_mock_cgrp_consumer_member_t *member = NULL;
1061
+
1062
+ mcgrp_consumer = rd_kafka_mock_cgrp_consumer_find(
1063
+ mcluster, &GroupId);
1064
+ if (mcgrp_consumer) {
1065
+ if (!RD_KAFKAP_STR_IS_NULL(&MemberId))
1066
+ member =
1067
+ rd_kafka_mock_cgrp_consumer_member_find(
1068
+ mcgrp_consumer, &MemberId);
1069
+
1070
+ if (!member)
1071
+ all_err =
1072
+ RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID;
1073
+ else
1074
+ all_err =
1075
+ GenerationIdOrMemberEpoch !=
1076
+ member->current_member_epoch
1077
+ ? RD_KAFKA_RESP_ERR_STALE_MEMBER_EPOCH
1078
+ : RD_KAFKA_RESP_ERR_NO_ERROR;
1079
+ }
1042
1080
  }
1043
1081
 
1044
- /* FIXME: also check that partitions are assigned to member */
1082
+ /* As happens here, a real broker doesn't check that partitions
1083
+ * are assigned to the member, but only the GenerationId. */
1045
1084
  }
1046
1085
 
1047
1086
  rd_kafka_buf_read_arraycnt(rkbuf, &TopicsCnt, RD_KAFKAP_TOPICS_MAX);
@@ -1258,6 +1297,8 @@ static int rd_kafka_mock_handle_Metadata(rd_kafka_mock_connection_t *mconn,
1258
1297
  rd_bool_t list_all_topics = rd_false;
1259
1298
  int32_t TopicsCnt;
1260
1299
  int i;
1300
+ size_t of_Brokers_cnt;
1301
+ int32_t response_Brokers_cnt = 0;
1261
1302
 
1262
1303
  if (rkbuf->rkbuf_reqhdr.ApiVersion >= 3) {
1263
1304
  /* Response: ThrottleTime */
@@ -1265,9 +1306,11 @@ static int rd_kafka_mock_handle_Metadata(rd_kafka_mock_connection_t *mconn,
1265
1306
  }
1266
1307
 
1267
1308
  /* Response: #Brokers */
1268
- rd_kafka_buf_write_arraycnt(resp, mcluster->broker_cnt);
1309
+ of_Brokers_cnt = rd_kafka_buf_write_arraycnt_pos(resp);
1269
1310
 
1270
1311
  TAILQ_FOREACH(mrkb, &mcluster->brokers, link) {
1312
+ if (!mrkb->up)
1313
+ continue;
1271
1314
  /* Response: Brokers.Nodeid */
1272
1315
  rd_kafka_buf_write_i32(resp, mrkb->id);
1273
1316
  /* Response: Brokers.Host */
@@ -1279,7 +1322,10 @@ static int rd_kafka_mock_handle_Metadata(rd_kafka_mock_connection_t *mconn,
1279
1322
  rd_kafka_buf_write_str(resp, mrkb->rack, -1);
1280
1323
  }
1281
1324
  rd_kafka_buf_write_tags_empty(resp);
1325
+ response_Brokers_cnt++;
1282
1326
  }
1327
+ rd_kafka_buf_finalize_arraycnt(resp, of_Brokers_cnt,
1328
+ response_Brokers_cnt);
1283
1329
 
1284
1330
  if (rkbuf->rkbuf_reqhdr.ApiVersion >= 2) {
1285
1331
  /* Response: ClusterId */
@@ -1524,8 +1570,8 @@ static int rd_kafka_mock_handle_JoinGroup(rd_kafka_mock_connection_t *mconn,
1524
1570
  int32_t ProtocolCnt = 0;
1525
1571
  int32_t i;
1526
1572
  rd_kafka_resp_err_t err;
1527
- rd_kafka_mock_cgrp_t *mcgrp;
1528
- rd_kafka_mock_cgrp_proto_t *protos = NULL;
1573
+ rd_kafka_mock_cgrp_classic_t *mcgrp;
1574
+ rd_kafka_mock_cgrp_classic_proto_t *protos = NULL;
1529
1575
 
1530
1576
  rd_kafka_buf_read_str(rkbuf, &GroupId);
1531
1577
  rd_kafka_buf_read_i32(rkbuf, &SessionTimeoutMs);
@@ -1578,13 +1624,13 @@ static int rd_kafka_mock_handle_JoinGroup(rd_kafka_mock_connection_t *mconn,
1578
1624
  }
1579
1625
 
1580
1626
  if (!err) {
1581
- mcgrp =
1582
- rd_kafka_mock_cgrp_get(mcluster, &GroupId, &ProtocolType);
1627
+ mcgrp = rd_kafka_mock_cgrp_classic_get(mcluster, &GroupId,
1628
+ &ProtocolType);
1583
1629
  rd_assert(mcgrp);
1584
1630
 
1585
1631
  /* This triggers an async rebalance, the response will be
1586
1632
  * sent later. */
1587
- err = rd_kafka_mock_cgrp_member_add(
1633
+ err = rd_kafka_mock_cgrp_classic_member_add(
1588
1634
  mcgrp, mconn, resp, &MemberId, &ProtocolType,
1589
1635
  &GroupInstanceId, protos, ProtocolCnt, SessionTimeoutMs);
1590
1636
  if (!err) {
@@ -1595,7 +1641,7 @@ static int rd_kafka_mock_handle_JoinGroup(rd_kafka_mock_connection_t *mconn,
1595
1641
  }
1596
1642
  }
1597
1643
 
1598
- rd_kafka_mock_cgrp_protos_destroy(protos, ProtocolCnt);
1644
+ rd_kafka_mock_cgrp_classic_protos_destroy(protos, ProtocolCnt);
1599
1645
 
1600
1646
  /* Error case */
1601
1647
  rd_kafka_buf_write_i16(resp, err); /* ErrorCode */
@@ -1612,7 +1658,7 @@ static int rd_kafka_mock_handle_JoinGroup(rd_kafka_mock_connection_t *mconn,
1612
1658
  err_parse:
1613
1659
  rd_kafka_buf_destroy(resp);
1614
1660
  if (protos)
1615
- rd_kafka_mock_cgrp_protos_destroy(protos, ProtocolCnt);
1661
+ rd_kafka_mock_cgrp_classic_protos_destroy(protos, ProtocolCnt);
1616
1662
  return -1;
1617
1663
  }
1618
1664
 
@@ -1630,8 +1676,8 @@ static int rd_kafka_mock_handle_Heartbeat(rd_kafka_mock_connection_t *mconn,
1630
1676
  rd_kafkap_str_t GroupInstanceId = RD_KAFKAP_STR_INITIALIZER;
1631
1677
  int32_t GenerationId;
1632
1678
  rd_kafka_resp_err_t err;
1633
- rd_kafka_mock_cgrp_t *mcgrp;
1634
- rd_kafka_mock_cgrp_member_t *member = NULL;
1679
+ rd_kafka_mock_cgrp_classic_t *mcgrp;
1680
+ rd_kafka_mock_cgrp_classic_member_t *member = NULL;
1635
1681
 
1636
1682
  rd_kafka_buf_read_str(rkbuf, &GroupId);
1637
1683
  rd_kafka_buf_read_i32(rkbuf, &GenerationId);
@@ -1660,23 +1706,24 @@ static int rd_kafka_mock_handle_Heartbeat(rd_kafka_mock_connection_t *mconn,
1660
1706
  }
1661
1707
 
1662
1708
  if (!err) {
1663
- mcgrp = rd_kafka_mock_cgrp_find(mcluster, &GroupId);
1709
+ mcgrp = rd_kafka_mock_cgrp_classic_find(mcluster, &GroupId);
1664
1710
  if (!mcgrp)
1665
1711
  err = RD_KAFKA_RESP_ERR_GROUP_ID_NOT_FOUND;
1666
1712
  }
1667
1713
 
1668
1714
  if (!err) {
1669
- member = rd_kafka_mock_cgrp_member_find(mcgrp, &MemberId);
1715
+ member =
1716
+ rd_kafka_mock_cgrp_classic_member_find(mcgrp, &MemberId);
1670
1717
  if (!member)
1671
1718
  err = RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID;
1672
1719
  }
1673
1720
 
1674
1721
  if (!err)
1675
- err = rd_kafka_mock_cgrp_check_state(mcgrp, member, rkbuf,
1676
- GenerationId);
1722
+ err = rd_kafka_mock_cgrp_classic_check_state(
1723
+ mcgrp, member, rkbuf, GenerationId);
1677
1724
 
1678
1725
  if (!err)
1679
- rd_kafka_mock_cgrp_member_active(mcgrp, member);
1726
+ rd_kafka_mock_cgrp_classic_member_active(mcgrp, member);
1680
1727
 
1681
1728
  rd_kafka_buf_write_i16(resp, err); /* ErrorCode */
1682
1729
 
@@ -1701,8 +1748,8 @@ static int rd_kafka_mock_handle_LeaveGroup(rd_kafka_mock_connection_t *mconn,
1701
1748
  rd_kafka_buf_t *resp = rd_kafka_mock_buf_new_response(rkbuf);
1702
1749
  rd_kafkap_str_t GroupId, MemberId;
1703
1750
  rd_kafka_resp_err_t err;
1704
- rd_kafka_mock_cgrp_t *mcgrp;
1705
- rd_kafka_mock_cgrp_member_t *member = NULL;
1751
+ rd_kafka_mock_cgrp_classic_t *mcgrp;
1752
+ rd_kafka_mock_cgrp_classic_member_t *member = NULL;
1706
1753
 
1707
1754
  rd_kafka_buf_read_str(rkbuf, &GroupId);
1708
1755
  rd_kafka_buf_read_str(rkbuf, &MemberId);
@@ -1729,22 +1776,24 @@ static int rd_kafka_mock_handle_LeaveGroup(rd_kafka_mock_connection_t *mconn,
1729
1776
  }
1730
1777
 
1731
1778
  if (!err) {
1732
- mcgrp = rd_kafka_mock_cgrp_find(mcluster, &GroupId);
1779
+ mcgrp = rd_kafka_mock_cgrp_classic_find(mcluster, &GroupId);
1733
1780
  if (!mcgrp)
1734
1781
  err = RD_KAFKA_RESP_ERR_GROUP_ID_NOT_FOUND;
1735
1782
  }
1736
1783
 
1737
1784
  if (!err) {
1738
- member = rd_kafka_mock_cgrp_member_find(mcgrp, &MemberId);
1785
+ member =
1786
+ rd_kafka_mock_cgrp_classic_member_find(mcgrp, &MemberId);
1739
1787
  if (!member)
1740
1788
  err = RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID;
1741
1789
  }
1742
1790
 
1743
1791
  if (!err)
1744
- err = rd_kafka_mock_cgrp_check_state(mcgrp, member, rkbuf, -1);
1792
+ err = rd_kafka_mock_cgrp_classic_check_state(mcgrp, member,
1793
+ rkbuf, -1);
1745
1794
 
1746
1795
  if (!err)
1747
- rd_kafka_mock_cgrp_member_leave(mcgrp, member);
1796
+ rd_kafka_mock_cgrp_classic_member_leave(mcgrp, member);
1748
1797
 
1749
1798
  rd_kafka_buf_write_i16(resp, err); /* ErrorCode */
1750
1799
 
@@ -1773,8 +1822,8 @@ static int rd_kafka_mock_handle_SyncGroup(rd_kafka_mock_connection_t *mconn,
1773
1822
  int32_t GenerationId, AssignmentCnt;
1774
1823
  int32_t i;
1775
1824
  rd_kafka_resp_err_t err;
1776
- rd_kafka_mock_cgrp_t *mcgrp = NULL;
1777
- rd_kafka_mock_cgrp_member_t *member = NULL;
1825
+ rd_kafka_mock_cgrp_classic_t *mcgrp = NULL;
1826
+ rd_kafka_mock_cgrp_classic_member_t *member = NULL;
1778
1827
 
1779
1828
  rd_kafka_buf_read_str(rkbuf, &GroupId);
1780
1829
  rd_kafka_buf_read_i32(rkbuf, &GenerationId);
@@ -1804,23 +1853,24 @@ static int rd_kafka_mock_handle_SyncGroup(rd_kafka_mock_connection_t *mconn,
1804
1853
  }
1805
1854
 
1806
1855
  if (!err) {
1807
- mcgrp = rd_kafka_mock_cgrp_find(mcluster, &GroupId);
1856
+ mcgrp = rd_kafka_mock_cgrp_classic_find(mcluster, &GroupId);
1808
1857
  if (!mcgrp)
1809
1858
  err = RD_KAFKA_RESP_ERR_GROUP_ID_NOT_FOUND;
1810
1859
  }
1811
1860
 
1812
1861
  if (!err) {
1813
- member = rd_kafka_mock_cgrp_member_find(mcgrp, &MemberId);
1862
+ member =
1863
+ rd_kafka_mock_cgrp_classic_member_find(mcgrp, &MemberId);
1814
1864
  if (!member)
1815
1865
  err = RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID;
1816
1866
  }
1817
1867
 
1818
1868
  if (!err)
1819
- err = rd_kafka_mock_cgrp_check_state(mcgrp, member, rkbuf,
1820
- GenerationId);
1869
+ err = rd_kafka_mock_cgrp_classic_check_state(
1870
+ mcgrp, member, rkbuf, GenerationId);
1821
1871
 
1822
1872
  if (!err)
1823
- rd_kafka_mock_cgrp_member_active(mcgrp, member);
1873
+ rd_kafka_mock_cgrp_classic_member_active(mcgrp, member);
1824
1874
 
1825
1875
  if (!err) {
1826
1876
  rd_bool_t is_leader = mcgrp->leader && mcgrp->leader == member;
@@ -1836,7 +1886,7 @@ static int rd_kafka_mock_handle_SyncGroup(rd_kafka_mock_connection_t *mconn,
1836
1886
  for (i = 0; i < AssignmentCnt; i++) {
1837
1887
  rd_kafkap_str_t MemberId2;
1838
1888
  rd_kafkap_bytes_t Metadata;
1839
- rd_kafka_mock_cgrp_member_t *member2;
1889
+ rd_kafka_mock_cgrp_classic_member_t *member2;
1840
1890
 
1841
1891
  rd_kafka_buf_read_str(rkbuf, &MemberId2);
1842
1892
  rd_kafka_buf_read_kbytes(rkbuf, &Metadata);
@@ -1845,17 +1895,18 @@ static int rd_kafka_mock_handle_SyncGroup(rd_kafka_mock_connection_t *mconn,
1845
1895
  continue;
1846
1896
 
1847
1897
  /* Find member */
1848
- member2 = rd_kafka_mock_cgrp_member_find(mcgrp, &MemberId2);
1898
+ member2 =
1899
+ rd_kafka_mock_cgrp_classic_member_find(mcgrp, &MemberId2);
1849
1900
  if (!member2)
1850
1901
  continue;
1851
1902
 
1852
- rd_kafka_mock_cgrp_member_assignment_set(mcgrp, member2,
1853
- &Metadata);
1903
+ rd_kafka_mock_cgrp_classic_member_assignment_set(mcgrp, member2,
1904
+ &Metadata);
1854
1905
  }
1855
1906
 
1856
1907
  if (!err) {
1857
- err = rd_kafka_mock_cgrp_member_sync_set(mcgrp, member, mconn,
1858
- resp);
1908
+ err = rd_kafka_mock_cgrp_classic_member_sync_set(mcgrp, member,
1909
+ mconn, resp);
1859
1910
  /* .._sync_set() assumes ownership of resp */
1860
1911
  if (!err)
1861
1912
  return 0; /* Response will be sent when all members
@@ -2645,6 +2696,7 @@ static int rd_kafka_mock_handle_PushTelemetry(rd_kafka_mock_connection_t *mconn,
2645
2696
  rd_kafka_Uuid_t ClientInstanceId;
2646
2697
  int32_t SubscriptionId;
2647
2698
  rd_bool_t terminating;
2699
+ int8_t CompressionType;
2648
2700
  rd_kafka_compression_t compression_type = RD_KAFKA_COMPRESSION_NONE;
2649
2701
  rd_kafkap_bytes_t metrics;
2650
2702
  rd_kafka_resp_err_t err;
@@ -2652,11 +2704,13 @@ static int rd_kafka_mock_handle_PushTelemetry(rd_kafka_mock_connection_t *mconn,
2652
2704
  rd_kafka_buf_read_uuid(rkbuf, &ClientInstanceId);
2653
2705
  rd_kafka_buf_read_i32(rkbuf, &SubscriptionId);
2654
2706
  rd_kafka_buf_read_bool(rkbuf, &terminating);
2655
- rd_kafka_buf_read_i8(rkbuf, &compression_type);
2707
+ rd_kafka_buf_read_i8(rkbuf, &CompressionType);
2708
+ compression_type = CompressionType;
2656
2709
  rd_kafka_buf_read_kbytes(rkbuf, &metrics);
2657
2710
 
2658
2711
  void *uncompressed_payload = NULL;
2659
2712
  size_t uncompressed_payload_len = 0;
2713
+ rd_assert(metrics.data != NULL);
2660
2714
 
2661
2715
  if (compression_type != RD_KAFKA_COMPRESSION_NONE) {
2662
2716
  rd_rkb_log(rkb, LOG_DEBUG, "MOCKTELEMETRY",
@@ -2678,6 +2732,7 @@ static int rd_kafka_mock_handle_PushTelemetry(rd_kafka_mock_connection_t *mconn,
2678
2732
  uncompressed_payload_len = metrics.len;
2679
2733
  }
2680
2734
 
2735
+ rd_assert(uncompressed_payload != NULL);
2681
2736
  rd_kafka_mock_handle_PushTelemetry_payload(rkb, uncompressed_payload,
2682
2737
  uncompressed_payload_len);
2683
2738
  if (compression_type != RD_KAFKA_COMPRESSION_NONE)
@@ -2698,6 +2753,245 @@ err_parse:
2698
2753
  rd_kafka_buf_destroy(resp);
2699
2754
  return -1;
2700
2755
  }
2756
+ static void rd_kafka_mock_handle_ConsumerGroupHeartbeat_write_TopicPartitions(
2757
+ rd_kafka_buf_t *rkbuf,
2758
+ rd_kafka_topic_partition_list_t *rktparlist) {
2759
+ const rd_kafka_topic_partition_field_t fields[] = {
2760
+ RD_KAFKA_TOPIC_PARTITION_FIELD_PARTITION,
2761
+ RD_KAFKA_TOPIC_PARTITION_FIELD_END};
2762
+ rd_kafka_topic_partition_list_sort_by_topic_id(rktparlist);
2763
+ rd_kafka_buf_write_topic_partitions(
2764
+ rkbuf, rktparlist, rd_false /*don't skip invalid offsets*/,
2765
+ rd_false /*any offset*/, rd_true /* use_topic id */,
2766
+ rd_false /* don't use topic name */, fields);
2767
+ }
2768
+
2769
+ static int
2770
+ rd_kafka_mock_handle_ConsumerGroupHeartbeat(rd_kafka_mock_connection_t *mconn,
2771
+ rd_kafka_buf_t *rkbuf) {
2772
+ const rd_bool_t log_decode_errors = rd_true;
2773
+ rd_bool_t sent_assignment_parse_err = rd_false;
2774
+ rd_kafka_mock_cluster_t *mcluster = mconn->broker->cluster;
2775
+ rd_kafka_buf_t *resp = rd_kafka_mock_buf_new_response(rkbuf);
2776
+ rd_kafka_topic_partition_list_t *sent_assignment = NULL,
2777
+ *existing_assignment = NULL,
2778
+ *next_assignment = NULL;
2779
+ rd_kafka_topic_partition_t *rktpar;
2780
+ rd_kafkap_str_t GroupId, MemberId, InstanceId, RackId, ServerAssignor,
2781
+ SubscribedTopicRegex;
2782
+ rd_kafkap_str_t *SubscribedTopicNames = NULL;
2783
+ int32_t MemberEpoch, RebalanceTimeoutMs, SubscribedTopicNamesCnt;
2784
+ int32_t i;
2785
+ rd_kafka_resp_err_t err;
2786
+ rd_kafka_mock_cgrp_consumer_t *mcgrp = NULL;
2787
+ rd_kafka_mock_broker_t *mrkb = NULL;
2788
+ rd_kafka_mock_cgrp_consumer_member_t *member = NULL;
2789
+
2790
+ /* GroupId */
2791
+ rd_kafka_buf_read_str(rkbuf, &GroupId);
2792
+ rd_assert(!RD_KAFKAP_STR_IS_NULL(&GroupId));
2793
+
2794
+ /* MemberId */
2795
+ rd_kafka_buf_read_str(rkbuf, &MemberId);
2796
+ rd_assert(!RD_KAFKAP_STR_IS_NULL(&MemberId));
2797
+
2798
+ /* MemberEpoch */
2799
+ rd_kafka_buf_read_i32(rkbuf, &MemberEpoch);
2800
+ rd_assert(MemberEpoch >= -2);
2801
+
2802
+ /* InstanceId */
2803
+ rd_kafka_buf_read_str(rkbuf, &InstanceId);
2804
+
2805
+ /* RackId */
2806
+ rd_kafka_buf_read_str(rkbuf, &RackId);
2807
+
2808
+ /* RebalanceTimeoutMs */
2809
+ rd_kafka_buf_read_i32(rkbuf, &RebalanceTimeoutMs);
2810
+ rd_assert(RebalanceTimeoutMs >= -1);
2811
+
2812
+ /* #SubscribedTopicNames */
2813
+ rd_kafka_buf_read_arraycnt(rkbuf, &SubscribedTopicNamesCnt,
2814
+ RD_KAFKAP_TOPICS_MAX);
2815
+ if (SubscribedTopicNamesCnt >= 0) {
2816
+ SubscribedTopicNames = rd_calloc(
2817
+ SubscribedTopicNamesCnt > 0 ? SubscribedTopicNamesCnt : 1,
2818
+ sizeof(rd_kafkap_str_t));
2819
+ for (i = 0; i < SubscribedTopicNamesCnt; i++) {
2820
+ /* SubscribedTopicNames[i] */
2821
+ rd_kafka_buf_read_str(rkbuf, &SubscribedTopicNames[i]);
2822
+ }
2823
+ }
2824
+
2825
+ rd_kafka_buf_read_str(rkbuf, &SubscribedTopicRegex);
2826
+
2827
+ /* ServerAssignor */
2828
+ rd_kafka_buf_read_str(rkbuf, &ServerAssignor);
2829
+
2830
+ /* #TopicPartitions */
2831
+ const rd_kafka_topic_partition_field_t sent_assignment_fields[] = {
2832
+ RD_KAFKA_TOPIC_PARTITION_FIELD_PARTITION,
2833
+ RD_KAFKA_TOPIC_PARTITION_FIELD_END};
2834
+ sent_assignment = rd_kafka_buf_read_topic_partitions_nullable(
2835
+ rkbuf, rd_true, rd_false, 0, sent_assignment_fields,
2836
+ &sent_assignment_parse_err);
2837
+ if (sent_assignment_parse_err)
2838
+ goto err_parse;
2839
+
2840
+ if (sent_assignment) {
2841
+ rd_kafka_Uuid_t last_topic_id = RD_KAFKA_UUID_ZERO;
2842
+ rd_kafka_mock_topic_t *mtopic = NULL;
2843
+ existing_assignment =
2844
+ rd_kafka_topic_partition_list_new(sent_assignment->cnt);
2845
+ RD_KAFKA_TPLIST_FOREACH(rktpar, sent_assignment) {
2846
+ rd_kafka_Uuid_t current_topic_id =
2847
+ rd_kafka_topic_partition_get_topic_id(rktpar);
2848
+
2849
+ if (rd_kafka_Uuid_cmp(current_topic_id,
2850
+ last_topic_id) != 0) {
2851
+ last_topic_id = current_topic_id;
2852
+ mtopic = rd_kafka_mock_topic_find_by_id(
2853
+ mcluster, current_topic_id);
2854
+ }
2855
+
2856
+ if (mtopic) {
2857
+ rd_kafka_topic_partition_t *added =
2858
+ rd_kafka_topic_partition_list_add(
2859
+ existing_assignment, "",
2860
+ rktpar->partition);
2861
+ rd_kafka_topic_partition_set_topic_id(
2862
+ added, last_topic_id);
2863
+ }
2864
+ }
2865
+ }
2866
+
2867
+ /* Inject error, if any */
2868
+ err = rd_kafka_mock_next_request_error(mconn, resp);
2869
+
2870
+ if (!err) {
2871
+ mrkb = rd_kafka_mock_cluster_get_coord(
2872
+ mcluster, RD_KAFKA_COORD_GROUP, &GroupId);
2873
+
2874
+ if (!mrkb)
2875
+ err = RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE;
2876
+ else if (mrkb != mconn->broker)
2877
+ err = RD_KAFKA_RESP_ERR_NOT_COORDINATOR;
2878
+ }
2879
+
2880
+ if (!err) {
2881
+ mtx_lock(&mcluster->lock);
2882
+ mcgrp = rd_kafka_mock_cgrp_consumer_get(mcluster, &GroupId);
2883
+ rd_assert(mcgrp);
2884
+
2885
+ member = rd_kafka_mock_cgrp_consumer_member_add(
2886
+ mcgrp, mconn, &MemberId, &InstanceId, SubscribedTopicNames,
2887
+ SubscribedTopicNamesCnt, &SubscribedTopicRegex);
2888
+
2889
+ if (member) {
2890
+ if (MemberEpoch >= 0) {
2891
+ next_assignment =
2892
+ rd_kafka_mock_cgrp_consumer_member_next_assignment(
2893
+ member, existing_assignment,
2894
+ &MemberEpoch);
2895
+ if (MemberEpoch < 0) {
2896
+ err =
2897
+ RD_KAFKA_RESP_ERR_FENCED_MEMBER_EPOCH;
2898
+ }
2899
+ } else {
2900
+ rd_kafka_mock_cgrp_consumer_member_leave(
2901
+ mcgrp, member, MemberEpoch == -2);
2902
+ member = NULL;
2903
+ }
2904
+ } else {
2905
+ err = RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID;
2906
+ }
2907
+ mtx_unlock(&mcluster->lock);
2908
+ } else {
2909
+ switch (err) {
2910
+ case RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID:
2911
+ case RD_KAFKA_RESP_ERR_FENCED_MEMBER_EPOCH:
2912
+ /* In case the error was set
2913
+ * by `rd_kafka_mock_next_request_error`. */
2914
+ MemberEpoch = -1;
2915
+ mtx_lock(&mcluster->lock);
2916
+ mcgrp = rd_kafka_mock_cgrp_consumer_find(mcluster,
2917
+ &GroupId);
2918
+ if (!mcgrp) {
2919
+ mtx_unlock(&mcluster->lock);
2920
+ break;
2921
+ }
2922
+
2923
+ rd_kafka_mock_cgrp_consumer_member_t *member =
2924
+ rd_kafka_mock_cgrp_consumer_member_find(mcgrp,
2925
+ &MemberId);
2926
+ if (member) {
2927
+ rd_kafka_mock_cgrp_consumer_member_fenced(
2928
+ mcgrp, member);
2929
+ member = NULL;
2930
+ }
2931
+ mtx_unlock(&mcluster->lock);
2932
+ default:
2933
+ break;
2934
+ }
2935
+ }
2936
+
2937
+ /*
2938
+ * Construct response
2939
+ */
2940
+ /* Response: Throttle */
2941
+ rd_kafka_buf_write_i32(resp, 0);
2942
+
2943
+ /* Response: ErrorCode */
2944
+ rd_kafka_buf_write_i16(resp, err);
2945
+
2946
+ /* Response: ErrorMessage */
2947
+ rd_kafka_buf_write_str(resp, rd_kafka_err2str(err), -1);
2948
+
2949
+ /* Response: MemberId */
2950
+ if (!err && member)
2951
+ rd_kafka_buf_write_str(resp, member->id, -1);
2952
+ else
2953
+ rd_kafka_buf_write_str(resp, NULL, -1);
2954
+
2955
+ /* Response: MemberEpoch */
2956
+ rd_kafka_buf_write_i32(resp, MemberEpoch);
2957
+
2958
+ /* Response: HeartbeatIntervalMs */
2959
+ if (mcgrp) {
2960
+ rd_kafka_buf_write_i32(resp, mcgrp->heartbeat_interval_ms);
2961
+ } else {
2962
+ rd_kafka_buf_write_i32(resp, 0);
2963
+ }
2964
+
2965
+ if (next_assignment) {
2966
+ /* Response: Assignment */
2967
+ rd_kafka_buf_write_i8(resp, 1);
2968
+
2969
+ /* Response: TopicPartitions */
2970
+ rd_kafka_mock_handle_ConsumerGroupHeartbeat_write_TopicPartitions(
2971
+ resp, next_assignment);
2972
+
2973
+ rd_kafka_buf_write_tags_empty(resp);
2974
+ } else {
2975
+ /* Response: Assignment */
2976
+ rd_kafka_buf_write_i8(resp, -1);
2977
+ }
2978
+
2979
+ rd_kafka_mock_connection_send_response(mconn, resp);
2980
+
2981
+ rd_free(SubscribedTopicNames);
2982
+ RD_IF_FREE(sent_assignment, rd_kafka_topic_partition_list_destroy);
2983
+ RD_IF_FREE(existing_assignment, rd_kafka_topic_partition_list_destroy);
2984
+ RD_IF_FREE(next_assignment, rd_kafka_topic_partition_list_destroy);
2985
+ return 0;
2986
+
2987
+ err_parse:
2988
+ RD_IF_FREE(SubscribedTopicNames, rd_free);
2989
+ RD_IF_FREE(sent_assignment, rd_kafka_topic_partition_list_destroy);
2990
+ RD_IF_FREE(existing_assignment, rd_kafka_topic_partition_list_destroy);
2991
+ RD_IF_FREE(next_assignment, rd_kafka_topic_partition_list_destroy);
2992
+ rd_kafka_buf_destroy(resp);
2993
+ return -1;
2994
+ }
2701
2995
 
2702
2996
  /**
2703
2997
  * @brief Default request handlers
@@ -2715,7 +3009,7 @@ const struct rd_kafka_mock_api_handler
2715
3009
  [RD_KAFKAP_FindCoordinator] = {0, 3, 3,
2716
3010
  rd_kafka_mock_handle_FindCoordinator},
2717
3011
  [RD_KAFKAP_InitProducerId] = {0, 4, 2,
2718
- rd_kafka_mock_handle_InitProducerId},
3012
+ rd_kafka_mock_handle_InitProducerId},
2719
3013
  [RD_KAFKAP_JoinGroup] = {0, 6, 6, rd_kafka_mock_handle_JoinGroup},
2720
3014
  [RD_KAFKAP_Heartbeat] = {0, 5, 4, rd_kafka_mock_handle_Heartbeat},
2721
3015
  [RD_KAFKAP_LeaveGroup] = {0, 4, 4, rd_kafka_mock_handle_LeaveGroup},
@@ -2729,6 +3023,8 @@ const struct rd_kafka_mock_api_handler
2729
3023
  [RD_KAFKAP_EndTxn] = {0, 1, -1, rd_kafka_mock_handle_EndTxn},
2730
3024
  [RD_KAFKAP_OffsetForLeaderEpoch] =
2731
3025
  {2, 2, -1, rd_kafka_mock_handle_OffsetForLeaderEpoch},
3026
+ [RD_KAFKAP_ConsumerGroupHeartbeat] =
3027
+ {1, 1, 1, rd_kafka_mock_handle_ConsumerGroupHeartbeat},
2732
3028
  [RD_KAFKAP_GetTelemetrySubscriptions] =
2733
3029
  {0, 0, 0, rd_kafka_mock_handle_GetTelemetrySubscriptions},
2734
3030
  [RD_KAFKAP_PushTelemetry] = {0, 0, 0,