@ohos-ports/confluentinc-kafka-javascript 1.10.0-beta.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.
- package/CHANGELOG.md +457 -0
- package/LICENSE.kafkajs +31 -0
- package/LICENSE.node-rdkafka +25 -0
- package/LICENSE.txt +20 -0
- package/README.md +133 -0
- package/binding.gyp +184 -0
- package/build/Release/confluent-kafka-javascript.node +0 -0
- package/build/deps/librdkafka++.so.1 +0 -0
- package/build/deps/librdkafka.Makefile +6 -0
- package/build/deps/librdkafka.so.1 +0 -0
- package/build/deps/librdkafka.target.mk +55 -0
- package/deps/librdkafka/.clang-format +136 -0
- package/deps/librdkafka/.clang-format-cpp +103 -0
- package/deps/librdkafka/.dir-locals.el +10 -0
- package/deps/librdkafka/.formatignore +35 -0
- package/deps/librdkafka/.gdbmacros +19 -0
- package/deps/librdkafka/CHANGELOG.md +2477 -0
- package/deps/librdkafka/CMakeLists.txt +291 -0
- package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
- package/deps/librdkafka/CONFIGURATION.md +212 -0
- package/deps/librdkafka/CONTRIBUTING.md +431 -0
- package/deps/librdkafka/Doxyfile +2375 -0
- package/deps/librdkafka/INTRODUCTION.md +2752 -0
- package/deps/librdkafka/LICENSE +26 -0
- package/deps/librdkafka/LICENSE.cjson +22 -0
- package/deps/librdkafka/LICENSE.crc32c +28 -0
- package/deps/librdkafka/LICENSE.fnv1a +18 -0
- package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
- package/deps/librdkafka/LICENSE.lz4 +26 -0
- package/deps/librdkafka/LICENSE.murmur2 +25 -0
- package/deps/librdkafka/LICENSE.nanopb +22 -0
- package/deps/librdkafka/LICENSE.opentelemetry +203 -0
- package/deps/librdkafka/LICENSE.pycrc +23 -0
- package/deps/librdkafka/LICENSE.queue +31 -0
- package/deps/librdkafka/LICENSE.regexp +5 -0
- package/deps/librdkafka/LICENSE.snappy +36 -0
- package/deps/librdkafka/LICENSE.tinycthread +26 -0
- package/deps/librdkafka/LICENSE.wingetopt +49 -0
- package/deps/librdkafka/LICENSES.txt +625 -0
- package/deps/librdkafka/Makefile +125 -0
- package/deps/librdkafka/README.md +201 -0
- package/deps/librdkafka/README.win32 +26 -0
- package/deps/librdkafka/STATISTICS.md +624 -0
- package/deps/librdkafka/configure +214 -0
- package/deps/librdkafka/configure.self +341 -0
- package/deps/librdkafka/dev-conf.sh +123 -0
- package/deps/librdkafka/lds-gen.py +73 -0
- package/deps/librdkafka/mainpage.doxy +40 -0
- package/deps/librdkafka/mklove/Makefile.base +329 -0
- package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
- package/deps/librdkafka/mklove/modules/configure.base +2484 -0
- package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
- package/deps/librdkafka/mklove/modules/configure.cc +186 -0
- package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
- package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
- package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
- package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
- package/deps/librdkafka/mklove/modules/configure.host +132 -0
- package/deps/librdkafka/mklove/modules/configure.lib +49 -0
- package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
- package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
- package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
- package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
- package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
- package/deps/librdkafka/mklove/modules/configure.pic +16 -0
- package/deps/librdkafka/mklove/modules/configure.socket +20 -0
- package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
- package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
- package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
- package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
- package/deps/librdkafka/service.yml +182 -0
- package/deps/librdkafka/src/CMakeLists.txt +379 -0
- package/deps/librdkafka/src/Makefile +105 -0
- package/deps/librdkafka/src/README.lz4.md +30 -0
- package/deps/librdkafka/src/cJSON.c +3191 -0
- package/deps/librdkafka/src/cJSON.h +306 -0
- package/deps/librdkafka/src/crc32c.c +430 -0
- package/deps/librdkafka/src/crc32c.h +38 -0
- package/deps/librdkafka/src/generate_proto.sh +66 -0
- package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
- package/deps/librdkafka/src/lz4.c +2727 -0
- package/deps/librdkafka/src/lz4.h +842 -0
- package/deps/librdkafka/src/lz4frame.c +2078 -0
- package/deps/librdkafka/src/lz4frame.h +692 -0
- package/deps/librdkafka/src/lz4frame_static.h +47 -0
- package/deps/librdkafka/src/lz4hc.c +1631 -0
- package/deps/librdkafka/src/lz4hc.h +413 -0
- package/deps/librdkafka/src/nanopb/pb.h +917 -0
- package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
- package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
- package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
- package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
- package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
- package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
- package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
- package/deps/librdkafka/src/queue.h +850 -0
- package/deps/librdkafka/src/rd.h +592 -0
- package/deps/librdkafka/src/rdaddr.c +255 -0
- package/deps/librdkafka/src/rdaddr.h +202 -0
- package/deps/librdkafka/src/rdatomic.h +262 -0
- package/deps/librdkafka/src/rdavg.h +260 -0
- package/deps/librdkafka/src/rdavl.c +210 -0
- package/deps/librdkafka/src/rdavl.h +250 -0
- package/deps/librdkafka/src/rdbase64.c +200 -0
- package/deps/librdkafka/src/rdbase64.h +43 -0
- package/deps/librdkafka/src/rdbuf.c +1884 -0
- package/deps/librdkafka/src/rdbuf.h +375 -0
- package/deps/librdkafka/src/rdcrc32.c +114 -0
- package/deps/librdkafka/src/rdcrc32.h +170 -0
- package/deps/librdkafka/src/rddl.c +179 -0
- package/deps/librdkafka/src/rddl.h +43 -0
- package/deps/librdkafka/src/rdendian.h +175 -0
- package/deps/librdkafka/src/rdfloat.h +67 -0
- package/deps/librdkafka/src/rdfnv1a.c +113 -0
- package/deps/librdkafka/src/rdfnv1a.h +35 -0
- package/deps/librdkafka/src/rdgz.c +120 -0
- package/deps/librdkafka/src/rdgz.h +46 -0
- package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
- package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
- package/deps/librdkafka/src/rdhttp.c +831 -0
- package/deps/librdkafka/src/rdhttp.h +101 -0
- package/deps/librdkafka/src/rdinterval.h +177 -0
- package/deps/librdkafka/src/rdkafka.c +7287 -0
- package/deps/librdkafka/src/rdkafka.h +11795 -0
- package/deps/librdkafka/src/rdkafka_admin.c +10165 -0
- package/deps/librdkafka/src/rdkafka_admin.h +658 -0
- package/deps/librdkafka/src/rdkafka_assignment.c +1282 -0
- package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
- package/deps/librdkafka/src/rdkafka_assignor.c +1800 -0
- package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
- package/deps/librdkafka/src/rdkafka_aux.c +409 -0
- package/deps/librdkafka/src/rdkafka_aux.h +174 -0
- package/deps/librdkafka/src/rdkafka_background.c +222 -0
- package/deps/librdkafka/src/rdkafka_broker.c +6736 -0
- package/deps/librdkafka/src/rdkafka_broker.h +851 -0
- package/deps/librdkafka/src/rdkafka_buf.c +543 -0
- package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
- package/deps/librdkafka/src/rdkafka_cert.c +576 -0
- package/deps/librdkafka/src/rdkafka_cert.h +62 -0
- package/deps/librdkafka/src/rdkafka_cgrp.c +8310 -0
- package/deps/librdkafka/src/rdkafka_cgrp.h +589 -0
- package/deps/librdkafka/src/rdkafka_conf.c +5177 -0
- package/deps/librdkafka/src/rdkafka_conf.h +746 -0
- package/deps/librdkafka/src/rdkafka_confval.h +97 -0
- package/deps/librdkafka/src/rdkafka_coord.c +623 -0
- package/deps/librdkafka/src/rdkafka_coord.h +132 -0
- package/deps/librdkafka/src/rdkafka_error.c +228 -0
- package/deps/librdkafka/src/rdkafka_error.h +80 -0
- package/deps/librdkafka/src/rdkafka_event.c +502 -0
- package/deps/librdkafka/src/rdkafka_event.h +126 -0
- package/deps/librdkafka/src/rdkafka_feature.c +898 -0
- package/deps/librdkafka/src/rdkafka_feature.h +104 -0
- package/deps/librdkafka/src/rdkafka_fetcher.c +3820 -0
- package/deps/librdkafka/src/rdkafka_fetcher.h +62 -0
- package/deps/librdkafka/src/rdkafka_header.c +220 -0
- package/deps/librdkafka/src/rdkafka_header.h +76 -0
- package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
- package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
- package/deps/librdkafka/src/rdkafka_int.h +1505 -0
- package/deps/librdkafka/src/rdkafka_interceptor.c +842 -0
- package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
- package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
- package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
- package/deps/librdkafka/src/rdkafka_metadata.c +2347 -0
- package/deps/librdkafka/src/rdkafka_metadata.h +350 -0
- package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
- package/deps/librdkafka/src/rdkafka_mock.c +4514 -0
- package/deps/librdkafka/src/rdkafka_mock.h +867 -0
- package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1877 -0
- package/deps/librdkafka/src/rdkafka_mock_handlers.c +5255 -0
- package/deps/librdkafka/src/rdkafka_mock_int.h +1005 -0
- package/deps/librdkafka/src/rdkafka_mock_sharegrp.c +1207 -0
- package/deps/librdkafka/src/rdkafka_msg.c +2619 -0
- package/deps/librdkafka/src/rdkafka_msg.h +629 -0
- package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
- package/deps/librdkafka/src/rdkafka_msgset.h +105 -0
- package/deps/librdkafka/src/rdkafka_msgset_reader.c +2099 -0
- package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
- package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
- package/deps/librdkafka/src/rdkafka_offset.h +150 -0
- package/deps/librdkafka/src/rdkafka_op.c +1219 -0
- package/deps/librdkafka/src/rdkafka_op.h +1065 -0
- package/deps/librdkafka/src/rdkafka_partition.c +5109 -0
- package/deps/librdkafka/src/rdkafka_partition.h +1215 -0
- package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
- package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
- package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
- package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
- package/deps/librdkafka/src/rdkafka_proto.h +739 -0
- package/deps/librdkafka/src/rdkafka_protocol.h +131 -0
- package/deps/librdkafka/src/rdkafka_queue.c +1351 -0
- package/deps/librdkafka/src/rdkafka_queue.h +1235 -0
- package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
- package/deps/librdkafka/src/rdkafka_request.c +7298 -0
- package/deps/librdkafka/src/rdkafka_request.h +761 -0
- package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
- package/deps/librdkafka/src/rdkafka_sasl.c +589 -0
- package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
- package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
- package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1827 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
- package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
- package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
- package/deps/librdkafka/src/rdkafka_share_acknowledgement.c +1445 -0
- package/deps/librdkafka/src/rdkafka_share_acknowledgement.h +373 -0
- package/deps/librdkafka/src/rdkafka_ssl.c +2235 -0
- package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
- package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
- package/deps/librdkafka/src/rdkafka_subscription.c +411 -0
- package/deps/librdkafka/src/rdkafka_telemetry.c +761 -0
- package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1307 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.c +1309 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.h +459 -0
- package/deps/librdkafka/src/rdkafka_timer.c +407 -0
- package/deps/librdkafka/src/rdkafka_timer.h +117 -0
- package/deps/librdkafka/src/rdkafka_topic.c +2382 -0
- package/deps/librdkafka/src/rdkafka_topic.h +369 -0
- package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
- package/deps/librdkafka/src/rdkafka_transport.h +99 -0
- package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
- package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
- package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
- package/deps/librdkafka/src/rdlist.c +593 -0
- package/deps/librdkafka/src/rdlist.h +444 -0
- package/deps/librdkafka/src/rdlog.c +89 -0
- package/deps/librdkafka/src/rdlog.h +41 -0
- package/deps/librdkafka/src/rdmap.c +508 -0
- package/deps/librdkafka/src/rdmap.h +492 -0
- package/deps/librdkafka/src/rdmurmur2.c +167 -0
- package/deps/librdkafka/src/rdmurmur2.h +35 -0
- package/deps/librdkafka/src/rdports.c +61 -0
- package/deps/librdkafka/src/rdports.h +38 -0
- package/deps/librdkafka/src/rdposix.h +250 -0
- package/deps/librdkafka/src/rdrand.c +151 -0
- package/deps/librdkafka/src/rdrand.h +72 -0
- package/deps/librdkafka/src/rdregex.c +156 -0
- package/deps/librdkafka/src/rdregex.h +43 -0
- package/deps/librdkafka/src/rdsignal.h +57 -0
- package/deps/librdkafka/src/rdstring.c +645 -0
- package/deps/librdkafka/src/rdstring.h +98 -0
- package/deps/librdkafka/src/rdsysqueue.h +404 -0
- package/deps/librdkafka/src/rdtime.h +356 -0
- package/deps/librdkafka/src/rdtypes.h +86 -0
- package/deps/librdkafka/src/rdunittest.c +564 -0
- package/deps/librdkafka/src/rdunittest.h +232 -0
- package/deps/librdkafka/src/rdunittest_acknowledge.c +1177 -0
- package/deps/librdkafka/src/rdunittest_fetcher.c +1211 -0
- package/deps/librdkafka/src/rdunittest_msgset_errors.c +1521 -0
- package/deps/librdkafka/src/rdvarint.c +134 -0
- package/deps/librdkafka/src/rdvarint.h +165 -0
- package/deps/librdkafka/src/rdwin32.h +382 -0
- package/deps/librdkafka/src/rdxxhash.c +1030 -0
- package/deps/librdkafka/src/rdxxhash.h +328 -0
- package/deps/librdkafka/src/regexp.c +1352 -0
- package/deps/librdkafka/src/regexp.h +41 -0
- package/deps/librdkafka/src/snappy.c +1866 -0
- package/deps/librdkafka/src/snappy.h +62 -0
- package/deps/librdkafka/src/snappy_compat.h +138 -0
- package/deps/librdkafka/src/statistics_schema.json +444 -0
- package/deps/librdkafka/src/tinycthread.c +932 -0
- package/deps/librdkafka/src/tinycthread.h +503 -0
- package/deps/librdkafka/src/tinycthread_extra.c +210 -0
- package/deps/librdkafka/src/tinycthread_extra.h +218 -0
- package/deps/librdkafka/src/win32_config.h +58 -0
- package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
- package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
- package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
- package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
- package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
- package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
- package/deps/librdkafka/src-cpp/Makefile +55 -0
- package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
- package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
- package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
- package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
- package/deps/librdkafka/src-cpp/README.md +16 -0
- package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
- package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
- package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
- package/deps/librdkafka/tests/0000-unittests.c +72 -0
- package/deps/librdkafka/tests/0001-multiobj.c +102 -0
- package/deps/librdkafka/tests/0002-unkpart.c +244 -0
- package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
- package/deps/librdkafka/tests/0004-conf.c +934 -0
- package/deps/librdkafka/tests/0005-order.c +133 -0
- package/deps/librdkafka/tests/0006-symbols.c +163 -0
- package/deps/librdkafka/tests/0007-autotopic.c +136 -0
- package/deps/librdkafka/tests/0008-reqacks.c +179 -0
- package/deps/librdkafka/tests/0009-mock_cluster.c +272 -0
- package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
- package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
- package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
- package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
- package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
- package/deps/librdkafka/tests/0016-client_swname.c +181 -0
- package/deps/librdkafka/tests/0017-compression.c +140 -0
- package/deps/librdkafka/tests/0018-cgrp_term.c +444 -0
- package/deps/librdkafka/tests/0019-list_groups.c +289 -0
- package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
- package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
- package/deps/librdkafka/tests/0022-consume_batch.c +331 -0
- package/deps/librdkafka/tests/0025-timers.c +147 -0
- package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
- package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
- package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
- package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
- package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
- package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
- package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
- package/deps/librdkafka/tests/0035-api_version.c +73 -0
- package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
- package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
- package/deps/librdkafka/tests/0038-performance.c +121 -0
- package/deps/librdkafka/tests/0039-event.c +284 -0
- package/deps/librdkafka/tests/0040-io_event.c +257 -0
- package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
- package/deps/librdkafka/tests/0042-many_topics.c +252 -0
- package/deps/librdkafka/tests/0043-no_connection.c +77 -0
- package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
- package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
- package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
- package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
- package/deps/librdkafka/tests/0048-partitioner.c +283 -0
- package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
- package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
- package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
- package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
- package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
- package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
- package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
- package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
- package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
- package/deps/librdkafka/tests/0058-log.cpp +123 -0
- package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
- package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
- package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
- package/deps/librdkafka/tests/0062-stats_event.c +126 -0
- package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
- package/deps/librdkafka/tests/0064-interceptors.c +529 -0
- package/deps/librdkafka/tests/0065-yield.cpp +140 -0
- package/deps/librdkafka/tests/0066-plugins.cpp +143 -0
- package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
- package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
- package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
- package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
- package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
- package/deps/librdkafka/tests/0073-headers.c +381 -0
- package/deps/librdkafka/tests/0074-producev.c +87 -0
- package/deps/librdkafka/tests/0075-retry.c +290 -0
- package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
- package/deps/librdkafka/tests/0077-compaction.c +366 -0
- package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
- package/deps/librdkafka/tests/0079-fork.c +93 -0
- package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
- package/deps/librdkafka/tests/0081-admin.c +5633 -0
- package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
- package/deps/librdkafka/tests/0083-cb_event.c +233 -0
- package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
- package/deps/librdkafka/tests/0085-headers.cpp +392 -0
- package/deps/librdkafka/tests/0086-purge.c +368 -0
- package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
- package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
- package/deps/librdkafka/tests/0090-idempotence.c +171 -0
- package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
- package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
- package/deps/librdkafka/tests/0093-holb.c +200 -0
- package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
- package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
- package/deps/librdkafka/tests/0097-ssl_verify.cpp +674 -0
- package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
- package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
- package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
- package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
- package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
- package/deps/librdkafka/tests/0103-transactions.c +1383 -0
- package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
- package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
- package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
- package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
- package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
- package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
- package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
- package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
- package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
- package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
- package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
- package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
- package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
- package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
- package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
- package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
- package/deps/librdkafka/tests/0121-clusterid.c +115 -0
- package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
- package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
- package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
- package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
- package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +1164 -0
- package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
- package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +217 -0
- package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
- package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
- package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
- package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
- package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
- package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
- package/deps/librdkafka/tests/0135-sasl_credentials.cpp +279 -0
- package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
- package/deps/librdkafka/tests/0137-barrier_batch_consume.c +752 -0
- package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
- package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
- package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
- package/deps/librdkafka/tests/0142-reauthentication.c +931 -0
- package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
- package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
- package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
- package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
- package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +1210 -0
- package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +569 -0
- package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
- package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
- 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/0155-share_group_heartbeat_mock.c +2695 -0
- package/deps/librdkafka/tests/0156-share_consumer_fetch_mock.c +1551 -0
- package/deps/librdkafka/tests/0157-share_consumer_ack_mock.c +1788 -0
- package/deps/librdkafka/tests/0158-share_consumer_transactions_mock.c +467 -0
- package/deps/librdkafka/tests/0170-share_consumer_subscription.c +2192 -0
- package/deps/librdkafka/tests/0171-share_consumer_consume.c +2150 -0
- package/deps/librdkafka/tests/0172-share_consumer_acknowledge.c +1919 -0
- package/deps/librdkafka/tests/0173-share_consumer_commit_async.c +2735 -0
- package/deps/librdkafka/tests/0174-share_consumer_concurrency.c +1434 -0
- package/deps/librdkafka/tests/0175-share_consumer_groups.c +574 -0
- package/deps/librdkafka/tests/0176-share_consumer_commit_sync.c +2986 -0
- package/deps/librdkafka/tests/0177-share_consumer_transactions.c +1815 -0
- package/deps/librdkafka/tests/0178-share_consumer_close.c +2102 -0
- package/deps/librdkafka/tests/0179-share_consumer_destroy.c +2482 -0
- package/deps/librdkafka/tests/0180-share_consumer_config.c +1677 -0
- package/deps/librdkafka/tests/0181-share_consumer_topic_delete.c +354 -0
- package/deps/librdkafka/tests/0182-share_consumer_error_handling_mock.c +3358 -0
- package/deps/librdkafka/tests/0183-share_consumer_leader_change_mock.c +1234 -0
- package/deps/librdkafka/tests/0184-share_consumer_topic_recreate.c +1356 -0
- package/deps/librdkafka/tests/0185-share_consumer_max_poll_interval.c +557 -0
- package/deps/librdkafka/tests/0186-share_consumer_fatal_error.c +360 -0
- package/deps/librdkafka/tests/0190-share_consumer_telemetry.c +387 -0
- package/deps/librdkafka/tests/1000-unktopic.c +164 -0
- package/deps/librdkafka/tests/8000-idle.cpp +60 -0
- package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
- package/deps/librdkafka/tests/CMakeLists.txt +193 -0
- package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
- package/deps/librdkafka/tests/Makefile +182 -0
- package/deps/librdkafka/tests/README.md +514 -0
- package/deps/librdkafka/tests/autotest.sh +33 -0
- package/deps/librdkafka/tests/backtrace.gdb +30 -0
- package/deps/librdkafka/tests/broker_version_tests.py +315 -0
- package/deps/librdkafka/tests/buildbox.sh +17 -0
- package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
- package/deps/librdkafka/tests/cluster_testing.py +203 -0
- package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
- package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
- package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
- package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -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 +50 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
- package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
- package/deps/librdkafka/tests/fuzzers/README.md +31 -0
- package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
- package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
- package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
- package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
- package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
- package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
- package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
- package/deps/librdkafka/tests/java/Makefile +13 -0
- package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
- package/deps/librdkafka/tests/java/README.md +14 -0
- package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
- package/deps/librdkafka/tests/java/run-class.sh +11 -0
- package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
- package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
- package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
- package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
- package/deps/librdkafka/tests/performance_plot.py +115 -0
- package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
- package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
- package/deps/librdkafka/tests/requirements.txt +2 -0
- package/deps/librdkafka/tests/run-all-tests.sh +81 -0
- package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-test-batches.py +157 -0
- package/deps/librdkafka/tests/run-test.sh +141 -0
- package/deps/librdkafka/tests/rusage.c +249 -0
- package/deps/librdkafka/tests/sasl_test.py +289 -0
- package/deps/librdkafka/tests/scenarios/README.md +6 -0
- package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
- package/deps/librdkafka/tests/scenarios/default.json +5 -0
- package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
- package/deps/librdkafka/tests/share_telemetry_verify/share-otel-collector-config.yaml +28 -0
- package/deps/librdkafka/tests/sockem.c +801 -0
- package/deps/librdkafka/tests/sockem.h +85 -0
- package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
- package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
- package/deps/librdkafka/tests/test.c +8376 -0
- package/deps/librdkafka/tests/test.conf.example +27 -0
- package/deps/librdkafka/tests/test.h +1150 -0
- package/deps/librdkafka/tests/testcpp.cpp +131 -0
- package/deps/librdkafka/tests/testcpp.h +388 -0
- package/deps/librdkafka/tests/testshared.h +416 -0
- package/deps/librdkafka/tests/tools/README.md +4 -0
- package/deps/librdkafka/tests/tools/stats/README.md +21 -0
- package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
- package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
- package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
- package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
- package/deps/librdkafka/tests/trivup/trivup-0.15.0.tar.gz +0 -0
- package/deps/librdkafka/tests/until-fail.sh +87 -0
- package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
- package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
- package/deps/librdkafka/vcpkg.json +23 -0
- package/deps/librdkafka/win32/README.md +5 -0
- package/deps/librdkafka/win32/build-package.bat +3 -0
- package/deps/librdkafka/win32/build.bat +19 -0
- package/deps/librdkafka/win32/common.vcxproj +84 -0
- package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
- package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
- package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
- package/deps/librdkafka/win32/librdkafka.sln +226 -0
- package/deps/librdkafka/win32/librdkafka.vcxproj +282 -0
- package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
- package/deps/librdkafka/win32/msbuild.ps1 +58 -0
- package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
- package/deps/librdkafka/win32/package-zip.ps1 +46 -0
- package/deps/librdkafka/win32/packages/repositories.config +4 -0
- package/deps/librdkafka/win32/push-package.bat +4 -0
- package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
- package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
- package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
- package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
- package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
- package/deps/librdkafka/win32/tests/test.conf.example +25 -0
- package/deps/librdkafka/win32/tests/tests.vcxproj +278 -0
- package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
- package/deps/librdkafka/win32/wingetopt.c +564 -0
- package/deps/librdkafka/win32/wingetopt.h +101 -0
- package/deps/librdkafka/win32/wintime.h +33 -0
- package/deps/librdkafka.gyp +83 -0
- package/deps/windows-install.py +80 -0
- package/index.d.ts +3 -0
- package/lib/admin.js +732 -0
- package/lib/client.js +679 -0
- package/lib/error.js +501 -0
- package/lib/index.js +8 -0
- package/lib/kafka-consumer-stream.js +399 -0
- package/lib/kafka-consumer.js +798 -0
- package/lib/kafkajs/_admin.js +1052 -0
- package/lib/kafkajs/_common.js +887 -0
- package/lib/kafkajs/_consumer.js +2156 -0
- package/lib/kafkajs/_consumer_cache.js +310 -0
- package/lib/kafkajs/_error.js +298 -0
- package/lib/kafkajs/_kafka.js +125 -0
- package/lib/kafkajs/_linked-list.js +220 -0
- package/lib/kafkajs/_producer.js +863 -0
- package/lib/kafkajs/index.js +5 -0
- package/lib/producer/high-level-producer.js +400 -0
- package/lib/producer-stream.js +337 -0
- package/lib/producer.js +405 -0
- package/lib/rdkafka.js +44 -0
- package/lib/tools/ref-counter.js +53 -0
- package/lib/topic-partition.js +91 -0
- package/lib/topic.js +43 -0
- package/lib/util.js +55 -0
- package/librdkafka.js +12 -0
- package/package.json +85 -0
- package/shim/source_location +54 -0
- package/src/admin.cc +1597 -0
- package/src/admin.h +112 -0
- package/src/binding.cc +76 -0
- package/src/binding.h +25 -0
- package/src/callbacks.cc +676 -0
- package/src/callbacks.h +302 -0
- package/src/common.cc +1628 -0
- package/src/common.h +192 -0
- package/src/config.cc +219 -0
- package/src/config.h +61 -0
- package/src/connection.cc +703 -0
- package/src/connection.h +117 -0
- package/src/errors.cc +119 -0
- package/src/errors.h +60 -0
- package/src/kafka-consumer.cc +1539 -0
- package/src/kafka-consumer.h +147 -0
- package/src/producer.cc +917 -0
- package/src/producer.h +124 -0
- package/src/topic.cc +173 -0
- package/src/topic.h +54 -0
- package/src/workers.cc +1714 -0
- package/src/workers.h +690 -0
- package/types/config.d.ts +1269 -0
- package/types/errors.d.ts +373 -0
- package/types/kafkajs.d.ts +568 -0
- package/types/rdkafka.d.ts +571 -0
- package/util/configure.js +32 -0
- package/util/generate-docs.sh +18 -0
- package/util/get-env.js +6 -0
- package/util/test-compile.js +11 -0
- package/util/test-producer-delivery.js +100 -0
|
@@ -0,0 +1,1234 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* librdkafka - Apache Kafka C library
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2026, Confluent Inc.
|
|
5
|
+
* All rights reserved.
|
|
6
|
+
*
|
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
|
9
|
+
*
|
|
10
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
|
11
|
+
* this list of conditions and the following disclaimer.
|
|
12
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
* and/or other materials provided with the distribution.
|
|
15
|
+
*
|
|
16
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
19
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
20
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
21
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
22
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
23
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
24
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
25
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
26
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#include "test.h"
|
|
30
|
+
|
|
31
|
+
#include "../src/rdkafka_proto.h"
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @brief Share consumer leader change tests.
|
|
35
|
+
*
|
|
36
|
+
* Verifies that per-partition leader-change errors on ShareAcknowledge
|
|
37
|
+
* trigger metadata refresh and that unnecessary RPCs are avoided once
|
|
38
|
+
* the client discovers the new leader.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
#define CONSUME_ARRAY 1024
|
|
42
|
+
|
|
43
|
+
/* ===================================================================
|
|
44
|
+
* Mock broker infrastructure.
|
|
45
|
+
* =================================================================== */
|
|
46
|
+
typedef struct test_ctx_s {
|
|
47
|
+
rd_kafka_t *producer;
|
|
48
|
+
rd_kafka_mock_cluster_t *mcluster;
|
|
49
|
+
const char *bootstraps;
|
|
50
|
+
} test_ctx_t;
|
|
51
|
+
|
|
52
|
+
static test_ctx_t test_ctx_new(int nbrok) {
|
|
53
|
+
test_ctx_t ctx;
|
|
54
|
+
rd_kafka_conf_t *conf;
|
|
55
|
+
char errstr[512];
|
|
56
|
+
|
|
57
|
+
memset(&ctx, 0, sizeof(ctx));
|
|
58
|
+
|
|
59
|
+
ctx.mcluster = test_mock_cluster_new(nbrok, &ctx.bootstraps);
|
|
60
|
+
|
|
61
|
+
TEST_ASSERT(rd_kafka_mock_set_apiversion(
|
|
62
|
+
ctx.mcluster, RD_KAFKAP_ShareGroupHeartbeat, 1, 1) ==
|
|
63
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
64
|
+
"Failed to enable ShareGroupHeartbeat");
|
|
65
|
+
TEST_ASSERT(rd_kafka_mock_set_apiversion(ctx.mcluster,
|
|
66
|
+
RD_KAFKAP_ShareFetch, 1, 1) ==
|
|
67
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
68
|
+
"Failed to enable ShareFetch");
|
|
69
|
+
|
|
70
|
+
rd_kafka_mock_sharegroup_set_auto_offset_reset(ctx.mcluster, 1);
|
|
71
|
+
|
|
72
|
+
test_conf_init(&conf, NULL, 0);
|
|
73
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
74
|
+
rd_kafka_conf_set_dr_msg_cb(conf, test_dr_msg_cb);
|
|
75
|
+
|
|
76
|
+
ctx.producer =
|
|
77
|
+
rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr));
|
|
78
|
+
TEST_ASSERT(ctx.producer != NULL, "Failed to create producer: %s",
|
|
79
|
+
errstr);
|
|
80
|
+
|
|
81
|
+
return ctx;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static void test_ctx_destroy(test_ctx_t *ctx) {
|
|
85
|
+
if (ctx->producer)
|
|
86
|
+
rd_kafka_destroy(ctx->producer);
|
|
87
|
+
if (ctx->mcluster)
|
|
88
|
+
test_mock_cluster_destroy(ctx->mcluster);
|
|
89
|
+
memset(ctx, 0, sizeof(*ctx));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static void subscribe_topics(rd_kafka_share_t *rkshare,
|
|
93
|
+
const char **topics,
|
|
94
|
+
int topic_cnt) {
|
|
95
|
+
rd_kafka_topic_partition_list_t *subs;
|
|
96
|
+
rd_kafka_resp_err_t err;
|
|
97
|
+
int i;
|
|
98
|
+
|
|
99
|
+
subs = rd_kafka_topic_partition_list_new(topic_cnt);
|
|
100
|
+
for (i = 0; i < topic_cnt; i++)
|
|
101
|
+
rd_kafka_topic_partition_list_add(subs, topics[i],
|
|
102
|
+
RD_KAFKA_PARTITION_UA);
|
|
103
|
+
err = rd_kafka_share_subscribe(rkshare, subs);
|
|
104
|
+
TEST_ASSERT(!err, "subscribe failed: %s", rd_kafka_err2str(err));
|
|
105
|
+
rd_kafka_topic_partition_list_destroy(subs);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static void subscribe_one(rd_kafka_share_t *rkshare, const char *topic) {
|
|
109
|
+
subscribe_topics(rkshare, &topic, 1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static int mock_produce(rd_kafka_t *producer,
|
|
113
|
+
const char *topic,
|
|
114
|
+
int32_t partition,
|
|
115
|
+
int msgcnt) {
|
|
116
|
+
int i;
|
|
117
|
+
for (i = 0; i < msgcnt; i++) {
|
|
118
|
+
char payload[64];
|
|
119
|
+
snprintf(payload, sizeof(payload), "%s-p%" PRId32 "-%d", topic,
|
|
120
|
+
partition, i);
|
|
121
|
+
TEST_ASSERT(rd_kafka_producev(
|
|
122
|
+
producer, RD_KAFKA_V_TOPIC(topic),
|
|
123
|
+
RD_KAFKA_V_PARTITION(partition),
|
|
124
|
+
RD_KAFKA_V_VALUE(payload, strlen(payload)),
|
|
125
|
+
RD_KAFKA_V_MSGFLAGS(RD_KAFKA_MSG_F_COPY),
|
|
126
|
+
RD_KAFKA_V_END) == RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
127
|
+
"Produce to %s [%" PRId32 "] failed", topic,
|
|
128
|
+
partition);
|
|
129
|
+
}
|
|
130
|
+
rd_kafka_flush(producer, 5000);
|
|
131
|
+
return msgcnt;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static rd_bool_t is_share_ack_request(rd_kafka_mock_request_t *request,
|
|
135
|
+
void *opaque) {
|
|
136
|
+
return rd_kafka_mock_request_api_key(request) ==
|
|
137
|
+
RD_KAFKAP_ShareAcknowledge;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static rd_bool_t is_share_fetch_request(rd_kafka_mock_request_t *request,
|
|
141
|
+
void *opaque) {
|
|
142
|
+
return rd_kafka_mock_request_api_key(request) == RD_KAFKAP_ShareFetch;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static rd_bool_t is_metadata_request(rd_kafka_mock_request_t *request,
|
|
146
|
+
void *opaque) {
|
|
147
|
+
return rd_kafka_mock_request_api_key(request) == RD_KAFKAP_Metadata;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
/* ===================================================================
|
|
152
|
+
* Test — ShareAcknowledge per-partition NOT_LEADER_OR_FOLLOWER
|
|
153
|
+
* should trigger metadata refresh and avoid redundant RPCs.
|
|
154
|
+
*
|
|
155
|
+
* Setup:
|
|
156
|
+
* - 2 brokers, 1 topic, 1 partition on broker 1
|
|
157
|
+
* - Explicit ack mode, background metadata refresh disabled
|
|
158
|
+
* - Produce 10 records, consume one batch (expect all 10)
|
|
159
|
+
* - Move leader to broker 2
|
|
160
|
+
*
|
|
161
|
+
* Loop (5 iterations):
|
|
162
|
+
* - Acknowledge 2 records from the held batch
|
|
163
|
+
* - commit_sync → attempts to route the batch to the cached
|
|
164
|
+
* leader. Round 1 routes to broker 1 (cache is stale);
|
|
165
|
+
* rounds 2-5 are short-circuited locally (see Expected
|
|
166
|
+
* behavior below).
|
|
167
|
+
*
|
|
168
|
+
* Expected behavior with this PR:
|
|
169
|
+
* - The first commit_sync sends a ShareAcknowledge to broker 1
|
|
170
|
+
* (cache still says broker 1 is leader). The response carries
|
|
171
|
+
* NOT_LEADER_OR_FOLLOWER plus a CurrentLeader hint and
|
|
172
|
+
* NodeEndpoints; the inline metadata update applies the new
|
|
173
|
+
* leader to the cache without a separate Metadata RPC.
|
|
174
|
+
* - Rounds 2-5 are caught by the local leader-stale short-circuit
|
|
175
|
+
* in rd_kafka_share_ack_batch_resolve_leader_or_fail_acks and
|
|
176
|
+
* fail without sending an RPC.
|
|
177
|
+
* - All 5 commit_sync return NOT_LEADER_OR_FOLLOWER.
|
|
178
|
+
* - 1 ShareAcknowledge RPC total, 0 Metadata RPCs.
|
|
179
|
+
* =================================================================== */
|
|
180
|
+
static void test_shareack_leader_change_reduces_rpcs(void) {
|
|
181
|
+
test_ctx_t ctx;
|
|
182
|
+
rd_kafka_conf_t *conf;
|
|
183
|
+
rd_kafka_share_t *rkshare;
|
|
184
|
+
rd_kafka_error_t *error;
|
|
185
|
+
const char *topic = "0183-shareack-nlof";
|
|
186
|
+
const char *group = "sg-0183-shareack-nlof";
|
|
187
|
+
const int broker1 = 1;
|
|
188
|
+
const int broker2 = 2;
|
|
189
|
+
const int msgcnt = 10;
|
|
190
|
+
const int acks_per_commit = 2;
|
|
191
|
+
const int commit_rounds = msgcnt / acks_per_commit;
|
|
192
|
+
rd_kafka_messages_t *batch = NULL;
|
|
193
|
+
int round;
|
|
194
|
+
size_t rcvd = 0;
|
|
195
|
+
size_t consumed_idx = 0;
|
|
196
|
+
size_t share_ack_cnt;
|
|
197
|
+
size_t metadata_cnt;
|
|
198
|
+
|
|
199
|
+
SUB_TEST_QUICK();
|
|
200
|
+
|
|
201
|
+
ctx = test_ctx_new(2);
|
|
202
|
+
|
|
203
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
204
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
205
|
+
"create topic");
|
|
206
|
+
|
|
207
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster, topic, 0,
|
|
208
|
+
broker1) ==
|
|
209
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
210
|
+
"set initial leader to broker %d", broker1);
|
|
211
|
+
|
|
212
|
+
mock_produce(ctx.producer, topic, RD_KAFKA_PARTITION_UA, msgcnt);
|
|
213
|
+
|
|
214
|
+
test_conf_init(&conf, NULL, 0);
|
|
215
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
216
|
+
test_conf_set(conf, "group.id", group);
|
|
217
|
+
test_conf_set(conf, "share.acknowledgement.mode", "explicit");
|
|
218
|
+
test_conf_set(conf, "topic.metadata.refresh.interval.ms", "-1");
|
|
219
|
+
rkshare = rd_kafka_share_consumer_new(conf, NULL, 0);
|
|
220
|
+
TEST_ASSERT(rkshare != NULL, "Failed to create share consumer");
|
|
221
|
+
subscribe_one(rkshare, topic);
|
|
222
|
+
|
|
223
|
+
/* Consume one batch — expect all 10 records in a single call. */
|
|
224
|
+
error = rd_kafka_share_poll(rkshare, 10000, &batch);
|
|
225
|
+
TEST_ASSERT(!error, "share_poll failed: %s",
|
|
226
|
+
error ? rd_kafka_error_string(error) : "");
|
|
227
|
+
rcvd = rd_kafka_messages_count(batch);
|
|
228
|
+
TEST_ASSERT(rcvd == (size_t)msgcnt,
|
|
229
|
+
"expected %d records in first batch, got %" PRIusz, msgcnt,
|
|
230
|
+
rcvd);
|
|
231
|
+
|
|
232
|
+
/* Move leader to broker 2 before acknowledging. */
|
|
233
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster, topic, 0,
|
|
234
|
+
broker2) ==
|
|
235
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
236
|
+
"set leader to broker %d", broker2);
|
|
237
|
+
|
|
238
|
+
rd_kafka_mock_start_request_tracking(ctx.mcluster);
|
|
239
|
+
rd_kafka_mock_clear_requests(ctx.mcluster);
|
|
240
|
+
|
|
241
|
+
/* 5 rounds: acknowledge 2 records, commitSync each time.
|
|
242
|
+
* Each commitSync should get NOT_LEADER_OR_FOLLOWER. */
|
|
243
|
+
for (round = 0; round < commit_rounds; round++) {
|
|
244
|
+
rd_kafka_topic_partition_list_t *results = NULL;
|
|
245
|
+
int k;
|
|
246
|
+
|
|
247
|
+
for (k = 0;
|
|
248
|
+
k < acks_per_commit && consumed_idx < (size_t)msgcnt;
|
|
249
|
+
k++, consumed_idx++) {
|
|
250
|
+
rd_kafka_resp_err_t ack_err;
|
|
251
|
+
ack_err = rd_kafka_share_acknowledge(
|
|
252
|
+
rkshare,
|
|
253
|
+
rd_kafka_messages_get(batch, consumed_idx));
|
|
254
|
+
TEST_ASSERT(ack_err == RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
255
|
+
"round %d: acknowledge failed: %s", round,
|
|
256
|
+
rd_kafka_err2str(ack_err));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
error = rd_kafka_share_commit_sync(rkshare, 500, &results);
|
|
260
|
+
|
|
261
|
+
TEST_SAY("round %d: commit_sync returned %s\n", round,
|
|
262
|
+
error ? rd_kafka_error_string(error) : "success");
|
|
263
|
+
|
|
264
|
+
TEST_ASSERT(results != NULL && results->cnt > 0,
|
|
265
|
+
"round %d: expected results from commit_sync",
|
|
266
|
+
round);
|
|
267
|
+
|
|
268
|
+
for (k = 0; k < results->cnt; k++) {
|
|
269
|
+
TEST_SAY(" round %d: partition %s [%" PRId32
|
|
270
|
+
"] err=%s\n",
|
|
271
|
+
round, results->elems[k].topic,
|
|
272
|
+
results->elems[k].partition,
|
|
273
|
+
rd_kafka_err2name(results->elems[k].err));
|
|
274
|
+
TEST_ASSERT(
|
|
275
|
+
results->elems[k].err ==
|
|
276
|
+
RD_KAFKA_RESP_ERR_NOT_LEADER_OR_FOLLOWER,
|
|
277
|
+
"round %d: expected NOT_LEADER_OR_FOLLOWER, "
|
|
278
|
+
"got %s",
|
|
279
|
+
round, rd_kafka_err2name(results->elems[k].err));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
rd_kafka_topic_partition_list_destroy(results);
|
|
283
|
+
|
|
284
|
+
if (error)
|
|
285
|
+
rd_kafka_error_destroy(error);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
share_ack_cnt = test_mock_get_matching_request_cnt(
|
|
289
|
+
ctx.mcluster, is_share_ack_request, NULL);
|
|
290
|
+
metadata_cnt = test_mock_get_matching_request_cnt(
|
|
291
|
+
ctx.mcluster, is_metadata_request, NULL);
|
|
292
|
+
|
|
293
|
+
TEST_SAY("ShareAcknowledge requests after leader change: %" PRIusz "\n",
|
|
294
|
+
share_ack_cnt);
|
|
295
|
+
TEST_SAY("Metadata requests after leader change: %" PRIusz "\n",
|
|
296
|
+
metadata_cnt);
|
|
297
|
+
|
|
298
|
+
/* The first commit_sync sends a ShareAcknowledge RPC to the
|
|
299
|
+
* stale broker; the response carries CurrentLeader and
|
|
300
|
+
* NodeEndpoints which update the metadata cache inline.
|
|
301
|
+
* Rounds 2-5 are caught by the local leader-stale check and
|
|
302
|
+
* fail without sending an RPC. No separate Metadata RPC is
|
|
303
|
+
* needed because the cache update is inline. */
|
|
304
|
+
TEST_ASSERT(share_ack_cnt == 1,
|
|
305
|
+
"expected 1 ShareAcknowledge RPC, got %" PRIusz,
|
|
306
|
+
share_ack_cnt);
|
|
307
|
+
TEST_ASSERT(metadata_cnt == 0,
|
|
308
|
+
"expected 0 Metadata RPCs (inline cache update), "
|
|
309
|
+
"got %" PRIusz,
|
|
310
|
+
metadata_cnt);
|
|
311
|
+
|
|
312
|
+
rd_kafka_mock_stop_request_tracking(ctx.mcluster);
|
|
313
|
+
|
|
314
|
+
/* Clean up held message handles. */
|
|
315
|
+
rd_kafka_messages_destroy(batch);
|
|
316
|
+
batch = NULL;
|
|
317
|
+
|
|
318
|
+
test_share_consumer_close(rkshare);
|
|
319
|
+
test_share_destroy(rkshare);
|
|
320
|
+
test_ctx_destroy(&ctx);
|
|
321
|
+
|
|
322
|
+
SUB_TEST_PASS();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
/* ===================================================================
|
|
327
|
+
* Test — per-partition NOT_LEADER_OR_FOLLOWER on ShareFetch is
|
|
328
|
+
* handled silently: no OP_CONSUMER_ERR, consumer recovers
|
|
329
|
+
* and continues reading from the new leader.
|
|
330
|
+
*
|
|
331
|
+
* Two-broker mock cluster. Phase 1 produces and consumes records
|
|
332
|
+
* from broker1. The partition leader is moved to broker2. Phase 2
|
|
333
|
+
* verifies the consumer silently recovers and reads new records
|
|
334
|
+
* from broker2.
|
|
335
|
+
*
|
|
336
|
+
* Wire-level verification: at least 1 Metadata request is triggered
|
|
337
|
+
* (error handler fired metadata refresh) and ShareFetch count stays
|
|
338
|
+
* below 10 (no retry storm). The NOT_LEADER_OR_FOLLOWER response
|
|
339
|
+
* may arrive before or after request tracking starts, so a >= 2
|
|
340
|
+
* ShareFetch lower bound is not reliable; >= 1 is the meaningful
|
|
341
|
+
* minimum.
|
|
342
|
+
*
|
|
343
|
+
* TODO KIP-932: Add a real-broker companion test that triggers a
|
|
344
|
+
* leader change on a multi-broker cluster.
|
|
345
|
+
* =================================================================== */
|
|
346
|
+
static void test_partition_not_leader_or_follower_silent(void) {
|
|
347
|
+
test_ctx_t ctx;
|
|
348
|
+
rd_kafka_conf_t *conf;
|
|
349
|
+
rd_kafka_share_t *rkshare;
|
|
350
|
+
rd_kafka_error_t *error;
|
|
351
|
+
const char *topic = "0183-nlof-silent";
|
|
352
|
+
const char *group = "sg-0183-nlof-silent";
|
|
353
|
+
const int broker1 = 1;
|
|
354
|
+
const int broker2 = 2;
|
|
355
|
+
const int msgcnt = 5;
|
|
356
|
+
rd_kafka_messages_t *batch = NULL;
|
|
357
|
+
int phase1_consumed = 0;
|
|
358
|
+
int phase2_consumed = 0;
|
|
359
|
+
int error_cnt = 0;
|
|
360
|
+
int attempts = 0;
|
|
361
|
+
size_t rcvd = 0;
|
|
362
|
+
size_t share_fetch_cnt;
|
|
363
|
+
size_t metadata_cnt;
|
|
364
|
+
size_t j;
|
|
365
|
+
|
|
366
|
+
SUB_TEST_QUICK();
|
|
367
|
+
|
|
368
|
+
ctx = test_ctx_new(2);
|
|
369
|
+
|
|
370
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
371
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
372
|
+
"create topic");
|
|
373
|
+
|
|
374
|
+
/* Explicitly set the initial leader (do not assume a default). */
|
|
375
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster, topic, 0,
|
|
376
|
+
broker1) ==
|
|
377
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
378
|
+
"set initial leader to broker %d", broker1);
|
|
379
|
+
|
|
380
|
+
/* Phase 1: produce and consume records from broker1.
|
|
381
|
+
* auto.offset.reset=earliest (set by test_ctx_new) so the
|
|
382
|
+
* share group starts from the beginning of the log. */
|
|
383
|
+
mock_produce(ctx.producer, topic, RD_KAFKA_PARTITION_UA, msgcnt);
|
|
384
|
+
|
|
385
|
+
/* Disable background metadata refresh so that the only metadata
|
|
386
|
+
* refresh that fires is the one triggered by the per-partition
|
|
387
|
+
* NOT_LEADER_OR_FOLLOWER error. This makes the >= 2 ShareFetch
|
|
388
|
+
* assertion deterministic: background refresh would otherwise
|
|
389
|
+
* silently update the cached leader before Phase 2 starts. */
|
|
390
|
+
test_conf_init(&conf, NULL, 0);
|
|
391
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
392
|
+
test_conf_set(conf, "group.id", group);
|
|
393
|
+
test_conf_set(conf, "share.acknowledgement.mode", "implicit");
|
|
394
|
+
test_conf_set(conf, "topic.metadata.refresh.interval.ms", "-1");
|
|
395
|
+
rkshare = rd_kafka_share_consumer_new(conf, NULL, 0);
|
|
396
|
+
TEST_ASSERT(rkshare != NULL, "Failed to create share consumer");
|
|
397
|
+
subscribe_one(rkshare, topic);
|
|
398
|
+
|
|
399
|
+
while (phase1_consumed < msgcnt && attempts++ < 30) {
|
|
400
|
+
error = rd_kafka_share_poll(rkshare, 3000, &batch);
|
|
401
|
+
if (error) {
|
|
402
|
+
rd_kafka_error_destroy(error);
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
rcvd = rd_kafka_messages_count(batch);
|
|
406
|
+
for (j = 0; j < rcvd; j++) {
|
|
407
|
+
rd_kafka_message_t *m = rd_kafka_messages_get(batch, j);
|
|
408
|
+
if (m && !m->err)
|
|
409
|
+
phase1_consumed++;
|
|
410
|
+
}
|
|
411
|
+
rd_kafka_messages_destroy(batch);
|
|
412
|
+
batch = NULL;
|
|
413
|
+
}
|
|
414
|
+
TEST_ASSERT(phase1_consumed == msgcnt,
|
|
415
|
+
"Phase 1: expected %d records from broker %d, got %d",
|
|
416
|
+
msgcnt, broker1, phase1_consumed);
|
|
417
|
+
|
|
418
|
+
/* Start request tracking before the leader change to capture
|
|
419
|
+
* ShareFetch requests sent after it. */
|
|
420
|
+
rd_kafka_mock_start_request_tracking(ctx.mcluster);
|
|
421
|
+
rd_kafka_mock_clear_requests(ctx.mcluster);
|
|
422
|
+
|
|
423
|
+
/* Move the partition leader to broker2. The consumer's next
|
|
424
|
+
* ShareFetch to broker1 will get NOT_LEADER_OR_FOLLOWER per
|
|
425
|
+
* partition, which triggers a silent metadata refresh and
|
|
426
|
+
* reconnect to broker2. */
|
|
427
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster, topic, 0,
|
|
428
|
+
broker2) ==
|
|
429
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
430
|
+
"set leader to broker %d", broker2);
|
|
431
|
+
|
|
432
|
+
/* Produce records that will be available on broker2. mock_produce
|
|
433
|
+
* flushes before returning, so all records are committed to
|
|
434
|
+
* broker2 before Phase 2 begins. */
|
|
435
|
+
mock_produce(ctx.producer, topic, RD_KAFKA_PARTITION_UA, msgcnt);
|
|
436
|
+
|
|
437
|
+
/* Phase 2: consume records after recovery. OP_CONSUMER_ERR
|
|
438
|
+
* surfaces as a non-NULL return from consume_batch; silent
|
|
439
|
+
* handling must keep that return NULL throughout recovery. */
|
|
440
|
+
attempts = 0;
|
|
441
|
+
while (phase2_consumed < msgcnt && attempts++ < 30) {
|
|
442
|
+
error = rd_kafka_share_poll(rkshare, 3000, &batch);
|
|
443
|
+
if (error) {
|
|
444
|
+
error_cnt++;
|
|
445
|
+
rd_kafka_error_destroy(error);
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
rcvd = rd_kafka_messages_count(batch);
|
|
449
|
+
for (j = 0; j < rcvd; j++) {
|
|
450
|
+
rd_kafka_message_t *m = rd_kafka_messages_get(batch, j);
|
|
451
|
+
if (m && !m->err)
|
|
452
|
+
phase2_consumed++;
|
|
453
|
+
}
|
|
454
|
+
rd_kafka_messages_destroy(batch);
|
|
455
|
+
batch = NULL;
|
|
456
|
+
}
|
|
457
|
+
TEST_ASSERT(phase2_consumed >= msgcnt,
|
|
458
|
+
"Phase 2: expected >= %d records from broker %d after "
|
|
459
|
+
"recovery, got %d",
|
|
460
|
+
msgcnt, broker2, phase2_consumed);
|
|
461
|
+
TEST_ASSERT(error_cnt == 0,
|
|
462
|
+
"expected 0 OP_CONSUMER_ERR (NOT_LEADER_OR_FOLLOWER "
|
|
463
|
+
"must be silently handled), got %d",
|
|
464
|
+
error_cnt);
|
|
465
|
+
|
|
466
|
+
/* Verify the error handler fired (metadata refresh triggered) and
|
|
467
|
+
* did not cause a retry storm. The NOT_LEADER_OR_FOLLOWER response
|
|
468
|
+
* may be processed before or after request tracking starts, so only
|
|
469
|
+
* a Metadata lower bound (not a >= 2 ShareFetch) is reliable. */
|
|
470
|
+
share_fetch_cnt = test_mock_get_matching_request_cnt(
|
|
471
|
+
ctx.mcluster, is_share_fetch_request, NULL);
|
|
472
|
+
metadata_cnt = test_mock_get_matching_request_cnt(
|
|
473
|
+
ctx.mcluster, is_metadata_request, NULL);
|
|
474
|
+
TEST_SAY("ShareFetch requests after leader change: %" PRIusz "\n",
|
|
475
|
+
share_fetch_cnt);
|
|
476
|
+
TEST_SAY("Metadata requests after leader change: %" PRIusz "\n",
|
|
477
|
+
metadata_cnt);
|
|
478
|
+
TEST_ASSERT(metadata_cnt >= 1,
|
|
479
|
+
"expected >= 1 Metadata request after leader change "
|
|
480
|
+
"(error handler must have triggered metadata refresh), "
|
|
481
|
+
"got %" PRIusz,
|
|
482
|
+
metadata_cnt);
|
|
483
|
+
TEST_ASSERT(share_fetch_cnt >= 1,
|
|
484
|
+
"expected >= 1 ShareFetch request after leader change, "
|
|
485
|
+
"got %" PRIusz,
|
|
486
|
+
share_fetch_cnt);
|
|
487
|
+
TEST_ASSERT(share_fetch_cnt < 10,
|
|
488
|
+
"expected < 10 ShareFetch requests (no retry storm), "
|
|
489
|
+
"got %" PRIusz,
|
|
490
|
+
share_fetch_cnt);
|
|
491
|
+
|
|
492
|
+
rd_kafka_mock_stop_request_tracking(ctx.mcluster);
|
|
493
|
+
|
|
494
|
+
test_share_consumer_close(rkshare);
|
|
495
|
+
test_share_destroy(rkshare);
|
|
496
|
+
test_ctx_destroy(&ctx);
|
|
497
|
+
|
|
498
|
+
SUB_TEST_PASS();
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* @brief Drive a consume loop until \p expected records have been read
|
|
504
|
+
* or the attempt budget is exhausted. In implicit mode an extra
|
|
505
|
+
* zero-timeout consume_batch flushes the last batch's auto-ack
|
|
506
|
+
* before returning.
|
|
507
|
+
*/
|
|
508
|
+
static int consume_phase(rd_kafka_share_t *rkshare,
|
|
509
|
+
rd_bool_t explicit_mode,
|
|
510
|
+
rd_bool_t use_commit_sync,
|
|
511
|
+
int expected,
|
|
512
|
+
int post_first_batch_settle_ms,
|
|
513
|
+
const char *phase_name) {
|
|
514
|
+
int consumed = 0;
|
|
515
|
+
int attempts = 0;
|
|
516
|
+
int max_attempts = expected * 3 + 60;
|
|
517
|
+
rd_kafka_messages_t *batch = NULL;
|
|
518
|
+
rd_kafka_topic_partition_list_t *flush_results = NULL;
|
|
519
|
+
rd_kafka_error_t *flush_err;
|
|
520
|
+
rd_bool_t first_batch = rd_true;
|
|
521
|
+
int ri;
|
|
522
|
+
|
|
523
|
+
while (consumed < expected && attempts++ < max_attempts) {
|
|
524
|
+
size_t rcvd = 0;
|
|
525
|
+
rd_kafka_error_t *error;
|
|
526
|
+
size_t j;
|
|
527
|
+
|
|
528
|
+
error = rd_kafka_share_poll(rkshare, 3000, &batch);
|
|
529
|
+
if (error) {
|
|
530
|
+
TEST_SAY("%s: share_poll err %s\n", phase_name,
|
|
531
|
+
rd_kafka_error_string(error));
|
|
532
|
+
rd_kafka_error_destroy(error);
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
rcvd = rd_kafka_messages_count(batch);
|
|
537
|
+
for (j = 0; j < rcvd; j++) {
|
|
538
|
+
rd_kafka_message_t *m = rd_kafka_messages_get(batch, j);
|
|
539
|
+
if (m && !m->err) {
|
|
540
|
+
consumed++;
|
|
541
|
+
TEST_SAY("%s: record #%d: %s [%" PRId32
|
|
542
|
+
"] offset %" PRId64 "\n",
|
|
543
|
+
phase_name, consumed,
|
|
544
|
+
rd_kafka_topic_name(m->rkt),
|
|
545
|
+
m->partition, m->offset);
|
|
546
|
+
if (explicit_mode)
|
|
547
|
+
rd_kafka_share_acknowledge(rkshare, m);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
rd_kafka_messages_destroy(batch);
|
|
551
|
+
batch = NULL;
|
|
552
|
+
|
|
553
|
+
if (explicit_mode && rcvd > 0) {
|
|
554
|
+
if (use_commit_sync) {
|
|
555
|
+
rd_kafka_topic_partition_list_t *results = NULL;
|
|
556
|
+
rd_kafka_error_t *cerr;
|
|
557
|
+
TEST_SAY(
|
|
558
|
+
"%s: calling commit_sync "
|
|
559
|
+
"(consumed %d)\n",
|
|
560
|
+
phase_name, consumed);
|
|
561
|
+
cerr = rd_kafka_share_commit_sync(rkshare, 5000,
|
|
562
|
+
&results);
|
|
563
|
+
if (cerr) {
|
|
564
|
+
TEST_SAY("%s: commit_sync error: %s\n",
|
|
565
|
+
phase_name,
|
|
566
|
+
rd_kafka_error_string(cerr));
|
|
567
|
+
rd_kafka_error_destroy(cerr);
|
|
568
|
+
}
|
|
569
|
+
RD_IF_FREE(
|
|
570
|
+
results,
|
|
571
|
+
rd_kafka_topic_partition_list_destroy);
|
|
572
|
+
} else {
|
|
573
|
+
rd_kafka_error_t *cerr =
|
|
574
|
+
rd_kafka_share_commit_async(rkshare);
|
|
575
|
+
if (cerr) {
|
|
576
|
+
TEST_SAY("%s: commit_async error: %s\n",
|
|
577
|
+
phase_name,
|
|
578
|
+
rd_kafka_error_string(cerr));
|
|
579
|
+
rd_kafka_error_destroy(cerr);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/* After the first consume_batch call, let any pending
|
|
585
|
+
* metadata refresh and per-broker session
|
|
586
|
+
* reconciliation triggered by the leader change settle
|
|
587
|
+
* before the next consume_batch picks the next broker
|
|
588
|
+
* in round-robin. Without this wait the next broker's
|
|
589
|
+
* session is still stale, producing a redundant
|
|
590
|
+
* NOT_LEADER_FOR_PARTITION and metadata refresh. */
|
|
591
|
+
if (first_batch && post_first_batch_settle_ms > 0) {
|
|
592
|
+
rd_usleep(post_first_batch_settle_ms * 1000, NULL);
|
|
593
|
+
first_batch = rd_false;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* Flush before exiting: commit_sync auto-acks for implicit
|
|
598
|
+
* mode (via acknowledge_all_if_implicit) and drains pending
|
|
599
|
+
* acks for explicit mode. Using commit_sync for both modes
|
|
600
|
+
* avoids re-arming share_fetch_more_records via another
|
|
601
|
+
* consume_batch, which would keep the main-thread fetch loop
|
|
602
|
+
* spinning between phases. */
|
|
603
|
+
TEST_SAY("%s: calling commit_sync flush (consumed %d/%d)\n", phase_name,
|
|
604
|
+
consumed, expected);
|
|
605
|
+
flush_err = rd_kafka_share_commit_sync(rkshare, 5000, &flush_results);
|
|
606
|
+
if (flush_err) {
|
|
607
|
+
TEST_SAY("%s: commit_sync flush error: %s\n", phase_name,
|
|
608
|
+
rd_kafka_error_string(flush_err));
|
|
609
|
+
rd_kafka_error_destroy(flush_err);
|
|
610
|
+
} else {
|
|
611
|
+
TEST_SAY("%s: commit_sync flush succeeded\n", phase_name);
|
|
612
|
+
}
|
|
613
|
+
if (flush_results) {
|
|
614
|
+
for (ri = 0; ri < flush_results->cnt; ri++) {
|
|
615
|
+
rd_kafka_topic_partition_t *rp =
|
|
616
|
+
&flush_results->elems[ri];
|
|
617
|
+
TEST_SAY("%s: commit_sync result: %s [%" PRId32
|
|
618
|
+
"]: %s\n",
|
|
619
|
+
phase_name, rp->topic, rp->partition,
|
|
620
|
+
rd_kafka_err2str(rp->err));
|
|
621
|
+
}
|
|
622
|
+
rd_kafka_topic_partition_list_destroy(flush_results);
|
|
623
|
+
flush_results = NULL;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
TEST_SAY("%s: consumed %d (expected == %d) in %d attempts\n",
|
|
627
|
+
phase_name, consumed, expected, attempts);
|
|
628
|
+
return consumed;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
/* ===================================================================
|
|
633
|
+
* Test — produce / consume / leader-change / produce / consume on a
|
|
634
|
+
* multi-topic, multi-partition mock cluster. Verifies that
|
|
635
|
+
* the share consumer picks up the new leader either via the
|
|
636
|
+
* Share RPC error path (refresh disabled) or via background
|
|
637
|
+
* metadata refresh (refresh enabled).
|
|
638
|
+
*
|
|
639
|
+
* Setup:
|
|
640
|
+
* - 3 brokers, 2 topics ("recovery-a" with 2 partitions,
|
|
641
|
+
* "recovery-b" with 5 partitions). Initial leaders round-robin.
|
|
642
|
+
*
|
|
643
|
+
* Phase 1:
|
|
644
|
+
* - Produce a random 10-20 records per partition.
|
|
645
|
+
* - Consume them all, ack/commit per variant.
|
|
646
|
+
*
|
|
647
|
+
* Leader change:
|
|
648
|
+
* - Each partition's leader is rotated to a different broker
|
|
649
|
+
* (chosen randomly).
|
|
650
|
+
* - If \p wait_for_metadata_refresh is true the test sleeps long
|
|
651
|
+
* enough for the configured 500 ms background refresh to fire.
|
|
652
|
+
*
|
|
653
|
+
* Phase 2:
|
|
654
|
+
* - Produce a random 10-20 records per partition.
|
|
655
|
+
* - Consume them all.
|
|
656
|
+
* - Assert the consumed count equals the Phase 2 production.
|
|
657
|
+
*
|
|
658
|
+
* TODO KIP-932: once the ShareFetch response's per-partition
|
|
659
|
+
* CurrentLeader / NodeEndpoints hints are applied inline to the
|
|
660
|
+
* metadata cache (same approach as the ShareAcknowledge path), the
|
|
661
|
+
* refresh-disabled variant must see 0 Metadata RPCs after the
|
|
662
|
+
* leader change and the refresh-enabled variant must see >= 1
|
|
663
|
+
* (background refresh). Today both variants see >= 1 because the
|
|
664
|
+
* ShareFetch error path forces a metadata refresh RPC until the
|
|
665
|
+
* inline update lands.
|
|
666
|
+
* =================================================================== */
|
|
667
|
+
static void
|
|
668
|
+
do_test_leader_change_consume_recovery(rd_bool_t explicit_mode,
|
|
669
|
+
rd_bool_t use_commit_sync,
|
|
670
|
+
rd_bool_t wait_for_metadata_refresh,
|
|
671
|
+
const char *variant_name) {
|
|
672
|
+
test_ctx_t ctx;
|
|
673
|
+
rd_kafka_conf_t *conf;
|
|
674
|
+
rd_kafka_share_t *rkshare;
|
|
675
|
+
char *topic_a;
|
|
676
|
+
char *topic_b;
|
|
677
|
+
const char *topics[2];
|
|
678
|
+
const int part_a = 2;
|
|
679
|
+
const int part_b = 5;
|
|
680
|
+
const char *group = "sg-0183-recovery";
|
|
681
|
+
int phase1_total = 0;
|
|
682
|
+
int phase2_total = 0;
|
|
683
|
+
int phase1_consumed = 0;
|
|
684
|
+
int phase2_consumed = 0;
|
|
685
|
+
int leader_before_a[2];
|
|
686
|
+
int leader_before_b[5];
|
|
687
|
+
size_t metadata_window1;
|
|
688
|
+
size_t metadata_window2;
|
|
689
|
+
int i;
|
|
690
|
+
int cnt;
|
|
691
|
+
|
|
692
|
+
SUB_TEST_QUICK("%s", variant_name);
|
|
693
|
+
|
|
694
|
+
topic_a = rd_strdup(test_mk_topic_name("0183-recovery-a", 1));
|
|
695
|
+
topic_b = rd_strdup(test_mk_topic_name("0183-recovery-b", 1));
|
|
696
|
+
topics[0] = topic_a;
|
|
697
|
+
topics[1] = topic_b;
|
|
698
|
+
|
|
699
|
+
ctx = test_ctx_new(3);
|
|
700
|
+
|
|
701
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_a, part_a,
|
|
702
|
+
1) == RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
703
|
+
"create topic a");
|
|
704
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_b, part_b,
|
|
705
|
+
1) == RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
706
|
+
"create topic b");
|
|
707
|
+
|
|
708
|
+
for (i = 0; i < part_a; i++) {
|
|
709
|
+
leader_before_a[i] = (i % 3) + 1;
|
|
710
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(
|
|
711
|
+
ctx.mcluster, topic_a, i, leader_before_a[i]) ==
|
|
712
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
713
|
+
"set leader a[%d] -> %d", i, leader_before_a[i]);
|
|
714
|
+
}
|
|
715
|
+
for (i = 0; i < part_b; i++) {
|
|
716
|
+
leader_before_b[i] = (i % 3) + 1;
|
|
717
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(
|
|
718
|
+
ctx.mcluster, topic_b, i, leader_before_b[i]) ==
|
|
719
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
720
|
+
"set leader b[%d] -> %d", i, leader_before_b[i]);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
srand(42);
|
|
724
|
+
|
|
725
|
+
for (i = 0; i < part_a; i++) {
|
|
726
|
+
cnt = 10 + (rand() % 11);
|
|
727
|
+
phase1_total += mock_produce(ctx.producer, topic_a, i, cnt);
|
|
728
|
+
TEST_SAY(
|
|
729
|
+
"%s: Phase 1 produce: %s [%d] = %d records "
|
|
730
|
+
"(offsets 0..%d)\n",
|
|
731
|
+
variant_name, topic_a, i, cnt, cnt - 1);
|
|
732
|
+
}
|
|
733
|
+
for (i = 0; i < part_b; i++) {
|
|
734
|
+
cnt = 10 + (rand() % 11);
|
|
735
|
+
phase1_total += mock_produce(ctx.producer, topic_b, i, cnt);
|
|
736
|
+
TEST_SAY(
|
|
737
|
+
"%s: Phase 1 produce: %s [%d] = %d records "
|
|
738
|
+
"(offsets 0..%d)\n",
|
|
739
|
+
variant_name, topic_b, i, cnt, cnt - 1);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
test_conf_init(&conf, NULL, 0);
|
|
743
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
744
|
+
test_conf_set(conf, "group.id", group);
|
|
745
|
+
test_conf_set(conf, "share.acknowledgement.mode",
|
|
746
|
+
explicit_mode ? "explicit" : "implicit");
|
|
747
|
+
test_conf_set(conf, "topic.metadata.refresh.interval.ms",
|
|
748
|
+
wait_for_metadata_refresh ? "10000" : "-1");
|
|
749
|
+
rkshare = rd_kafka_share_consumer_new(conf, NULL, 0);
|
|
750
|
+
TEST_ASSERT(rkshare != NULL, "create share consumer");
|
|
751
|
+
subscribe_topics(rkshare, topics, 2);
|
|
752
|
+
|
|
753
|
+
phase1_consumed = consume_phase(rkshare, explicit_mode, use_commit_sync,
|
|
754
|
+
phase1_total, 0, "Phase 1");
|
|
755
|
+
TEST_ASSERT(phase1_consumed == phase1_total,
|
|
756
|
+
"Phase 1: expected %d records, got %d", phase1_total,
|
|
757
|
+
phase1_consumed);
|
|
758
|
+
|
|
759
|
+
/* Let initial offset queries (ListOffsetsRequest from the
|
|
760
|
+
* share consumer's reused fetch-state machine on partition
|
|
761
|
+
* assignment) complete before changing leaders. Without this
|
|
762
|
+
* settle window, an in-flight ListOffsets response could race
|
|
763
|
+
* with the leader change and bring in an extra metadata
|
|
764
|
+
* refresh that pollutes Window 1.
|
|
765
|
+
* TODO KIP-932: this wait can be removed once the share
|
|
766
|
+
* consumer no longer issues ListOffsetsRequests. */
|
|
767
|
+
rd_usleep(2000 * 1000, NULL);
|
|
768
|
+
|
|
769
|
+
/* Window 1 — track Metadata RPCs from the leader change
|
|
770
|
+
* through the wait sleep. Captures any background metadata
|
|
771
|
+
* refresh fired while the consumer was idle. */
|
|
772
|
+
rd_kafka_mock_start_request_tracking(ctx.mcluster);
|
|
773
|
+
|
|
774
|
+
for (i = 0; i < part_a; i++) {
|
|
775
|
+
int new_leader = leader_before_a[i];
|
|
776
|
+
while (new_leader == leader_before_a[i])
|
|
777
|
+
new_leader = 1 + (rand() % 3);
|
|
778
|
+
TEST_SAY("%s: leader change: %s [%d]: B%d -> B%d\n",
|
|
779
|
+
variant_name, topic_a, i, leader_before_a[i],
|
|
780
|
+
new_leader);
|
|
781
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(
|
|
782
|
+
ctx.mcluster, topic_a, i, new_leader) ==
|
|
783
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
784
|
+
"set leader a[%d] -> %d", i, new_leader);
|
|
785
|
+
}
|
|
786
|
+
for (i = 0; i < part_b; i++) {
|
|
787
|
+
int new_leader = leader_before_b[i];
|
|
788
|
+
while (new_leader == leader_before_b[i])
|
|
789
|
+
new_leader = 1 + (rand() % 3);
|
|
790
|
+
TEST_SAY("%s: leader change: %s [%d]: B%d -> B%d\n",
|
|
791
|
+
variant_name, topic_b, i, leader_before_b[i],
|
|
792
|
+
new_leader);
|
|
793
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(
|
|
794
|
+
ctx.mcluster, topic_b, i, new_leader) ==
|
|
795
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
796
|
+
"set leader b[%d] -> %d", i, new_leader);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (wait_for_metadata_refresh)
|
|
800
|
+
rd_usleep(11000 * 1000, NULL);
|
|
801
|
+
|
|
802
|
+
metadata_window1 = test_mock_get_matching_request_cnt(
|
|
803
|
+
ctx.mcluster, is_metadata_request, NULL);
|
|
804
|
+
TEST_SAY(
|
|
805
|
+
"%s: Window 1 (post leader change, pre Phase 2) "
|
|
806
|
+
"Metadata: %" PRIusz "\n",
|
|
807
|
+
variant_name, metadata_window1);
|
|
808
|
+
|
|
809
|
+
/* Pause tracking around Phase 2 produce so producer-driven
|
|
810
|
+
* metadata refreshes do not pollute the Window 2 count. */
|
|
811
|
+
rd_kafka_mock_stop_request_tracking(ctx.mcluster);
|
|
812
|
+
rd_kafka_mock_clear_requests(ctx.mcluster);
|
|
813
|
+
|
|
814
|
+
for (i = 0; i < part_a; i++) {
|
|
815
|
+
cnt = 10 + (rand() % 11);
|
|
816
|
+
phase2_total += mock_produce(ctx.producer, topic_a, i, cnt);
|
|
817
|
+
TEST_SAY(
|
|
818
|
+
"%s: Phase 2 produce: %s [%d] = %d records "
|
|
819
|
+
"(Phase 2 starts at offset after Phase 1)\n",
|
|
820
|
+
variant_name, topic_a, i, cnt);
|
|
821
|
+
}
|
|
822
|
+
for (i = 0; i < part_b; i++) {
|
|
823
|
+
cnt = 10 + (rand() % 11);
|
|
824
|
+
phase2_total += mock_produce(ctx.producer, topic_b, i, cnt);
|
|
825
|
+
TEST_SAY(
|
|
826
|
+
"%s: Phase 2 produce: %s [%d] = %d records "
|
|
827
|
+
"(Phase 2 starts at offset after Phase 1)\n",
|
|
828
|
+
variant_name, topic_b, i, cnt);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/* Ensure all produces and their triggered metadata refreshes
|
|
832
|
+
* have settled before measuring Phase 2 consume. */
|
|
833
|
+
rd_kafka_flush(ctx.producer, 5000);
|
|
834
|
+
|
|
835
|
+
/* Window 2 — track Metadata RPCs strictly around Phase 2
|
|
836
|
+
* consume. Excludes producer activity from Phase 2 produce. */
|
|
837
|
+
rd_kafka_mock_start_request_tracking(ctx.mcluster);
|
|
838
|
+
|
|
839
|
+
phase2_consumed = consume_phase(rkshare, explicit_mode, use_commit_sync,
|
|
840
|
+
phase2_total, 1000, "Phase 2");
|
|
841
|
+
TEST_ASSERT(phase2_consumed == phase2_total,
|
|
842
|
+
"Phase 2: expected %d records after leader change, "
|
|
843
|
+
"got %d",
|
|
844
|
+
phase2_total, phase2_consumed);
|
|
845
|
+
|
|
846
|
+
metadata_window2 = test_mock_get_matching_request_cnt(
|
|
847
|
+
ctx.mcluster, is_metadata_request, NULL);
|
|
848
|
+
TEST_SAY("%s: Window 2 (Phase 2 consume) Metadata: %" PRIusz "\n",
|
|
849
|
+
variant_name, metadata_window2);
|
|
850
|
+
|
|
851
|
+
rd_kafka_mock_stop_request_tracking(ctx.mcluster);
|
|
852
|
+
rd_kafka_mock_clear_requests(ctx.mcluster);
|
|
853
|
+
|
|
854
|
+
/* TODO KIP-932: the share consumer still runs the regular
|
|
855
|
+
* consumer's offset-query path. On leader change, the failed
|
|
856
|
+
* ListOffsets requests trigger extra metadata refreshes that
|
|
857
|
+
* inflate the wait-refresh window1 count and the no-refresh
|
|
858
|
+
* window2 count beyond the single refresh those windows are
|
|
859
|
+
* meant to capture. Once the offset-query path is removed
|
|
860
|
+
* from the share consumer, tighten the >= 1 checks below to
|
|
861
|
+
* == 1.
|
|
862
|
+
*
|
|
863
|
+
* TODO KIP-932: revisit these assertions when the ShareFetch
|
|
864
|
+
* response handler applies its per-partition CurrentLeader
|
|
865
|
+
* and NodeEndpoints hints inline to the metadata cache (same
|
|
866
|
+
* approach already taken for the ShareAcknowledge path). At
|
|
867
|
+
* that point the no-refresh variant must see 0 Metadata RPCs
|
|
868
|
+
* during Phase 2 consume — the cache is updated from the
|
|
869
|
+
* Share response, no separate Metadata RPC is needed — and
|
|
870
|
+
* the wait-refresh expectations stay as today. */
|
|
871
|
+
if (wait_for_metadata_refresh) {
|
|
872
|
+
TEST_ASSERT(metadata_window1 >= 1,
|
|
873
|
+
"%s: expected >= 1 Metadata RPC during the "
|
|
874
|
+
"wait window (background refresh), got %" PRIusz,
|
|
875
|
+
variant_name, metadata_window1);
|
|
876
|
+
TEST_ASSERT(metadata_window2 == 0,
|
|
877
|
+
"%s: expected 0 Metadata RPCs during Phase 2 "
|
|
878
|
+
"consume (cache already updated, no error path), "
|
|
879
|
+
"got %" PRIusz,
|
|
880
|
+
variant_name, metadata_window2);
|
|
881
|
+
} else {
|
|
882
|
+
TEST_ASSERT(metadata_window1 == 0,
|
|
883
|
+
"%s: expected 0 Metadata RPCs before Phase 2 "
|
|
884
|
+
"(background refresh disabled, no error yet), "
|
|
885
|
+
"got %" PRIusz,
|
|
886
|
+
variant_name, metadata_window1);
|
|
887
|
+
TEST_ASSERT(metadata_window2 >= 1,
|
|
888
|
+
"%s: expected >= 1 Metadata RPC during Phase 2 "
|
|
889
|
+
"consume (ShareFetch error path triggered "
|
|
890
|
+
"refresh), got %" PRIusz,
|
|
891
|
+
variant_name, metadata_window2);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
test_share_consumer_close(rkshare);
|
|
895
|
+
test_share_destroy(rkshare);
|
|
896
|
+
test_ctx_destroy(&ctx);
|
|
897
|
+
rd_free(topic_a);
|
|
898
|
+
rd_free(topic_b);
|
|
899
|
+
|
|
900
|
+
SUB_TEST_PASS();
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
// /* ===================================================================
|
|
905
|
+
// * Test — per-partition UNKNOWN_TOPIC_OR_PARTITION on ShareFetch is
|
|
906
|
+
// * handled silently: no OP_CONSUMER_ERR is delivered after the
|
|
907
|
+
// * topic is deleted.
|
|
908
|
+
// *
|
|
909
|
+
// * Single-broker mock cluster. Phase 1 produces and consumes records
|
|
910
|
+
// * to establish a share session. The topic is deleted. Phase 2 polls
|
|
911
|
+
// * several times and verifies no error is surfaced to the application.
|
|
912
|
+
// *
|
|
913
|
+
// * Wire-level verification: ShareFetch count is between 1 and 9
|
|
914
|
+
// * (lower bound: error path fired; upper bound: no retry storm).
|
|
915
|
+
// *
|
|
916
|
+
// * TODO KIP-932: Add a real-broker companion test that deletes a
|
|
917
|
+
// * live topic and verifies the same silent behaviour.
|
|
918
|
+
// * =================================================================== */
|
|
919
|
+
// static void test_partition_unknown_topic_silent(void) {
|
|
920
|
+
// test_ctx_t ctx;
|
|
921
|
+
// rd_kafka_conf_t *conf;
|
|
922
|
+
// rd_kafka_share_t *rkshare;
|
|
923
|
+
// rd_kafka_error_t *error;
|
|
924
|
+
// const char *topic = "0183-utp-silent";
|
|
925
|
+
// const char *group = "sg-0183-utp-silent";
|
|
926
|
+
// const int msgcnt = 5;
|
|
927
|
+
// rd_kafka_message_t *rkmessages[CONSUME_ARRAY];
|
|
928
|
+
// int phase1_consumed = 0;
|
|
929
|
+
// int error_cnt = 0;
|
|
930
|
+
// int attempts = 0;
|
|
931
|
+
// int poll_cnt = 0;
|
|
932
|
+
// size_t rcvd = 0;
|
|
933
|
+
// size_t share_fetch_cnt;
|
|
934
|
+
// size_t metadata_cnt;
|
|
935
|
+
// size_t j;
|
|
936
|
+
|
|
937
|
+
// SUB_TEST_QUICK();
|
|
938
|
+
|
|
939
|
+
// ctx = test_ctx_new(1);
|
|
940
|
+
|
|
941
|
+
// TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
942
|
+
// RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
943
|
+
// "create topic");
|
|
944
|
+
|
|
945
|
+
// /* Phase 1: produce and consume records to establish a share
|
|
946
|
+
// * session. auto.offset.reset=earliest (set by test_ctx_new) so
|
|
947
|
+
// * the share group starts from the beginning of the log. */
|
|
948
|
+
// mock_produce(ctx.producer, topic, RD_KAFKA_PARTITION_UA, msgcnt);
|
|
949
|
+
|
|
950
|
+
// /* Disable auto-create so the metadata handler does not recreate
|
|
951
|
+
// * the deleted topic, and disable the propagation wait so the
|
|
952
|
+
// * toppar is removed from the session immediately when metadata
|
|
953
|
+
// * confirms the topic is gone (instead of waiting 30 s). */
|
|
954
|
+
// test_conf_init(&conf, NULL, 0);
|
|
955
|
+
// test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
956
|
+
// test_conf_set(conf, "group.id", group);
|
|
957
|
+
// test_conf_set(conf, "share.acknowledgement.mode", "implicit");
|
|
958
|
+
// test_conf_set(conf, "allow.auto.create.topics", "false");
|
|
959
|
+
// test_conf_set(conf, "topic.metadata.propagation.max.ms", "0");
|
|
960
|
+
// rkshare = rd_kafka_share_consumer_new(conf, NULL, 0);
|
|
961
|
+
// TEST_ASSERT(rkshare != NULL, "Failed to create share consumer");
|
|
962
|
+
// subscribe_one(rkshare, topic);
|
|
963
|
+
|
|
964
|
+
// while (phase1_consumed < msgcnt && attempts++ < 30) {
|
|
965
|
+
// rcvd = 0;
|
|
966
|
+
// error = rd_kafka_share_poll(rkshare, 3000,
|
|
967
|
+
// rkmessages,
|
|
968
|
+
// &rcvd);
|
|
969
|
+
// if (error) {
|
|
970
|
+
// rd_kafka_error_destroy(error);
|
|
971
|
+
// continue;
|
|
972
|
+
// }
|
|
973
|
+
// for (j = 0; j < rcvd; j++) {
|
|
974
|
+
// if (!rkmessages[j]->err)
|
|
975
|
+
// phase1_consumed++;
|
|
976
|
+
// rd_kafka_message_destroy(rkmessages[j]);
|
|
977
|
+
// }
|
|
978
|
+
// }
|
|
979
|
+
// TEST_ASSERT(phase1_consumed == msgcnt,
|
|
980
|
+
// "Phase 1: expected %d records, got %d", msgcnt,
|
|
981
|
+
// phase1_consumed);
|
|
982
|
+
|
|
983
|
+
// /* Start request tracking before topic deletion to capture
|
|
984
|
+
// * ShareFetch requests that get UNKNOWN_TOPIC_OR_PARTITION. */
|
|
985
|
+
// rd_kafka_mock_start_request_tracking(ctx.mcluster);
|
|
986
|
+
// rd_kafka_mock_clear_requests(ctx.mcluster);
|
|
987
|
+
|
|
988
|
+
// /* Delete the topic. The consumer's next ShareFetch will receive
|
|
989
|
+
// * UNKNOWN_TOPIC_OR_PARTITION per partition, which must be handled
|
|
990
|
+
// * silently (metadata refresh, no OP_CONSUMER_ERR). */
|
|
991
|
+
// TEST_ASSERT(rd_kafka_mock_topic_delete(ctx.mcluster, topic) ==
|
|
992
|
+
// RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
993
|
+
// "delete topic");
|
|
994
|
+
|
|
995
|
+
// /* Phase 2: poll several times. OP_CONSUMER_ERR surfaces as a
|
|
996
|
+
// * non-NULL return from consume_batch; count any such return as
|
|
997
|
+
// * an error (silent handling requires zero). */
|
|
998
|
+
// while (poll_cnt++ < 5) {
|
|
999
|
+
// rcvd = 0;
|
|
1000
|
+
// error = rd_kafka_share_poll(rkshare, 1000,
|
|
1001
|
+
// rkmessages,
|
|
1002
|
+
// &rcvd);
|
|
1003
|
+
// if (error) {
|
|
1004
|
+
// error_cnt++;
|
|
1005
|
+
// rd_kafka_error_destroy(error);
|
|
1006
|
+
// continue;
|
|
1007
|
+
// }
|
|
1008
|
+
// for (j = 0; j < rcvd; j++)
|
|
1009
|
+
// rd_kafka_message_destroy(rkmessages[j]);
|
|
1010
|
+
// }
|
|
1011
|
+
// TEST_ASSERT(error_cnt == 0,
|
|
1012
|
+
// "expected 0 OP_CONSUMER_ERR after topic delete "
|
|
1013
|
+
// "(UNKNOWN_TOPIC_OR_PARTITION must be silently handled), "
|
|
1014
|
+
// "got %d",
|
|
1015
|
+
// error_cnt);
|
|
1016
|
+
|
|
1017
|
+
// /* Verify the error path fired. The background "keep fetching" loop
|
|
1018
|
+
// * may send additional empty ShareFetch requests after the partition
|
|
1019
|
+
// * leaves the session, so only a lower bound is meaningful here. */
|
|
1020
|
+
// share_fetch_cnt = test_mock_get_matching_request_cnt(
|
|
1021
|
+
// ctx.mcluster, is_share_fetch_request, NULL);
|
|
1022
|
+
// TEST_SAY("ShareFetch requests after topic delete: %" PRIusz "\n",
|
|
1023
|
+
// share_fetch_cnt);
|
|
1024
|
+
// TEST_ASSERT(share_fetch_cnt >= 1,
|
|
1025
|
+
// "expected >= 1 ShareFetch after topic delete "
|
|
1026
|
+
// "(error path must have fired), got %" PRIusz,
|
|
1027
|
+
// share_fetch_cnt);
|
|
1028
|
+
|
|
1029
|
+
// /* Verify a metadata refresh was triggered by the error. */
|
|
1030
|
+
// metadata_cnt = test_mock_get_matching_request_cnt(
|
|
1031
|
+
// ctx.mcluster, is_metadata_request, NULL);
|
|
1032
|
+
// TEST_SAY("Metadata requests after topic delete: %" PRIusz "\n",
|
|
1033
|
+
// metadata_cnt);
|
|
1034
|
+
// TEST_ASSERT(metadata_cnt >= 1,
|
|
1035
|
+
// "expected >= 1 Metadata request after topic delete "
|
|
1036
|
+
// "(metadata refresh must fire), got %" PRIusz,
|
|
1037
|
+
// metadata_cnt);
|
|
1038
|
+
|
|
1039
|
+
// rd_kafka_mock_stop_request_tracking(ctx.mcluster);
|
|
1040
|
+
|
|
1041
|
+
// test_share_consumer_close(rkshare);
|
|
1042
|
+
// test_share_destroy(rkshare);
|
|
1043
|
+
// test_ctx_destroy(&ctx);
|
|
1044
|
+
|
|
1045
|
+
// SUB_TEST_PASS();
|
|
1046
|
+
// }
|
|
1047
|
+
|
|
1048
|
+
/* ===================================================================
|
|
1049
|
+
* Regression test: records survive a leader-less partition transit.
|
|
1050
|
+
* -------------------------------------------------------------------
|
|
1051
|
+
* Trigger: a partition becomes leader-less between two leader
|
|
1052
|
+
* changes (leader -> -1 -> new_leader). The leader-less period
|
|
1053
|
+
* makes the client briefly delegate the toppar to the :0/internal
|
|
1054
|
+
* pseudo-broker. Previously, that pseudo-broker thread ran the
|
|
1055
|
+
* regular-consumer fetch_decide path on the share-consumer rktp,
|
|
1056
|
+
* promoting rktp_fetch_version above 0. Subsequent share-fetch
|
|
1057
|
+
* parsing then stamped every parsed message rko with that
|
|
1058
|
+
* promoted version, after which the version-outdated filter
|
|
1059
|
+
* dropped them silently (because rktp_version had been bumped by
|
|
1060
|
+
* the initial fetch_start barrier).
|
|
1061
|
+
*
|
|
1062
|
+
* Repro shape:
|
|
1063
|
+
* 1. leader=1; produce phase 1; consume phase 1.
|
|
1064
|
+
* 2. set leader=-1; consume again briefly so the consumer
|
|
1065
|
+
* processes the metadata change and migrates the toppar to
|
|
1066
|
+
* :0/internal. This is the step that historically promoted
|
|
1067
|
+
* rktp_fetch_version on the share-consumer rktp.
|
|
1068
|
+
* 3. wait 3 s for the bad state to settle.
|
|
1069
|
+
* 4. set leader=2 but DO NOT consume yet — let the migration
|
|
1070
|
+
* to broker 2 happen quietly.
|
|
1071
|
+
* 5. produce phase 2 on the new leader.
|
|
1072
|
+
* 6. consume phase 2 and verify every produced record reaches
|
|
1073
|
+
* the application.
|
|
1074
|
+
*
|
|
1075
|
+
* Pre-fix: phase 2 consumed < phase 2 produced (parsed records
|
|
1076
|
+
* dropped by the version filter). Post-fix: phase 2 fully drained.
|
|
1077
|
+
* =================================================================== */
|
|
1078
|
+
static void
|
|
1079
|
+
do_test_records_survive_leaderless_transit(rd_bool_t explicit_mode) {
|
|
1080
|
+
test_ctx_t ctx;
|
|
1081
|
+
rd_kafka_conf_t *conf;
|
|
1082
|
+
rd_kafka_share_t *rkshare;
|
|
1083
|
+
rd_kafka_messages_t *drain_batch = NULL;
|
|
1084
|
+
size_t drain_rcvd = 0;
|
|
1085
|
+
char *topic;
|
|
1086
|
+
const int part_cnt = 1;
|
|
1087
|
+
const char *group = "sg-0183-leaderless-transit";
|
|
1088
|
+
int phase1_total = 0;
|
|
1089
|
+
int phase2_total = 0;
|
|
1090
|
+
int phase1_consumed = 0;
|
|
1091
|
+
int phase2_consumed = 0;
|
|
1092
|
+
int i;
|
|
1093
|
+
|
|
1094
|
+
SUB_TEST_QUICK("%s", explicit_mode ? "explicit" : "implicit");
|
|
1095
|
+
|
|
1096
|
+
topic = rd_strdup(test_mk_topic_name("0183-leaderless-transit", 1));
|
|
1097
|
+
|
|
1098
|
+
ctx = test_ctx_new(3);
|
|
1099
|
+
|
|
1100
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, part_cnt,
|
|
1101
|
+
1) == RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1102
|
+
"create topic");
|
|
1103
|
+
|
|
1104
|
+
/* All partitions start on broker 1. */
|
|
1105
|
+
for (i = 0; i < part_cnt; i++)
|
|
1106
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster,
|
|
1107
|
+
topic, i, 1) ==
|
|
1108
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1109
|
+
"set initial leader [%d] -> 1", i);
|
|
1110
|
+
|
|
1111
|
+
srand(42);
|
|
1112
|
+
for (i = 0; i < part_cnt; i++)
|
|
1113
|
+
phase1_total +=
|
|
1114
|
+
mock_produce(ctx.producer, topic, i, 20 + (rand() % 11));
|
|
1115
|
+
|
|
1116
|
+
test_conf_init(&conf, NULL, 0);
|
|
1117
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
1118
|
+
test_conf_set(conf, "group.id", group);
|
|
1119
|
+
test_conf_set(conf, "share.acknowledgement.mode",
|
|
1120
|
+
explicit_mode ? "explicit" : "implicit");
|
|
1121
|
+
/* Short refresh interval so leader-change notifications
|
|
1122
|
+
* land quickly. */
|
|
1123
|
+
test_conf_set(conf, "topic.metadata.refresh.interval.ms", "2000");
|
|
1124
|
+
rkshare = rd_kafka_share_consumer_new(conf, NULL, 0);
|
|
1125
|
+
TEST_ASSERT(rkshare != NULL, "create share consumer");
|
|
1126
|
+
subscribe_one(rkshare, topic);
|
|
1127
|
+
|
|
1128
|
+
/* Phase 1: consume initial batch from broker 1. This warms
|
|
1129
|
+
* up the consumer's view of leader=1 for every partition. */
|
|
1130
|
+
phase1_consumed = consume_phase(rkshare, explicit_mode, rd_true,
|
|
1131
|
+
phase1_total, 0, "Phase 1");
|
|
1132
|
+
TEST_ASSERT(phase1_consumed == phase1_total,
|
|
1133
|
+
"Phase 1: expected %d, got %d", phase1_total,
|
|
1134
|
+
phase1_consumed);
|
|
1135
|
+
|
|
1136
|
+
/* First leader change: every partition becomes leader-less.
|
|
1137
|
+
* The next consume call drives the share-fetch loop, which
|
|
1138
|
+
* will hit broker 1, get NOT_LEADER_OR_FOLLOWER, refresh
|
|
1139
|
+
* metadata, see leader_id=-1, and delegate the toppar to the
|
|
1140
|
+
* :0/internal pseudo-broker — the exact bug-trigger. */
|
|
1141
|
+
for (i = 0; i < part_cnt; i++)
|
|
1142
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster,
|
|
1143
|
+
topic, i, -1) ==
|
|
1144
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1145
|
+
"set leader [%d] -> -1 (leader-less)", i);
|
|
1146
|
+
|
|
1147
|
+
/* Mid consume_batch: drive the internal fetch cycle so the
|
|
1148
|
+
* consumer hits broker 1 with SHAREFETCH, gets
|
|
1149
|
+
* NOT_LEADER_OR_FOLLOWER, refreshes metadata, sees
|
|
1150
|
+
* leader_id=-1, and delegates the rktp to the :0/internal
|
|
1151
|
+
* pseudo-broker. No records expected (leader-less). */
|
|
1152
|
+
TEST_ASSERT(!rd_kafka_share_poll(rkshare, 500, &drain_batch),
|
|
1153
|
+
"mid share_poll unexpected err");
|
|
1154
|
+
drain_rcvd = rd_kafka_messages_count(drain_batch);
|
|
1155
|
+
TEST_ASSERT(drain_rcvd == 0,
|
|
1156
|
+
"mid share_poll expected 0 records during the "
|
|
1157
|
+
"leader-less window, got %" PRIusz,
|
|
1158
|
+
drain_rcvd);
|
|
1159
|
+
rd_kafka_messages_destroy(drain_batch);
|
|
1160
|
+
drain_batch = NULL;
|
|
1161
|
+
|
|
1162
|
+
/* Settle: pre-fix, :0/internal's broker_internal_serve loop
|
|
1163
|
+
* runs consumer_toppars_serve here, which calls fetch_decide
|
|
1164
|
+
* on the share-consumer rktp and promotes
|
|
1165
|
+
* rktp_fetch_version. After this point, any parsed
|
|
1166
|
+
* share-fetch message gets stamped with the promoted
|
|
1167
|
+
* version and dropped by the version-outdated filter. */
|
|
1168
|
+
rd_usleep(3000 * 1000, NULL);
|
|
1169
|
+
|
|
1170
|
+
/* Second leader change: leader=2. The fast-query timer
|
|
1171
|
+
* armed by the NOT_LEADER response is still active and will
|
|
1172
|
+
* fire within ~1s (capped by retry_backoff_max_ms), find
|
|
1173
|
+
* leader=2, and clear LEADER_UNAVAIL. No consume here — let
|
|
1174
|
+
* the metadata refresh happen on its own. */
|
|
1175
|
+
for (i = 0; i < part_cnt; i++)
|
|
1176
|
+
TEST_ASSERT(rd_kafka_mock_partition_set_leader(ctx.mcluster,
|
|
1177
|
+
topic, i, 2) ==
|
|
1178
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1179
|
+
"set leader [%d] -> 2", i);
|
|
1180
|
+
|
|
1181
|
+
/* Produce Phase 2 records on the new leader. */
|
|
1182
|
+
for (i = 0; i < part_cnt; i++)
|
|
1183
|
+
phase2_total +=
|
|
1184
|
+
mock_produce(ctx.producer, topic, i, 20 + (rand() % 11));
|
|
1185
|
+
rd_kafka_flush(ctx.producer, 5000);
|
|
1186
|
+
|
|
1187
|
+
/* Phase 2: every record produced post-transit must reach the
|
|
1188
|
+
* application. Pre-fix this assertion failed because parsed
|
|
1189
|
+
* SHAREFETCH messages were stamped with the promoted
|
|
1190
|
+
* fetch_version and then dropped by the version-outdated
|
|
1191
|
+
* filter against the bumped rktp_version. */
|
|
1192
|
+
phase2_consumed = consume_phase(rkshare, explicit_mode, rd_true,
|
|
1193
|
+
phase2_total, 1500, "Phase 2");
|
|
1194
|
+
TEST_ASSERT(phase2_consumed == phase2_total,
|
|
1195
|
+
"Phase 2: expected %d records after leader-less "
|
|
1196
|
+
"transit + new leader, got %d. If pre-fix: parsed "
|
|
1197
|
+
"records were silently dropped by the "
|
|
1198
|
+
"rktp_version filter on the share-consumer path.",
|
|
1199
|
+
phase2_total, phase2_consumed);
|
|
1200
|
+
|
|
1201
|
+
test_share_consumer_close(rkshare);
|
|
1202
|
+
test_share_destroy(rkshare);
|
|
1203
|
+
test_ctx_destroy(&ctx);
|
|
1204
|
+
rd_free(topic);
|
|
1205
|
+
|
|
1206
|
+
SUB_TEST_PASS();
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
int main_0183_share_consumer_leader_change_mock(int argc, char **argv) {
|
|
1211
|
+
TEST_SKIP_MOCK_CLUSTER(0);
|
|
1212
|
+
test_timeout_set(120);
|
|
1213
|
+
|
|
1214
|
+
test_shareack_leader_change_reduces_rpcs();
|
|
1215
|
+
test_partition_not_leader_or_follower_silent();
|
|
1216
|
+
/* test_partition_unknown_topic_silent(); */
|
|
1217
|
+
|
|
1218
|
+
do_test_records_survive_leaderless_transit(rd_false);
|
|
1219
|
+
do_test_records_survive_leaderless_transit(rd_true);
|
|
1220
|
+
|
|
1221
|
+
do_test_leader_change_consume_recovery(rd_false, rd_false, rd_false,
|
|
1222
|
+
"implicit-no-refresh");
|
|
1223
|
+
do_test_leader_change_consume_recovery(rd_false, rd_false, rd_true,
|
|
1224
|
+
"implicit-wait-refresh");
|
|
1225
|
+
do_test_leader_change_consume_recovery(rd_true, rd_false, rd_false,
|
|
1226
|
+
"explicit-async-no-refresh");
|
|
1227
|
+
do_test_leader_change_consume_recovery(rd_true, rd_false, rd_true,
|
|
1228
|
+
"explicit-async-wait-refresh");
|
|
1229
|
+
do_test_leader_change_consume_recovery(rd_true, rd_true, rd_false,
|
|
1230
|
+
"explicit-sync-no-refresh");
|
|
1231
|
+
do_test_leader_change_consume_recovery(rd_true, rd_true, rd_true,
|
|
1232
|
+
"explicit-sync-wait-refresh");
|
|
1233
|
+
return 0;
|
|
1234
|
+
}
|