@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.
- package/README.md +5 -5
- package/bench/seed.sh +0 -0
- package/binding.gyp +8 -1
- package/ci/prepublish.js +0 -1
- package/config.d.ts +126 -10
- package/configure +0 -0
- package/deps/librdkafka/.semaphore/run-all-tests.yml +77 -0
- package/deps/librdkafka/.semaphore/semaphore-integration.yml +250 -0
- package/deps/librdkafka/.semaphore/semaphore.yml +67 -44
- package/deps/librdkafka/.semaphore/verify-linux-packages.yml +41 -0
- package/deps/librdkafka/CHANGELOG.md +471 -1
- package/deps/librdkafka/CONFIGURATION.md +29 -9
- package/deps/librdkafka/INTRODUCTION.md +909 -601
- package/deps/librdkafka/LICENSES.txt +592 -1
- package/deps/librdkafka/Makefile +2 -1
- package/deps/librdkafka/_mkltmpuuWEwa.c +13 -0
- package/deps/librdkafka/configure +0 -0
- package/deps/librdkafka/debian/rules +0 -0
- package/deps/librdkafka/dev-conf.sh +0 -0
- package/deps/librdkafka/examples/consumer.c +18 -8
- package/deps/librdkafka/examples/describe_consumer_groups.c +25 -6
- package/deps/librdkafka/examples/incremental_alter_configs.c +4 -5
- package/deps/librdkafka/examples/kafkatest_verifiable_client.cpp +26 -42
- package/deps/librdkafka/examples/openssl_engine_example.cpp +3 -4
- package/deps/librdkafka/examples/producer.cpp +2 -2
- package/deps/librdkafka/examples/user_scram.c +4 -5
- package/deps/librdkafka/examples/win_ssl_cert_store.cpp +4 -3
- package/deps/librdkafka/lds-gen.py +0 -0
- package/deps/librdkafka/mklove/Makefile.base +0 -0
- package/deps/librdkafka/packaging/RELEASE.md +8 -0
- package/deps/librdkafka/packaging/alpine/build-alpine.sh +0 -0
- package/deps/librdkafka/packaging/cp/README.md +4 -1
- package/deps/librdkafka/packaging/cp/check_features.c +12 -4
- package/deps/librdkafka/packaging/cp/verify-deb.sh +6 -6
- package/deps/librdkafka/packaging/cp/verify-packages.sh +52 -31
- package/deps/librdkafka/packaging/cp/verify-rpm.sh +6 -13
- package/deps/librdkafka/packaging/debian/rules +0 -0
- package/deps/librdkafka/packaging/get_version.py +0 -0
- package/deps/librdkafka/packaging/homebrew/brew-update-pr.sh +0 -0
- package/deps/librdkafka/packaging/mingw-w64/{travis-before-install.sh → export-variables.sh} +0 -7
- package/deps/librdkafka/packaging/mingw-w64/semaphoreci-build.sh +1 -1
- package/deps/librdkafka/packaging/nuget/artifact.py +0 -0
- package/deps/librdkafka/packaging/nuget/cleanup-s3.py +0 -0
- package/deps/librdkafka/packaging/nuget/nuget.sh +0 -0
- package/deps/librdkafka/packaging/nuget/packaging.py +0 -0
- package/deps/librdkafka/packaging/nuget/push-to-nuget.sh +0 -0
- package/deps/librdkafka/packaging/nuget/release.py +0 -0
- package/deps/librdkafka/packaging/nuget/requirements.txt +3 -3
- package/deps/librdkafka/packaging/rpm/mock-on-docker.sh +0 -0
- package/deps/librdkafka/packaging/rpm/tests/run-test.sh +0 -0
- package/deps/librdkafka/packaging/rpm/tests/test-on-docker.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-configurations-checks.sh +3 -1
- package/deps/librdkafka/packaging/tools/build-deb-package.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-debian.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-manylinux.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-release-artifacts.sh +0 -0
- package/deps/librdkafka/packaging/tools/distro-build.sh +0 -0
- package/deps/librdkafka/packaging/tools/gh-release-checksums.py +0 -0
- package/deps/librdkafka/packaging/tools/rdutcoverage.sh +0 -0
- package/deps/librdkafka/packaging/tools/run-in-docker.sh +28 -0
- package/deps/librdkafka/packaging/tools/run-integration-tests.sh +31 -0
- package/deps/librdkafka/packaging/tools/run-style-check.sh +4 -0
- package/deps/librdkafka/packaging/tools/style-format.sh +6 -5
- package/deps/librdkafka/packaging/tools/update_rpcs_max_versions.py +100 -0
- package/deps/librdkafka/service.yml +154 -0
- package/deps/librdkafka/src/generate_proto.sh +0 -0
- package/deps/librdkafka/src/rd.h +145 -2
- package/deps/librdkafka/src/rdaddr.h +6 -7
- package/deps/librdkafka/src/rdatomic.h +15 -11
- package/deps/librdkafka/src/rdavg.h +3 -2
- package/deps/librdkafka/src/rdbase64.c +33 -2
- package/deps/librdkafka/src/rdbase64.h +2 -0
- package/deps/librdkafka/src/rdendian.h +10 -9
- package/deps/librdkafka/src/rdhttp.c +418 -100
- package/deps/librdkafka/src/rdhttp.h +23 -5
- package/deps/librdkafka/src/rdkafka.c +299 -145
- package/deps/librdkafka/src/rdkafka.h +89 -6
- package/deps/librdkafka/src/rdkafka_admin.c +482 -105
- package/deps/librdkafka/src/rdkafka_admin.h +42 -0
- package/deps/librdkafka/src/rdkafka_broker.c +463 -312
- package/deps/librdkafka/src/rdkafka_broker.h +68 -10
- package/deps/librdkafka/src/rdkafka_buf.c +8 -5
- package/deps/librdkafka/src/rdkafka_buf.h +4 -3
- package/deps/librdkafka/src/rdkafka_cert.c +25 -1
- package/deps/librdkafka/src/rdkafka_cert.h +4 -3
- package/deps/librdkafka/src/rdkafka_cgrp.c +468 -143
- package/deps/librdkafka/src/rdkafka_cgrp.h +36 -2
- package/deps/librdkafka/src/rdkafka_conf.c +526 -102
- package/deps/librdkafka/src/rdkafka_conf.h +68 -4
- package/deps/librdkafka/src/rdkafka_feature.c +472 -35
- package/deps/librdkafka/src/rdkafka_feature.h +2 -0
- package/deps/librdkafka/src/rdkafka_fetcher.c +22 -2
- package/deps/librdkafka/src/rdkafka_fetcher.h +2 -2
- package/deps/librdkafka/src/rdkafka_int.h +84 -46
- package/deps/librdkafka/src/rdkafka_metadata.c +221 -136
- package/deps/librdkafka/src/rdkafka_metadata.h +15 -11
- package/deps/librdkafka/src/rdkafka_metadata_cache.c +279 -73
- package/deps/librdkafka/src/rdkafka_mock.c +795 -19
- package/deps/librdkafka/src/rdkafka_mock.h +119 -0
- package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1298 -132
- package/deps/librdkafka/src/rdkafka_mock_handlers.c +345 -49
- package/deps/librdkafka/src/rdkafka_mock_int.h +180 -61
- package/deps/librdkafka/src/rdkafka_msg.c +35 -19
- package/deps/librdkafka/src/rdkafka_msg.h +3 -3
- package/deps/librdkafka/src/rdkafka_msgset_writer.c +14 -10
- package/deps/librdkafka/src/rdkafka_offset.c +33 -5
- package/deps/librdkafka/src/rdkafka_op.c +1 -1
- package/deps/librdkafka/src/rdkafka_op.h +45 -21
- package/deps/librdkafka/src/rdkafka_partition.c +118 -23
- package/deps/librdkafka/src/rdkafka_partition.h +16 -7
- package/deps/librdkafka/src/rdkafka_proto.h +4 -1
- package/deps/librdkafka/src/rdkafka_protocol.h +1 -0
- package/deps/librdkafka/src/rdkafka_queue.c +125 -48
- package/deps/librdkafka/src/rdkafka_queue.h +19 -0
- package/deps/librdkafka/src/rdkafka_range_assignor.c +1 -1
- package/deps/librdkafka/src/rdkafka_request.c +336 -64
- package/deps/librdkafka/src/rdkafka_request.h +24 -1
- package/deps/librdkafka/src/rdkafka_sasl.c +5 -3
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +14 -10
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1166 -89
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +13 -3
- package/deps/librdkafka/src/rdkafka_sasl_plain.c +3 -3
- package/deps/librdkafka/src/rdkafka_sasl_scram.c +4 -3
- package/deps/librdkafka/src/rdkafka_ssl.c +306 -81
- package/deps/librdkafka/src/rdkafka_ssl.h +22 -0
- package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4 -0
- package/deps/librdkafka/src/rdkafka_telemetry.c +80 -23
- package/deps/librdkafka/src/rdkafka_telemetry_encode.c +5 -1
- package/deps/librdkafka/src/rdkafka_telemetry_encode.h +20 -20
- package/deps/librdkafka/src/rdkafka_topic.c +220 -137
- package/deps/librdkafka/src/rdkafka_topic.h +14 -8
- package/deps/librdkafka/src/rdkafka_transport.c +59 -47
- package/deps/librdkafka/src/rdkafka_transport.h +5 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.c +6 -1
- package/deps/librdkafka/src/rdmap.c +6 -1
- package/deps/librdkafka/src/rdrand.c +11 -1
- package/deps/librdkafka/src/rdtime.h +48 -17
- package/deps/librdkafka/src/rdunittest.c +42 -25
- package/deps/librdkafka/src/rdunittest.h +2 -0
- package/deps/librdkafka/src/rdwin32.h +1 -1
- package/deps/librdkafka/src/regexp.c +47 -42
- package/deps/librdkafka/src/tinycthread_extra.c +45 -21
- package/deps/librdkafka/src/tinycthread_extra.h +7 -3
- package/deps/librdkafka/src-cpp/rdkafkacpp.h +28 -2
- package/deps/librdkafka/tests/0001-multiobj.c +4 -0
- package/deps/librdkafka/tests/0004-conf.c +103 -36
- package/deps/librdkafka/tests/0009-mock_cluster.c +1 -0
- package/deps/librdkafka/tests/0011-produce_batch.c +2 -1
- package/deps/librdkafka/tests/0016-client_swname.c +18 -3
- package/deps/librdkafka/tests/0017-compression.c +6 -8
- package/deps/librdkafka/tests/0018-cgrp_term.c +8 -3
- package/deps/librdkafka/tests/0021-rkt_destroy.c +1 -0
- package/deps/librdkafka/tests/0022-consume_batch.c +4 -1
- package/deps/librdkafka/tests/0026-consume_pause.c +12 -14
- package/deps/librdkafka/tests/0028-long_topicnames.c +1 -1
- package/deps/librdkafka/tests/0029-assign_offset.c +6 -8
- package/deps/librdkafka/tests/0030-offset_commit.c +2 -2
- package/deps/librdkafka/tests/0033-regex_subscribe.c +33 -17
- package/deps/librdkafka/tests/0034-offset_reset.c +25 -4
- package/deps/librdkafka/tests/0036-partial_fetch.c +1 -0
- package/deps/librdkafka/tests/0038-performance.c +1 -0
- package/deps/librdkafka/tests/0040-io_event.c +11 -5
- package/deps/librdkafka/tests/0041-fetch_max_bytes.c +1 -0
- package/deps/librdkafka/tests/0044-partition_cnt.c +3 -2
- package/deps/librdkafka/tests/0045-subscribe_update.c +284 -20
- package/deps/librdkafka/tests/0047-partial_buf_tmout.c +1 -0
- package/deps/librdkafka/tests/0048-partitioner.c +1 -1
- package/deps/librdkafka/tests/0050-subscribe_adds.c +1 -0
- package/deps/librdkafka/tests/0051-assign_adds.c +1 -0
- package/deps/librdkafka/tests/0052-msg_timestamps.c +22 -4
- package/deps/librdkafka/tests/0053-stats_cb.cpp +12 -20
- package/deps/librdkafka/tests/0055-producer_latency.c +176 -3
- package/deps/librdkafka/tests/0056-balanced_group_mt.c +6 -2
- package/deps/librdkafka/tests/0058-log.cpp +3 -3
- package/deps/librdkafka/tests/0059-bsearch.cpp +8 -4
- package/deps/librdkafka/tests/0061-consumer_lag.cpp +25 -5
- package/deps/librdkafka/tests/0067-empty_topic.cpp +3 -0
- package/deps/librdkafka/tests/0068-produce_timeout.c +21 -23
- package/deps/librdkafka/tests/0069-consumer_add_parts.c +3 -7
- package/deps/librdkafka/tests/0075-retry.c +38 -1
- package/deps/librdkafka/tests/0076-produce_retry.c +2 -0
- package/deps/librdkafka/tests/0077-compaction.c +8 -2
- package/deps/librdkafka/tests/0080-admin_ut.c +34 -4
- package/deps/librdkafka/tests/0081-admin.c +455 -155
- package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +4 -0
- package/deps/librdkafka/tests/0083-cb_event.c +8 -3
- package/deps/librdkafka/tests/0084-destroy_flags.c +14 -18
- package/deps/librdkafka/tests/0085-headers.cpp +4 -0
- package/deps/librdkafka/tests/0086-purge.c +40 -7
- package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +1 -1
- package/deps/librdkafka/tests/0089-max_poll_interval.c +12 -7
- package/deps/librdkafka/tests/0090-idempotence.c +1 -2
- package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +5 -7
- package/deps/librdkafka/tests/0092-mixed_msgver.c +6 -0
- package/deps/librdkafka/tests/0093-holb.c +8 -5
- package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +1 -0
- package/deps/librdkafka/tests/0097-ssl_verify.cpp +262 -70
- package/deps/librdkafka/tests/0098-consumer-txn.cpp +16 -16
- package/deps/librdkafka/tests/0099-commit_metadata.c +1 -1
- package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +1 -1
- package/deps/librdkafka/tests/0102-static_group_rebalance.c +317 -16
- package/deps/librdkafka/tests/0103-transactions.c +7 -7
- package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +1 -0
- package/deps/librdkafka/tests/0105-transactions_mock.c +18 -11
- package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +35 -14
- package/deps/librdkafka/tests/0107-topic_recreate.c +2 -2
- package/deps/librdkafka/tests/0109-auto_create_topics.cpp +86 -26
- package/deps/librdkafka/tests/0110-batch_size.cpp +1 -2
- package/deps/librdkafka/tests/0112-assign_unknown_part.c +3 -14
- package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +248 -104
- package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +3 -3
- package/deps/librdkafka/tests/0115-producer_auth.cpp +4 -1
- package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +7 -5
- package/deps/librdkafka/tests/0117-mock_errors.c +15 -5
- package/deps/librdkafka/tests/0118-commit_rebalance.c +41 -8
- package/deps/librdkafka/tests/0119-consumer_auth.cpp +20 -1
- package/deps/librdkafka/tests/0120-asymmetric_subscription.c +8 -3
- package/deps/librdkafka/tests/0125-immediate_flush.c +1 -1
- package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +323 -8
- package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +1 -0
- package/deps/librdkafka/tests/0132-strategy_ordering.c +12 -4
- package/deps/librdkafka/tests/0133-ssl_keys.c +28 -6
- package/deps/librdkafka/tests/0137-barrier_batch_consume.c +24 -14
- package/deps/librdkafka/tests/0139-offset_validation_mock.c +510 -2
- package/deps/librdkafka/tests/0140-commit_metadata.cpp +1 -1
- package/deps/librdkafka/tests/0142-reauthentication.c +37 -17
- package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +39 -40
- package/deps/librdkafka/tests/0146-metadata_mock.c +76 -15
- package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +952 -0
- package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +563 -0
- package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
- package/deps/librdkafka/tests/0150-telemetry_mock.c +9 -6
- package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
- package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
- package/deps/librdkafka/tests/0153-memberid.c +128 -0
- package/deps/librdkafka/tests/CMakeLists.txt +6 -0
- package/deps/librdkafka/tests/LibrdkafkaTestApp.py +34 -9
- package/deps/librdkafka/tests/autotest.sh +0 -0
- package/deps/librdkafka/tests/broker_version_tests.py +0 -0
- package/deps/librdkafka/tests/buildbox.sh +0 -0
- package/deps/librdkafka/tests/cleanup-checker-tests.sh +0 -0
- package/deps/librdkafka/tests/cluster_testing.py +0 -0
- package/deps/librdkafka/tests/delete-test-topics.sh +0 -0
- package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +42 -101
- package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.key +41 -29
- package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +112 -37
- package/deps/librdkafka/tests/gen-ssl-certs.sh +0 -0
- package/deps/librdkafka/tests/interactive_broker_version.py +0 -0
- package/deps/librdkafka/tests/java/Makefile +2 -1
- package/deps/librdkafka/tests/java/run-class.sh +0 -0
- package/deps/librdkafka/tests/lz4_manual_test.sh +0 -0
- package/deps/librdkafka/tests/multi-broker-version-test.sh +0 -0
- package/deps/librdkafka/tests/parse-refcnt.sh +0 -0
- package/deps/librdkafka/tests/performance_plot.py +0 -0
- package/deps/librdkafka/tests/requirements.txt +1 -1
- package/deps/librdkafka/tests/run-all-tests.sh +79 -0
- package/deps/librdkafka/tests/run-consumer-tests.sh +0 -0
- package/deps/librdkafka/tests/run-producer-tests.sh +0 -0
- package/deps/librdkafka/tests/run-test-batches.py +157 -0
- package/deps/librdkafka/tests/run-test.sh +0 -0
- package/deps/librdkafka/tests/sasl_test.py +0 -0
- package/deps/librdkafka/tests/test.c +478 -18
- package/deps/librdkafka/tests/test.h +62 -13
- package/deps/librdkafka/tests/testcpp.cpp +6 -1
- package/deps/librdkafka/tests/testcpp.h +30 -2
- package/deps/librdkafka/tests/testshared.h +16 -2
- package/deps/librdkafka/tests/tools/stats/graph.py +0 -0
- package/deps/librdkafka/tests/tools/stats/to_csv.py +1 -1
- package/deps/librdkafka/tests/trivup/trivup-0.14.0.tar.gz +0 -0
- package/deps/librdkafka/tests/until-fail.sh +0 -0
- package/deps/librdkafka/tests/xxxx-metadata.cpp +1 -1
- package/deps/librdkafka/vcpkg.json +1 -1
- package/deps/librdkafka/win32/setup-msys2.ps1 +24 -8
- package/deps/librdkafka/win32/setup-vcpkg.ps1 +28 -6
- package/deps/librdkafka/win32/tests/tests.vcxproj +6 -0
- package/deps/librdkafka/win32/wingetopt.h +5 -4
- package/errors.d.ts +27 -1
- package/lib/error.js +29 -3
- package/make_docs.sh +0 -0
- package/package.json +11 -11
- package/run_docker.sh +0 -0
- package/src/callbacks.cc +6 -9
- package/src/callbacks.h +1 -5
- package/test/kafka-consumer-worker.js +10 -7
- package/test/kafka-consumer.spec.js +32 -21
- package/ci/update-version.js +0 -123
- package/deps/librdkafka/.semaphore/project.yml +0 -43
- package/deps/librdkafka/.semaphore/project_public.yml +0 -20
- package/deps/librdkafka/win32/install-openssl.ps1 +0 -33
|
@@ -192,14 +192,14 @@ static void do_test_permanent_error_retried(rd_kafka_resp_err_t err) {
|
|
|
192
192
|
rktpar = rd_kafka_topic_partition_list_add(rktpars, topic, 0);
|
|
193
193
|
rktpar->offset = 0;
|
|
194
194
|
|
|
195
|
-
/* Will validate the offset
|
|
195
|
+
/* Will validate the offset and start fetching again
|
|
196
196
|
* from offset 0. */
|
|
197
197
|
rd_kafka_topic_partition_set_leader_epoch(rktpar, 0);
|
|
198
198
|
rd_kafka_seek_partitions(c1, rktpars, -1);
|
|
199
199
|
rd_kafka_topic_partition_list_destroy(rktpars);
|
|
200
200
|
|
|
201
201
|
/* Read all messages after seek to zero.
|
|
202
|
-
* In case of permanent error instead it
|
|
202
|
+
* In case of permanent error, instead, it resets to latest and
|
|
203
203
|
* gets an EOF. */
|
|
204
204
|
test_consumer_poll("MSG_ALL", c1, testid, 0, 0, 5, NULL);
|
|
205
205
|
|
|
@@ -424,6 +424,505 @@ static void do_test_store_offset_without_leader_epoch(void) {
|
|
|
424
424
|
SUB_TEST_PASS();
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
+
static rd_bool_t is_broker_fetch_request(rd_kafka_mock_request_t *request,
|
|
428
|
+
void *opaque) {
|
|
429
|
+
return rd_kafka_mock_request_id(request) == *(int *)(opaque) &&
|
|
430
|
+
rd_kafka_mock_request_api_key(request) == RD_KAFKAP_Fetch;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
static rd_bool_t
|
|
434
|
+
is_offset_for_leader_epoch_request(rd_kafka_mock_request_t *request,
|
|
435
|
+
void *opaque) {
|
|
436
|
+
return rd_kafka_mock_request_id(request) == *(int *)(opaque) &&
|
|
437
|
+
rd_kafka_mock_request_api_key(request) ==
|
|
438
|
+
RD_KAFKAP_OffsetForLeaderEpoch;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
static rd_bool_t is_metadata_request(rd_kafka_mock_request_t *request,
|
|
442
|
+
void *opaque) {
|
|
443
|
+
return rd_kafka_mock_request_api_key(request) == RD_KAFKAP_Metadata;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* @brief A second leader change is triggered after first one switches
|
|
448
|
+
* to a leader supporting KIP-320, the second leader either:
|
|
449
|
+
*
|
|
450
|
+
* - variation 0: doesn't support KIP-320 (leader epoch -1).
|
|
451
|
+
* This can happed during a cluster roll for upgrading the cluster.
|
|
452
|
+
* See #4796.
|
|
453
|
+
* - variation 1: the leader epoch is the same as previous leader.
|
|
454
|
+
* This can happen when the broker doesn't need that a validation
|
|
455
|
+
* should be performed after a leader change.
|
|
456
|
+
*
|
|
457
|
+
* In both cases no validation should be performed
|
|
458
|
+
* and it should continue fetching messages on the new leader.
|
|
459
|
+
*/
|
|
460
|
+
static void do_test_leader_change_no_validation(int variation) {
|
|
461
|
+
const char *topic = test_mk_topic_name(__FUNCTION__, 1);
|
|
462
|
+
const char *c1_groupid = topic;
|
|
463
|
+
rd_kafka_t *c1;
|
|
464
|
+
const char *bootstraps;
|
|
465
|
+
rd_kafka_mock_cluster_t *mcluster;
|
|
466
|
+
int msg_cnt = 5;
|
|
467
|
+
uint64_t testid = test_id_generate();
|
|
468
|
+
rd_kafka_conf_t *conf;
|
|
469
|
+
int i, leader = 1;
|
|
470
|
+
size_t matching_requests;
|
|
471
|
+
/* No KIP-320 support on second leader change */
|
|
472
|
+
int32_t leader_epoch = -1;
|
|
473
|
+
if (variation == 1) {
|
|
474
|
+
/* Same leader epoch on second leader change */
|
|
475
|
+
leader_epoch = 2;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
SUB_TEST_QUICK("variation: %d", variation);
|
|
479
|
+
|
|
480
|
+
mcluster = test_mock_cluster_new(2, &bootstraps);
|
|
481
|
+
rd_kafka_mock_topic_create(mcluster, topic, 1, 2);
|
|
482
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 1);
|
|
483
|
+
|
|
484
|
+
/* Seed the topic with messages */
|
|
485
|
+
test_produce_msgs_easy_v(topic, testid, 0, 0, msg_cnt, 10,
|
|
486
|
+
"bootstrap.servers", bootstraps,
|
|
487
|
+
"batch.num.messages", "1", NULL);
|
|
488
|
+
|
|
489
|
+
test_conf_init(&conf, NULL, 60);
|
|
490
|
+
test_conf_set(conf, "bootstrap.servers", bootstraps);
|
|
491
|
+
test_conf_set(conf, "auto.offset.reset", "earliest");
|
|
492
|
+
test_conf_set(conf, "enable.auto.commit", "false");
|
|
493
|
+
|
|
494
|
+
c1 = test_create_consumer(c1_groupid, NULL, conf, NULL);
|
|
495
|
+
test_consumer_subscribe(c1, topic);
|
|
496
|
+
|
|
497
|
+
rd_kafka_mock_start_request_tracking(mcluster);
|
|
498
|
+
TEST_SAY("Consume initial messages and join the group, etc.\n");
|
|
499
|
+
test_consumer_poll("MSG_INIT", c1, testid, 0, 0, msg_cnt, NULL);
|
|
500
|
+
|
|
501
|
+
TEST_SAY("Wait Fetch request to broker 1\n");
|
|
502
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
503
|
+
mcluster, 1, 1000, is_broker_fetch_request, &leader);
|
|
504
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
505
|
+
"Expected at least one Fetch request to broker 1");
|
|
506
|
+
|
|
507
|
+
/* No validation is performed on first fetch. */
|
|
508
|
+
TEST_SAY("Wait no OffsetForLeaderEpoch request to broker 1\n");
|
|
509
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
510
|
+
mcluster, 0, 1000, is_offset_for_leader_epoch_request, &leader);
|
|
511
|
+
TEST_ASSERT_LATER(matching_requests == 0,
|
|
512
|
+
"Expected no OffsetForLeaderEpoch request"
|
|
513
|
+
" to broker 1, got %" PRIusz,
|
|
514
|
+
matching_requests);
|
|
515
|
+
rd_kafka_mock_stop_request_tracking(mcluster);
|
|
516
|
+
|
|
517
|
+
/* The leader will change from 1->2, and the OffsetForLeaderEpoch will
|
|
518
|
+
* be sent to broker 2. Leader epoch becomes 1. */
|
|
519
|
+
rd_kafka_mock_start_request_tracking(mcluster);
|
|
520
|
+
TEST_SAY("Changing leader to broker 2\n");
|
|
521
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 2);
|
|
522
|
+
leader = 2;
|
|
523
|
+
rd_kafka_poll(c1, 1000);
|
|
524
|
+
|
|
525
|
+
TEST_SAY("Wait Fetch request to broker 2\n");
|
|
526
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
527
|
+
mcluster, 1, 1000, is_broker_fetch_request, &leader);
|
|
528
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
529
|
+
"Expected at least one fetch request to broker 2");
|
|
530
|
+
|
|
531
|
+
TEST_SAY("Wait OffsetForLeaderEpoch request to broker 2\n");
|
|
532
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
533
|
+
mcluster, 1, 1000, is_offset_for_leader_epoch_request, &leader);
|
|
534
|
+
TEST_ASSERT_LATER(matching_requests == 1,
|
|
535
|
+
"Expected one OffsetForLeaderEpoch request"
|
|
536
|
+
" to broker 2, got %" PRIusz,
|
|
537
|
+
matching_requests);
|
|
538
|
+
rd_kafka_mock_stop_request_tracking(mcluster);
|
|
539
|
+
|
|
540
|
+
/* Reset leader, set leader epoch to `leader_epoch`
|
|
541
|
+
* to trigger this special case. */
|
|
542
|
+
TEST_SAY("Changing leader to broker 1\n");
|
|
543
|
+
for (i = 0; i < 5; i++) {
|
|
544
|
+
rd_kafka_mock_partition_push_leader_response(mcluster, topic, 0,
|
|
545
|
+
1, leader_epoch);
|
|
546
|
+
}
|
|
547
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 1);
|
|
548
|
+
leader = 1;
|
|
549
|
+
rd_kafka_mock_start_request_tracking(mcluster);
|
|
550
|
+
rd_kafka_poll(c1, 1000);
|
|
551
|
+
|
|
552
|
+
TEST_SAY("Wait Fetch request to broker 1\n");
|
|
553
|
+
/* 0 is correct here as second parameter as we don't wait to receive
|
|
554
|
+
* at least one Fetch request, given in the failure case it'll take more
|
|
555
|
+
* than 1s and it's possible a OffsetForLeaderEpoch is received after
|
|
556
|
+
* that, because we ran out of overridden leader responses. */
|
|
557
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
558
|
+
mcluster, 0, 1000, is_broker_fetch_request, &leader);
|
|
559
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
560
|
+
"Expected at least one fetch request to broker 1");
|
|
561
|
+
|
|
562
|
+
/* Given same leader epoch, or -1, is returned,
|
|
563
|
+
* no validation is performed */
|
|
564
|
+
TEST_SAY("Wait no OffsetForLeaderEpoch request to broker 1\n");
|
|
565
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
566
|
+
mcluster, 0, 1000, is_offset_for_leader_epoch_request, &leader);
|
|
567
|
+
TEST_ASSERT_LATER(matching_requests == 0,
|
|
568
|
+
"Expected no OffsetForLeaderEpoch request"
|
|
569
|
+
" to broker 1, got %" PRIusz,
|
|
570
|
+
matching_requests);
|
|
571
|
+
rd_kafka_mock_stop_request_tracking(mcluster);
|
|
572
|
+
|
|
573
|
+
rd_kafka_destroy(c1);
|
|
574
|
+
test_mock_cluster_destroy(mcluster);
|
|
575
|
+
|
|
576
|
+
TEST_LATER_CHECK();
|
|
577
|
+
SUB_TEST_PASS();
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
static int
|
|
581
|
+
is_fatal_cb(rd_kafka_t *rk, rd_kafka_resp_err_t err, const char *reason) {
|
|
582
|
+
/* Ignore UNKNOWN_TOPIC_OR_PART errors. */
|
|
583
|
+
TEST_SAY("is_fatal?: %s: %s\n", rd_kafka_err2str(err), reason);
|
|
584
|
+
if (err == RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION ||
|
|
585
|
+
err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART)
|
|
586
|
+
return 0;
|
|
587
|
+
return 1;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* @brief Test partition validation when it's temporarily delegated to
|
|
592
|
+
* the internal broker. There are two variations:
|
|
593
|
+
*
|
|
594
|
+
* variation 1: leader epoch bump is simultaneous to the partition
|
|
595
|
+
* delegation returning from the internal broker to the
|
|
596
|
+
* new leader.
|
|
597
|
+
* variation 2: leader epoch bump is triggered immediately by KIP-951
|
|
598
|
+
* and validation fails, later metadata request fails
|
|
599
|
+
* and partition is delegated to the internal broker.
|
|
600
|
+
* When partition is delegated back to the leader,
|
|
601
|
+
* it finds the same leader epoch but validation must
|
|
602
|
+
* be completed as state is still VALIDATE_EPOCH_WAIT.
|
|
603
|
+
*
|
|
604
|
+
* In both cases, fetch must continue with the new leader and
|
|
605
|
+
* after the validation is completed.
|
|
606
|
+
*
|
|
607
|
+
* See #4804.
|
|
608
|
+
*/
|
|
609
|
+
static void do_test_leader_change_from_internal_broker(int variation) {
|
|
610
|
+
const char *topic = test_mk_topic_name(__FUNCTION__, 1);
|
|
611
|
+
const char *c1_groupid = topic;
|
|
612
|
+
rd_kafka_t *c1;
|
|
613
|
+
const char *bootstraps;
|
|
614
|
+
rd_kafka_mock_cluster_t *mcluster;
|
|
615
|
+
int msg_cnt = 5;
|
|
616
|
+
uint64_t testid = test_id_generate();
|
|
617
|
+
rd_kafka_conf_t *conf;
|
|
618
|
+
int leader = 1;
|
|
619
|
+
size_t matching_requests, expected_offset_for_leader_epoch_requests = 1;
|
|
620
|
+
|
|
621
|
+
SUB_TEST_QUICK("variation: %d", variation);
|
|
622
|
+
|
|
623
|
+
mcluster = test_mock_cluster_new(2, &bootstraps);
|
|
624
|
+
rd_kafka_mock_topic_create(mcluster, topic, 1, 2);
|
|
625
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 1);
|
|
626
|
+
|
|
627
|
+
/* Seed the topic with messages */
|
|
628
|
+
test_produce_msgs_easy_v(topic, testid, 0, 0, msg_cnt, 10,
|
|
629
|
+
"bootstrap.servers", bootstraps,
|
|
630
|
+
"batch.num.messages", "1", NULL);
|
|
631
|
+
|
|
632
|
+
test_conf_init(&conf, NULL, 60);
|
|
633
|
+
test_conf_set(conf, "bootstrap.servers", bootstraps);
|
|
634
|
+
test_conf_set(conf, "auto.offset.reset", "earliest");
|
|
635
|
+
test_conf_set(conf, "enable.auto.commit", "false");
|
|
636
|
+
|
|
637
|
+
c1 = test_create_consumer(c1_groupid, NULL, conf, NULL);
|
|
638
|
+
test_consumer_subscribe(c1, topic);
|
|
639
|
+
test_curr->is_fatal_cb = is_fatal_cb;
|
|
640
|
+
|
|
641
|
+
rd_kafka_mock_start_request_tracking(mcluster);
|
|
642
|
+
TEST_SAY("Consume initial messages and join the group, etc.\n");
|
|
643
|
+
test_consumer_poll("MSG_INIT", c1, testid, 0, 0, msg_cnt, NULL);
|
|
644
|
+
|
|
645
|
+
TEST_SAY("Wait Fetch request to broker 1\n");
|
|
646
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
647
|
+
mcluster, 1, 1000, is_broker_fetch_request, &leader);
|
|
648
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
649
|
+
"Expected at least one Fetch request to broker 1");
|
|
650
|
+
|
|
651
|
+
/* No validation is performed on first fetch. */
|
|
652
|
+
TEST_SAY("Wait no OffsetForLeaderEpoch request to broker 1\n");
|
|
653
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
654
|
+
mcluster, 0, 1000, is_offset_for_leader_epoch_request, &leader);
|
|
655
|
+
TEST_ASSERT_LATER(matching_requests == 0,
|
|
656
|
+
"Expected no OffsetForLeaderEpoch request"
|
|
657
|
+
" to broker 1, got %" PRIusz,
|
|
658
|
+
matching_requests);
|
|
659
|
+
rd_kafka_mock_stop_request_tracking(mcluster);
|
|
660
|
+
|
|
661
|
+
/* The leader will change from 1->2, and the OffsetForLeaderEpoch will
|
|
662
|
+
* be sent to broker 2. Leader epoch becomes 1. */
|
|
663
|
+
rd_kafka_mock_start_request_tracking(mcluster);
|
|
664
|
+
TEST_SAY("Changing leader to broker 2\n");
|
|
665
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 2);
|
|
666
|
+
leader = 2;
|
|
667
|
+
rd_kafka_poll(c1, 1000);
|
|
668
|
+
|
|
669
|
+
TEST_SAY("Wait Fetch request to broker 2\n");
|
|
670
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
671
|
+
mcluster, 1, 1000, is_broker_fetch_request, &leader);
|
|
672
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
673
|
+
"Expected at least one fetch request to broker 2");
|
|
674
|
+
|
|
675
|
+
TEST_SAY("Wait OffsetForLeaderEpoch request to broker 2\n");
|
|
676
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
677
|
+
mcluster, 1, 1000, is_offset_for_leader_epoch_request, &leader);
|
|
678
|
+
TEST_ASSERT_LATER(matching_requests == 1,
|
|
679
|
+
"Expected one OffsetForLeaderEpoch request"
|
|
680
|
+
" to broker 2, got %" PRIusz,
|
|
681
|
+
matching_requests);
|
|
682
|
+
rd_kafka_mock_stop_request_tracking(mcluster);
|
|
683
|
+
|
|
684
|
+
/* Reset leader, Metadata request fails in between and delegates
|
|
685
|
+
* the partition to the internal broker. */
|
|
686
|
+
TEST_SAY("Changing leader to broker 1\n");
|
|
687
|
+
if (variation == 0) {
|
|
688
|
+
/* Fail Fetch request too, otherwise KIP-951 mechanism is faster
|
|
689
|
+
* than the Metadata request. */
|
|
690
|
+
rd_kafka_mock_push_request_errors(
|
|
691
|
+
mcluster, RD_KAFKAP_Fetch, 1,
|
|
692
|
+
RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART);
|
|
693
|
+
} else if (variation == 1) {
|
|
694
|
+
/* First OffsetForLeaderEpoch is triggered by KIP-951,
|
|
695
|
+
* it updates leader epoch, then it fails, triggers metadata
|
|
696
|
+
* refresh,
|
|
697
|
+
* Metadata fails too and partition is delegated to the internal
|
|
698
|
+
* broker.
|
|
699
|
+
* Validation is retried three times during this period
|
|
700
|
+
* and it should fail because we want to see what happens
|
|
701
|
+
* next when partition isn't delegated to the internal
|
|
702
|
+
* broker anymore. */
|
|
703
|
+
rd_kafka_mock_push_request_errors(
|
|
704
|
+
mcluster, RD_KAFKAP_OffsetForLeaderEpoch, 3,
|
|
705
|
+
RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART,
|
|
706
|
+
RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART,
|
|
707
|
+
RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/* This causes a Metadata request error. */
|
|
711
|
+
rd_kafka_mock_topic_set_error(mcluster, topic,
|
|
712
|
+
RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART);
|
|
713
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 1);
|
|
714
|
+
leader = 1;
|
|
715
|
+
rd_kafka_mock_start_request_tracking(mcluster);
|
|
716
|
+
rd_kafka_poll(c1, 1000);
|
|
717
|
+
|
|
718
|
+
TEST_SAY(
|
|
719
|
+
"Wait a Metadata request that fails and delegates partition to"
|
|
720
|
+
" the internal broker.\n");
|
|
721
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
722
|
+
mcluster, 1, 1000, is_metadata_request, NULL);
|
|
723
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
724
|
+
"Expected at least one Metadata request");
|
|
725
|
+
TEST_SAY(
|
|
726
|
+
"Reset partition error status."
|
|
727
|
+
" Partition is delegated to broker 1.\n");
|
|
728
|
+
rd_kafka_mock_topic_set_error(mcluster, topic,
|
|
729
|
+
RD_KAFKA_RESP_ERR_NO_ERROR);
|
|
730
|
+
|
|
731
|
+
TEST_SAY("Wait Fetch request to broker 1\n");
|
|
732
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
733
|
+
mcluster, 1, 2000, is_broker_fetch_request, &leader);
|
|
734
|
+
TEST_ASSERT_LATER(matching_requests > 0,
|
|
735
|
+
"Expected at least one fetch request to broker 1");
|
|
736
|
+
|
|
737
|
+
TEST_SAY("Wait OffsetForLeaderEpoch request to broker 1\n");
|
|
738
|
+
if (variation == 1) {
|
|
739
|
+
/* There's three OffsetForLeaderEpoch requests more in
|
|
740
|
+
* variation 1. See previous comment. */
|
|
741
|
+
expected_offset_for_leader_epoch_requests += 3;
|
|
742
|
+
}
|
|
743
|
+
matching_requests = test_mock_wait_matching_requests(
|
|
744
|
+
mcluster, 1, 1000, is_offset_for_leader_epoch_request, &leader);
|
|
745
|
+
TEST_ASSERT_LATER(
|
|
746
|
+
matching_requests == expected_offset_for_leader_epoch_requests,
|
|
747
|
+
"Expected %" PRIusz
|
|
748
|
+
" OffsetForLeaderEpoch request"
|
|
749
|
+
" to broker 1, got %" PRIusz,
|
|
750
|
+
expected_offset_for_leader_epoch_requests, matching_requests);
|
|
751
|
+
rd_kafka_mock_stop_request_tracking(mcluster);
|
|
752
|
+
|
|
753
|
+
rd_kafka_destroy(c1);
|
|
754
|
+
test_mock_cluster_destroy(mcluster);
|
|
755
|
+
|
|
756
|
+
TEST_LATER_CHECK();
|
|
757
|
+
SUB_TEST_PASS();
|
|
758
|
+
test_curr->is_fatal_cb = NULL;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* @brief Opaque for do_test_list_offsets_leader_change.
|
|
763
|
+
*/
|
|
764
|
+
typedef struct do_test_list_offsets_leader_change_s {
|
|
765
|
+
rd_kafka_mock_cluster_t *mcluster;
|
|
766
|
+
const char *topic;
|
|
767
|
+
int msg_cnt;
|
|
768
|
+
int variation;
|
|
769
|
+
} do_test_list_offsets_leader_change_t;
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* @brief Rebalance callback for do_test_list_offsets_leader_change.
|
|
773
|
+
*/
|
|
774
|
+
static void do_test_list_offsets_leader_change_rebalance_cb(
|
|
775
|
+
rd_kafka_t *rk,
|
|
776
|
+
rd_kafka_resp_err_t err,
|
|
777
|
+
rd_kafka_topic_partition_list_t *partitions,
|
|
778
|
+
void *opaque) {
|
|
779
|
+
TEST_SAY("Rebalance callback: %s with %d partition(s)\n",
|
|
780
|
+
rd_kafka_err2str(err), partitions->cnt);
|
|
781
|
+
do_test_list_offsets_leader_change_t *test = opaque;
|
|
782
|
+
switch (err) {
|
|
783
|
+
case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS: {
|
|
784
|
+
int retries = 0;
|
|
785
|
+
int64_t low, high;
|
|
786
|
+
rd_kafka_resp_err_t list_offsets_err =
|
|
787
|
+
RD_KAFKA_RESP_ERR_NO_ERROR;
|
|
788
|
+
|
|
789
|
+
TEST_ASSERT(partitions->cnt == 1,
|
|
790
|
+
"Expected 1 assigned partition, got %d",
|
|
791
|
+
partitions->cnt);
|
|
792
|
+
|
|
793
|
+
/* Change leader to 2 */
|
|
794
|
+
rd_kafka_mock_partition_set_leader(test->mcluster, test->topic,
|
|
795
|
+
0, 2);
|
|
796
|
+
|
|
797
|
+
do {
|
|
798
|
+
/* Set a wrong leader epoch that should not be used
|
|
799
|
+
* for listing offsets. */
|
|
800
|
+
rd_kafka_topic_partition_set_leader_epoch(
|
|
801
|
+
&partitions->elems[0], 1234);
|
|
802
|
+
|
|
803
|
+
if (test->variation == 0) {
|
|
804
|
+
partitions->elems[0].offset = 1;
|
|
805
|
+
list_offsets_err = rd_kafka_offsets_for_times(
|
|
806
|
+
rk, partitions, 1000);
|
|
807
|
+
} else {
|
|
808
|
+
list_offsets_err =
|
|
809
|
+
rd_kafka_query_watermark_offsets(
|
|
810
|
+
rk, partitions->elems[0].topic,
|
|
811
|
+
partitions->elems[0].partition, &low,
|
|
812
|
+
&high, 1000);
|
|
813
|
+
}
|
|
814
|
+
retries++;
|
|
815
|
+
if (retries == 1) {
|
|
816
|
+
TEST_ASSERT(
|
|
817
|
+
list_offsets_err ==
|
|
818
|
+
RD_KAFKA_RESP_ERR_NOT_LEADER_FOR_PARTITION,
|
|
819
|
+
"Expected NOT_LEADER_FOR_PARTITION, got %s",
|
|
820
|
+
rd_kafka_err2str(list_offsets_err));
|
|
821
|
+
}
|
|
822
|
+
if (retries > 2)
|
|
823
|
+
TEST_FAIL(
|
|
824
|
+
"Offsets for times failed %d times "
|
|
825
|
+
" during the rebalance callback",
|
|
826
|
+
retries);
|
|
827
|
+
} while (list_offsets_err != RD_KAFKA_RESP_ERR_NO_ERROR);
|
|
828
|
+
|
|
829
|
+
TEST_ASSERT(retries == 2,
|
|
830
|
+
"There must be exactly 2 retries, "
|
|
831
|
+
"got %d",
|
|
832
|
+
retries);
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
if (test->variation == 0) {
|
|
836
|
+
/* Mock handler currently returns
|
|
837
|
+
* RD_KAFKA_OFFSET_SPEC_LATEST
|
|
838
|
+
* in the offsets for times case */
|
|
839
|
+
TEST_ASSERT(partitions->elems[0].offset ==
|
|
840
|
+
RD_KAFKA_OFFSET_SPEC_LATEST,
|
|
841
|
+
"Expected offset for times LATEST,"
|
|
842
|
+
" got %" PRId64,
|
|
843
|
+
partitions->elems[0].offset);
|
|
844
|
+
} else {
|
|
845
|
+
TEST_ASSERT(0 == low,
|
|
846
|
+
"Expected low offset 0"
|
|
847
|
+
", got %" PRId64,
|
|
848
|
+
low);
|
|
849
|
+
TEST_ASSERT(10 == high,
|
|
850
|
+
"Expected high offset 10"
|
|
851
|
+
", got %" PRId64,
|
|
852
|
+
high);
|
|
853
|
+
partitions->elems[0].offset = high;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
test_consumer_assign_by_rebalance_protocol("rebalance", rk,
|
|
857
|
+
partitions);
|
|
858
|
+
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS:
|
|
862
|
+
test_consumer_unassign_by_rebalance_protocol("rebalance", rk,
|
|
863
|
+
partitions);
|
|
864
|
+
break;
|
|
865
|
+
default:
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* @brief Test that listing offsets during a leader change works as expected.
|
|
872
|
+
* by returning a NOT_LEADER_FOR_PARTITION error and clearing the cache.
|
|
873
|
+
*
|
|
874
|
+
* There are two variations:
|
|
875
|
+
* - variation 0: uses rd_kafka_offsets_for_times
|
|
876
|
+
* - variation 1: uses rd_kafka_query_watermark_offsets
|
|
877
|
+
*/
|
|
878
|
+
static void do_test_list_offsets_leader_change(int variation) {
|
|
879
|
+
const char *topic = test_mk_topic_name(__FUNCTION__, 1);
|
|
880
|
+
const char *c1_groupid = topic;
|
|
881
|
+
rd_kafka_t *c1;
|
|
882
|
+
const char *bootstraps;
|
|
883
|
+
rd_kafka_mock_cluster_t *mcluster;
|
|
884
|
+
int msg_cnt = 10;
|
|
885
|
+
uint64_t testid = test_id_generate();
|
|
886
|
+
rd_kafka_conf_t *conf;
|
|
887
|
+
do_test_list_offsets_leader_change_t opaque;
|
|
888
|
+
|
|
889
|
+
SUB_TEST_QUICK("%s", variation == 0 ? "offsets_for_times"
|
|
890
|
+
: "query_watermark_offsets");
|
|
891
|
+
|
|
892
|
+
mcluster = test_mock_cluster_new(2, &bootstraps);
|
|
893
|
+
rd_kafka_mock_topic_create(mcluster, topic, 1, 2);
|
|
894
|
+
rd_kafka_mock_partition_set_leader(mcluster, topic, 0, 1);
|
|
895
|
+
|
|
896
|
+
/* Seed the topic with messages */
|
|
897
|
+
test_produce_msgs_easy_v(topic, testid, 0, 0, msg_cnt, 10,
|
|
898
|
+
"bootstrap.servers", bootstraps, NULL);
|
|
899
|
+
|
|
900
|
+
test_conf_init(&conf, NULL, 60);
|
|
901
|
+
test_conf_set(conf, "bootstrap.servers", bootstraps);
|
|
902
|
+
test_conf_set(conf, "auto.offset.reset", "earliest");
|
|
903
|
+
rd_kafka_conf_set_rebalance_cb(
|
|
904
|
+
conf, do_test_list_offsets_leader_change_rebalance_cb);
|
|
905
|
+
opaque.mcluster = mcluster;
|
|
906
|
+
opaque.topic = topic;
|
|
907
|
+
opaque.msg_cnt = msg_cnt;
|
|
908
|
+
opaque.variation = variation;
|
|
909
|
+
rd_kafka_conf_set_opaque(conf, &opaque);
|
|
910
|
+
|
|
911
|
+
c1 = test_create_consumer(c1_groupid, NULL, conf, NULL);
|
|
912
|
+
test_consumer_subscribe(c1, topic);
|
|
913
|
+
|
|
914
|
+
/* Consumes no messages if assignment starts from
|
|
915
|
+
* latest as set in the rebalance callback,
|
|
916
|
+
* otherwise it's configured as earliest. */
|
|
917
|
+
test_consumer_poll_no_msgs("MSG_INIT", c1, testid, 5000);
|
|
918
|
+
|
|
919
|
+
rd_kafka_destroy(c1);
|
|
920
|
+
|
|
921
|
+
test_mock_cluster_destroy(mcluster);
|
|
922
|
+
|
|
923
|
+
TEST_LATER_CHECK();
|
|
924
|
+
SUB_TEST_PASS();
|
|
925
|
+
}
|
|
427
926
|
|
|
428
927
|
int main_0139_offset_validation_mock(int argc, char **argv) {
|
|
429
928
|
|
|
@@ -438,5 +937,14 @@ int main_0139_offset_validation_mock(int argc, char **argv) {
|
|
|
438
937
|
|
|
439
938
|
do_test_store_offset_without_leader_epoch();
|
|
440
939
|
|
|
940
|
+
do_test_leader_change_no_validation(0);
|
|
941
|
+
do_test_leader_change_no_validation(1);
|
|
942
|
+
|
|
943
|
+
do_test_leader_change_from_internal_broker(0);
|
|
944
|
+
do_test_leader_change_from_internal_broker(1);
|
|
945
|
+
|
|
946
|
+
do_test_list_offsets_leader_change(0);
|
|
947
|
+
do_test_list_offsets_leader_change(1);
|
|
948
|
+
|
|
441
949
|
return 0;
|
|
442
950
|
}
|
|
@@ -54,7 +54,7 @@ static void test_commit_metadata() {
|
|
|
54
54
|
delete conf;
|
|
55
55
|
|
|
56
56
|
Test::Say("Create topic.\n");
|
|
57
|
-
Test::
|
|
57
|
+
Test::create_topic_wait_exists(consumer, topic.c_str(), 1, 1, 5000);
|
|
58
58
|
|
|
59
59
|
Test::Say("Commit offsets.\n");
|
|
60
60
|
std::vector<RdKafka::TopicPartition *> offsets;
|
|
@@ -83,6 +83,7 @@ void do_test_producer(int64_t reauth_time, const char *topic) {
|
|
|
83
83
|
|
|
84
84
|
rk = test_create_handle(RD_KAFKA_PRODUCER, conf);
|
|
85
85
|
rkt = test_create_producer_topic(rk, topic, NULL);
|
|
86
|
+
test_wait_topic_exists(rk, topic, 5000);
|
|
86
87
|
|
|
87
88
|
/* Create the topic to make sure connections are up and ready. */
|
|
88
89
|
err = test_auto_create_topic_rkt(rk, rkt, tmout_multip(5000));
|
|
@@ -129,7 +130,7 @@ void do_test_consumer(int64_t reauth_time, const char *topic) {
|
|
|
129
130
|
|
|
130
131
|
p1 = test_create_handle(RD_KAFKA_PRODUCER, rd_kafka_conf_dup(conf));
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
test_create_topic_wait_exists(p1, topic, 1, 3, 5000);
|
|
133
134
|
TEST_SAY("Topic: %s is created\n", topic);
|
|
134
135
|
|
|
135
136
|
test_conf_set(conf, "auto.offset.reset", "earliest");
|
|
@@ -207,6 +208,7 @@ void do_test_txn_producer(int64_t reauth_time,
|
|
|
207
208
|
|
|
208
209
|
rk = test_create_handle(RD_KAFKA_PRODUCER, conf);
|
|
209
210
|
rkt = test_create_producer_topic(rk, topic, NULL);
|
|
211
|
+
test_wait_topic_exists(rk, topic, 5000);
|
|
210
212
|
|
|
211
213
|
err = test_auto_create_topic_rkt(rk, rkt, tmout_multip(5000));
|
|
212
214
|
TEST_ASSERT(!err, "topic creation failed: %s", rd_kafka_err2str(err));
|
|
@@ -268,7 +270,7 @@ void do_test_oauthbearer(int64_t reauth_time,
|
|
|
268
270
|
rd_kafka_t *rk = NULL;
|
|
269
271
|
uint64_t testid = test_id_generate();
|
|
270
272
|
rd_kafka_resp_err_t err;
|
|
271
|
-
char *mechanism;
|
|
273
|
+
char *mechanism, *oauthbearer_method;
|
|
272
274
|
int msgrate, msgcnt, sent_msg;
|
|
273
275
|
test_timing_t t_produce;
|
|
274
276
|
int token_lifetime_s = token_lifetime_ms / 1000;
|
|
@@ -290,11 +292,16 @@ void do_test_oauthbearer(int64_t reauth_time,
|
|
|
290
292
|
mechanism);
|
|
291
293
|
}
|
|
292
294
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
oauthbearer_method = test_conf_get(conf, "sasl.oauthbearer.method");
|
|
296
|
+
if (rd_strcasecmp(oauthbearer_method, "oidc")) {
|
|
297
|
+
test_conf_set(
|
|
298
|
+
conf, "sasl.oauthbearer.config",
|
|
299
|
+
tsprintf(
|
|
300
|
+
"principal=admin scope=requiredScope lifeSeconds=%d",
|
|
301
|
+
token_lifetime_s));
|
|
302
|
+
test_conf_set(conf, "enable.sasl.oauthbearer.unsecure.jwt",
|
|
303
|
+
"true");
|
|
304
|
+
}
|
|
298
305
|
rk = test_create_handle(RD_KAFKA_PRODUCER, conf);
|
|
299
306
|
|
|
300
307
|
/* Enable to background queue since we don't want to poll the SASL
|
|
@@ -303,6 +310,7 @@ void do_test_oauthbearer(int64_t reauth_time,
|
|
|
303
310
|
rd_kafka_sasl_background_callbacks_enable(rk);
|
|
304
311
|
|
|
305
312
|
rkt = test_create_producer_topic(rk, topic, NULL);
|
|
313
|
+
test_wait_topic_exists(rk, topic, 5000);
|
|
306
314
|
|
|
307
315
|
/* Create the topic to make sure connections are up and ready. */
|
|
308
316
|
err = test_auto_create_topic_rkt(rk, rkt, tmout_multip(5000));
|
|
@@ -372,6 +380,7 @@ void do_test_reauth_failure(int64_t reauth_time, const char *topic) {
|
|
|
372
380
|
|
|
373
381
|
rk = test_create_handle(RD_KAFKA_PRODUCER, conf);
|
|
374
382
|
rkt = test_create_producer_topic(rk, topic, NULL);
|
|
383
|
+
test_wait_topic_exists(rk, topic, 5000);
|
|
375
384
|
|
|
376
385
|
/* Create the topic to make sure connections are up and ready. */
|
|
377
386
|
err = test_auto_create_topic_rkt(rk, rkt, tmout_multip(5000));
|
|
@@ -403,7 +412,9 @@ int main_0142_reauthentication(int argc, char **argv) {
|
|
|
403
412
|
size_t broker_id_cnt;
|
|
404
413
|
int32_t *broker_ids = NULL;
|
|
405
414
|
rd_kafka_conf_t *conf = NULL;
|
|
406
|
-
const char *security_protocol
|
|
415
|
+
const char *security_protocol;
|
|
416
|
+
rd_bool_t sasl_mechanism_oauthbearer = rd_false;
|
|
417
|
+
rd_bool_t oauthbearer_method_default = rd_false;
|
|
407
418
|
|
|
408
419
|
size_t i;
|
|
409
420
|
int64_t reauth_time = INT64_MAX;
|
|
@@ -419,8 +430,11 @@ int main_0142_reauthentication(int argc, char **argv) {
|
|
|
419
430
|
return 0;
|
|
420
431
|
}
|
|
421
432
|
|
|
422
|
-
|
|
423
|
-
|
|
433
|
+
sasl_mechanism_oauthbearer = !rd_strcasecmp(
|
|
434
|
+
test_conf_get(NULL, "sasl.mechanism"), "oauthbearer");
|
|
435
|
+
oauthbearer_method_default = !rd_strcasecmp(
|
|
436
|
+
test_conf_get(NULL, "sasl.oauthbearer.method"), "default");
|
|
437
|
+
if (sasl_mechanism_oauthbearer && oauthbearer_method_default)
|
|
424
438
|
test_conf_set(conf, "enable.sasl.oauthbearer.unsecure.jwt",
|
|
425
439
|
"true");
|
|
426
440
|
|
|
@@ -481,13 +495,19 @@ int main_0142_reauthentication(int argc, char **argv) {
|
|
|
481
495
|
* reauth time. */
|
|
482
496
|
do_test_oauthbearer(reauth_time, topic, reauth_time / 2, rd_true);
|
|
483
497
|
do_test_oauthbearer(reauth_time, topic, reauth_time / 2, rd_false);
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
*
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
498
|
+
|
|
499
|
+
/* With OIDC the expiration time is fixed so do the testing only
|
|
500
|
+
* once. */
|
|
501
|
+
if (oauthbearer_method_default) {
|
|
502
|
+
/* Case when the token_lifetime is greater than the maximum
|
|
503
|
+
* reauth time configured. In this case, the broker returns the
|
|
504
|
+
* maximum reauth time configured. We don't need to recreate the
|
|
505
|
+
* token, but we need to reauthenticate using the same token. */
|
|
506
|
+
do_test_oauthbearer(reauth_time, topic, reauth_time * 2,
|
|
507
|
+
rd_true);
|
|
508
|
+
do_test_oauthbearer(reauth_time, topic, reauth_time * 2,
|
|
509
|
+
rd_false);
|
|
510
|
+
}
|
|
491
511
|
|
|
492
512
|
do_test_reauth_failure(reauth_time, topic);
|
|
493
513
|
|