Skip to content

fix(core): draining PC stops polling - 10kHz busy-spin + zombie partition hold (#857-family silent stall) - #80

Merged
astubbs merged 41 commits into
masterfrom
fix/flaky-partitionstate-committedoffset-it
Aug 4, 2026
Merged

astubbs merged 41 commits into
masterfrom
fix/flaky-partitionstate-committedoffset-it

Conversation

@astubbs

@astubbs astubbs commented Jul 29, 2026 •

Copy link
Copy Markdown
Owner

One flaky CI check (PartitionStateCommittedOffsetIT.committedOffsetRemoved[latest]) turned out to conceal two independent bugs - one real production defect in the close path, one long-lived race in the test harness. This PR fixes both, with each fix proven RED→GREEN against its captured defect, and lands the diagnostics that made the hunt possible so the next investigation costs hours instead of days.

Bug 1 (product): draining consumer busy-spins and zombie-holds its partitions

ConsumerManager.shutdownRequested was a private shadow of BrokerPollSystem.runState, set at the wrong lifecycle phase: drain() raised it on entry to DRAINING, so poll()'s guard short-circuited and consumer.poll() was never invoked again during the drain window. Measured consequences:

  • the poll loop busy-spun at ~10k iterations/s (a full core per closing instance) - the paused 2s long poll that handlePoll()'s own comment designates as the loop's sleep never ran;
  • rebalance participation lives inside poll(), so the draining consumer became a rebalance-unresponsive zombie: background heartbeats kept it a live group member holding its full partition assignment (up to max.poll.interval.ms) while consuming nothing - freezing same-group siblings. Relates to upstream Paused consumption across multiple consumers confluentinc/parallel-consumer#857's "paused consumption after rebalance".

Fix: collapse the duplicated lifecycle state rather than re-time it - the flag and signalStop() are deleted; ConsumerManager derives "close in progress" from the poll system's runState (now volatile) via an injected signal. One source of truth; the desync class is structurally impossible. Drain semantics preserved: a draining member correctly keeps its partitions to finish in-flight work and commit (that is what bounds duplicates) - what it must also do, and now does, is stay rebalance-responsive.

Guards: BrokerPollSystemDrainTest (unit; committed first as a characterisation of the defect, then flipped RED→GREEN by the fix) and DrainingMemberRebalanceIT (integration: PC-B joining mid-drain makes progress while PC-A drains; clean close; correctness ledger - no records lost, duplicates exactly the parked in-flight tail, proving the handover honoured A's commits).

Bug 2 (test harness): the auto.offset.reset=latest nudge race

The flake itself was not a product stall: a consumer with LATEST reset and no committed offset resolves its start position when the reset executes. runPcUntilOffset produced its single nudge record before the await - under contention, bootstrap takes 1-3s, the reset resolves after the nudge, and the consumer is positioned past every record that will ever exist: the await is unwinnable at any timeout. Only the [latest] param can lose this race - and every observed failure ever was [latest]. Captured via the Kafka client's own (normally silenced) internals: Resetting offset ... to position FetchPosition{offset=201} on a topic holding exactly 201 records.

Fix, DRY'd per the ensureTopic drift lesson: shared BrokerIntegrationTest#awaitWithTopicNudge - produces a nudge inside each await attempt (the pattern runPcCheckStartIs already used inline) and self-diagnoses on timeout (topic end vs group committed vs nudges sent). Both helpers delegate to it; no timeout enlarged, no assertion weakened. LatestResetTailNudgeIT bottles the race deterministically (RED with the old pattern in ~23s every run; GREEN with the primitive).

Validation

  • 20 consecutive fork16 stress runs (16 broker-forks on 12 cores - the proven reproducer config): committedOffsetRemoved 0/20 (historical failure rate ~33% → P(luck) ≈ 0.03%); 15/20 fully clean; zero stall-class failures. Residuals catalogued in docs/inflight.md as the load-tightness flake family (fast-fail assertion flakes, pass isolated).
  • Full unit suite green at every commit; highcpu self-hosted runner green on Unit + Performance.
  • Fix independence verified: the harness race reproduced with the drain fix (and other in-flight stall fixes) applied - two separate bugs, two separate fixes.

Also included

  • Committed diagnostics (all DEBUG/off-by-default, behaviour-preserving): ShardManager under-served detector, WorkManager throttle-decision log, per-PC myId log attribution, correlation markers on tail-nudge awaits, a standing (commented) kafka-client bootstrap DEBUG harness, and SubscriptionState at INFO (offset-reset lines are rare and decisive).
  • Research record: docs/solutions/test-flakiness/pc-silent-stall-under-contention-2026-07-29.md (the investigation + drain design review) and latest-reset-nudge-race-committedoffsetremoved-2026-07-30.md (the solved mechanism + diagnosability lessons). docs/inflight.md updated throughout.
  • Changelog entry for the operator-visible drain fix; plan document under docs/plans/.
  • Both fix(core): draining PC stops polling - 10kHz busy-spin + zombie partition hold (#857-family silent stall) #80-owned quarantined tests re-enabled (ChaosChurnStormIT.churnStormMeetsSlosAndBalancesLedger, PartitionStateCommittedOffsetIT.committedOffsetRemoved): their fixes are this PR, so the @Quarantined annotations and docs/QUARANTINED_TESTS.md entries are deleted here - the registry is now empty. Triggered by the Quarantine Lane's unexpected-pass detection on this branch.
  • Repo hygiene (later commits on this branch): removed a stale CI "concede" mechanism that had ridden in via an old branch merge - it was previously rejected from PR ci: self-hosted high-CPU fast-feedback workflow + PR-scoped advisory PIT #75 by review as a gate-spoof (a PR could add a workflow named highcpu with a trivially-passing job and make the required gate skip real tests), so maven.yml is now byte-identical to master and bin/ci-concede-check.sh is deleted; collapsed three doubled copyright headers (a maven-license-plugin artifact) in BrokerIntegrationTest, KafkaClientUtils, RetriesTest; and pruned satisfied docs/inflight.md entries.

Checklist

  • Changelog entry added (CHANGELOG.adoc, under == Unreleased) - drain-zombie fix entry
  • Docs updated - two docs/solutions/ write-ups, docs/inflight.md, docs/QUARANTINED_TESTS.md, plan doc
  • Tests added/updated - BrokerPollSystemDrainTest (RED→GREEN characterisation), DrainingMemberRebalanceIT, LatestResetTailNudgeIT; two quarantined tests re-enabled
  • Title & body reflect the final content of this PR
  • Self-hosted runner / security implications considered - this PR makes no CI-gate changes: maven.yml is byte-identical to master. A stale "concede" mechanism that would have let a self-hosted result satisfy the required GitHub-hosted gate (rejected from PR ci: self-hosted high-CPU fast-feedback workflow + PR-scoped advisory PIT #75 as a gate-spoof) had ridden in via an old merge and has been removed here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18

astubbs and others added 18 commits July 29, 2026 16:55
…same-repo only)

Optional, non-gating fast feedback that runs unit, integration and performance as parallel
matrix jobs on a self-hosted many-core runner (label `highcpu`), guarded to same-repo PRs so
fork code never executes on it. The GitHub-hosted gate in maven.yml stays the required check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…rkflow

# Conflicts:
#	.github/actionlint.yaml
…-only

The high-CPU self-hosted matrix now runs unit + integration + performance + mutation as parallel
jobs (a strict superset of the mac runner, which is offline indefinitely). The mac workflow is
switched to workflow_dispatch-only so it stops queuing dead jobs on every PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
failingHttpCall drove an HTTP call at a dotless bogus hostname ("xxxxxxxxx") and asserted the failure
was a DNS *resolution* error ("failed resolve"). That only holds where the name fails to resolve - on any
network with a local resolver + search domain (e.g. a Pi-hole LAN) the name resolves and the failure mode
becomes "connection refused", so the test fails there while passing on GitHub's public DNS.

Point the bad request at a closed local port (127.0.0.1:1) instead: an immediate, deterministic
"connection refused" on every environment, no DNS lookup at all (and faster than one). Keep the real
failed==true check; assert the deterministic "connection refused" message. Found bringing up the
self-hosted high-CPU runner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…with failingHttpCall)

The failingHttpCall fix (127.0.0.1:1 -> connection refused) also flipped this sibling test through the shared getBadRequest() helper, so its assertion is updated to match. Caught by ce-review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
Load was ~18/32 with 34GB free - the box is I/O-bound (cold cache), not CPU-bound - so use all the cores.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…ateCommittedOffsetIT

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…epo guard (ce-review P2)

The if: guard lives in the PR-head file, so the real RCE backstop is the repo Actions setting "require approval for all outside collaborators". Documented in the workflow header + referenced SELF_HOSTED_RUNNER.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
Unit forkCount 1C->2C, Integration 8->16 (probe the oversubscription ceiling). Mutation PIT threads 2->16 (CPU-bound, stays in the matrix). Performance split into its own job that needs the matrix, so the throughput benchmark measures on a quiet box (solo 1m54 vs 7m18 when it shares the box).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…formance

Doubling was flat (unit 2C=1C) to worse (integration 16 slower than 8), so back to the knee. Performance returns to the concurrent matrix - it is a correctness gate here; noisy timing is fine and isolation wrecked total wall-clock (it queued behind a 17-min mutation). Mutation keeps threads=16. Accurate benchmarking -> separate on-demand run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
Unit/Integration now also enable JUnit method-parallelism (-Dparallel-tests=true) on top of forking, forks reduced so forks x threads ~= cores - tests whether thread-parallelism is still flaky after recent fixes (revert to fork-only if red). ci-mutation-test.sh: on a PR (GITHUB_BASE_REF) mutate ONLY changed core classes, skip if none - the full internal.* sweep has never completed. Full sweep still runs for push/nightly (no base ref).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…eads finding

fork×threads (parallel-tests=true) was safe (threading no longer races - unit green; integration red was the known flaky PartitionStateCommittedOffsetIT) but no faster than fork-only, so back to 1C/8. PIT: grep no-match under set -euo pipefail made the changed-class skip exit non-zero (0m19 red); wrap grep with || true so it exits 0. Recorded the thread-parallelism-vs-forking finding in inflight next to the shelved Step-2 question.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…bserve a green board

TEMPORARY - not a fix. Disables the known-flaky PartitionStateCommittedOffsetIT.committedOffsetRemoved (awaitility timeout, in inflight, fails on GitHub-hosted too) purely to see a fully-green highcpu run. Revert and harden the test properly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
Now that ci-mutation-test.sh scopes PIT to changed classes on PRs (GITHUB_BASE_REF), it is fast enough for the 2-core hosted runner - so mutation runs on GitHub-hosted as well, not just the self-hosted box. Non-gating (continue-on-error). fetch-depth: 0 so the changed-class diff resolves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…already passed

Each GitHub-hosted test job, before running its slow 2-core suite, polls whether the self-hosted highcpu equivalent for the same commit already PASSED (ci-concede-check.sh). If so it skips and goes green; the hosted job stays the required gate but finishes faster when grumpy wins. Never depends on the self-hosted runner: offline/queued/slow/failed -> run the tests normally. Bounded wait, continue-on-error so a check bug can never fail the gate. Caveat documented: conceding trusts the self-hosted env (env-specific failures could be missed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
… the green-board experiment)

Reverts the temporary experiment disable. The test is still the known flaky awaitility timeout (tracked in inflight) - harden it (adaptive await / underlying timing) rather than leave it disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
…fluentinc#857 hunt)

DEBUG-only, behaviour-preserving observability for the silent-stall family:

- ShardManager.getWorkIfAvailable: under-served detector - when less work is
  returned than requested while work is still tracked, log the breakdown
  [awaitingSelection, inFlight, retryQueue.size, readyToRetry] so 'asked for
  work / got none / but it's in the queues (or missing)' can be told apart
  from normal in-flight back-pressure.
- WorkManager.isSufficientlyLoaded: log the throttle-decision inputs
  (awaitingSelection + outForProcessing vs target*loadingFactor). This gates
  broker-poller pause/resume, so numberRecordsOutForProcessing counter drift
  (confluentinc#857) shows up here as 'loaded' with no real work.
- KafkaClientUtils.buildPc: unique myId per test PC so pc-control-PCn /
  pc-broker-poll-PCn thread names and the pcId MDC make concurrent instances
  attributable in logs (the myId hook was never wired; all instances collided).
  Safe: RebalanceEoSDeadlockTest matches thread names with .contains().
- logback-test.xml: labelled (commented) logger set for the stall hunt.

These diagnostics fired during the forkCount=16 reproductions documented in
docs/solutions/test-flakiness/pc-silent-stall-under-contention-2026-07-29.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
…ain-path spin + zombie partition hold (confluentinc#857 family)

Research report assessing PR #75's red Integration check: not the grumpy
runner, and NOT a benign flaky timeout - a PC under contention polls zero
records even with a 120s bound (a stall, not slowness). No test was masked.

Root-caused a drain-path defect: drain() fires ConsumerManager.signalStop()
whose shutdownRequested flag short-circuits poll() so consumer.poll() is
never called - defeating the intended 'paused 2s long poll = drain-loop
sleep' (handlePoll() comment). Measured 92,880 poll-loop iterations in 9.0s
(~10kHz busy-spin). With consumer.poll() never invoked, a draining PC cannot
join rebalances while background heartbeats keep it a live member - a zombie
holding its partitions (up to max.poll.interval.ms) while burning a core.
Maps directly onto confluentinc#857's 'paused consumption after rebalance' (partition-
hold hypothesis credit: Antony). Report includes a drain fail-safe design
review (honour the 2s poll; hard deadline + explicit LeaveGroup; eager
leave trade-offs; spin watchdog) and the reproduction recipe.

inflight.md entry reframed accordingly: DO NOT MASK, route to confluentinc#857 (PR #29).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions

github-actions Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

✅ Duplicate Code Report

Two engines run in parallel for cross-validation. Each has its own thresholds tuned to its baseline - the real safety net is the per-engine "max increase vs base" check.

✅ PMD CPD

PR Base Change
Clones 29 29 ➖ 0
Duplicated lines 874 874 ➖ 0
Duplication 2.58% 2.58% ➖ 0
Rule Limit Status
Max duplication 5% ✅ Pass (2.58%)
Max increase vs base +0.1% ✅ Pass (+0.00%)

No new clones introduced by this PR.

✅ jscpd (language-agnostic)

PR Base Change
Clones 77 76 🫤 +1
Duplicated lines 1111 1100 :face_with_monocle: +11
Duplication 3.31% 3.34% 🙂 -0.03%
Rule Limit Status
Max duplication 5% ✅ Pass (3.31%)
Max increase vs base +0.1% ✅ Pass (-0.03%)
⚠️ 1 new clones introduced
  • 12 lines: parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java:1 <-> parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java:1

Powered by astubbs/duplicate-code-cross-check

@github-actions

github-actions Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

📌 Duplicate code detection tool report

The tool analyzed your source code and found the following degree of similarity between the files:

🆕 New file similarities introduced

File A File B Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/DrainingMemberRebalanceIT.java parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/BrokerPollSystemDrainTest.java 31.5

🔺 Increased similarities

File A File B Base (%) PR (%) Change
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java 69.6 71.2 +1.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java 32.9 33.5 +0.6
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java 37.7 38.3 +0.6
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 56.4 56.9 +0.5
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 55.0 55.4 +0.4
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 39.1 39.4 +0.4
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java 35.0 35.4 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 30.4 30.7 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 60.7 61.0 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java 32.8 33.1 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 32.4 32.7 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 31.4 31.6 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 54.5 54.7 +0.3
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 50.4 50.6 +0.2
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java 30.9 31.1 +0.2
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 31.1 31.4 +0.2
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 52.6 52.8 +0.2
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 36.5 36.8 +0.2
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 36.8 37.0 +0.2
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 32.2 32.4 +0.2

...and 41 more

Full similarity report
parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java

📄 parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java 35.32
parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java 33.26
parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java

📄 parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java 39.5
parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java 35.32
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 54.36 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 40.38
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 37.0
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java 36.97
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 35.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 35.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 35.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 34.15
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 30.07
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 60.96 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 54.74 ⚠️
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 40.4
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 37.01
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 32.68
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 31.47
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 60.96 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 50.65 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 36.76
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 32.44
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 31.63
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 30.22
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 36.97
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 33.11
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 54.36 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 53.28 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 44.98
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 35.05
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 33.75
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 31.14
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 31.14
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 30.74
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 30.15
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java 32.32
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java 30.0
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 54.74 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 50.65 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 45.53
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 33.92
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java 33.05
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java 31.14
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 45.53
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 37.01
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 36.76
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 32.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java 35.38
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 32.36
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 33.92
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java 33.09
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 32.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java 32.36
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 31.63
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java 35.38
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 33.09
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java 33.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 33.05
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java 33.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ExternalEngine.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ExternalEngine.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java 39.59
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 60.58 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 53.28 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 51.0 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 48.89
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 40.38
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 39.43
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 37.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 34.02
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 34.02
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java 33.11
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 39.43
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 31.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 30.74
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/PCModule.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/PCModule.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/PCModuleTestEnv.java 32.97
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java 32.32
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ProducerManagerTest.java 30.64
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 51.75 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 37.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 37.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 37.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 35.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 35.05
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 32.92
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 60.58 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 51.75 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 48.47
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 47.37
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 47.37
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 46.84
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 44.98
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 37.0
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 31.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 48.89
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 46.84
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 45.47
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 38.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 38.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 30.15
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 30.07
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 51.0 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 48.47
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 45.47
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 34.15
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 33.75
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 32.92
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 31.8
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 31.8
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 63.65 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 47.37
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 38.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 37.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 35.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 34.02
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 31.8
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 31.14
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 63.65 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 47.37
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 38.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 37.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 35.39
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 34.02
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 31.8
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 31.14
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java 30.45
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java 30.0
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/WorkManager.java 39.62
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java 30.45
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ProcessingShard.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ProcessingShard.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ShardManager.java 36.71
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ShardManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ShardManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ProcessingShard.java 36.71
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/WorkManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/WorkManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java 39.62
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/AmbientProbeExtension.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/AmbientProbeExtension.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AmbientProbeExtensionTest.java 30.14
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/DrainingMemberRebalanceIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/DrainingMemberRebalanceIT.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/BrokerPollSystemDrainTest.java 31.54
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/KafkaSanityTests.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/KafkaSanityTests.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/csid/utils/LoopingResumingIteratorTest.java 34.02
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 55.42 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 46.93
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java 38.68
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 44.13
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 41.11
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java 38.68
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceEoSDeadlockTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceEoSDeadlockTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceTest.java 36.56
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceEoSDeadlockTest.java 36.56
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 60.72 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java 46.93
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java 41.11
parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java 30.02
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 60.72 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java 55.42 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java 44.13
parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java 39.24
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java 48.87
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 35.69
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java 48.87
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java 38.27
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 30.35
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkCooperativeIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkCooperativeIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 49.38
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkCooperativeIT.java 49.38
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java 35.69
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java 30.35
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java 38.27
parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java

📄 parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java 39.5
parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java 33.26
parallel-consumer-core/src/test/java/io/confluent/csid/utils/LoopingResumingIteratorTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/csid/utils/LoopingResumingIteratorTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/KafkaSanityTests.java 34.02
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AbstractParallelEoSStreamProcessorTestBase.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AbstractParallelEoSStreamProcessorTestBase.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java 30.01
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AmbientProbeExtensionTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AmbientProbeExtensionTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/AmbientProbeExtension.java 30.14
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/BatchTestBase.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/BatchTestBase.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 30.61
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java 45.22
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java 43.72
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CommitRejectionTestBase.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CommitRejectionTestBase.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 32.44
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 32.42
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java 52.04 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java 50.73 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java 44.86
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/BatchTestBase.java 30.61
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java 70.36 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 56.9 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 49.45
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CommitRejectionTestBase.java 32.42
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 70.36 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 55.42 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 52.82 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java 52.82 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 49.45
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 46.82
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 56.9 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java 55.42 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 46.82
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CommitRejectionTestBase.java 32.44
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSSStreamProcessorRebalancedTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSSStreamProcessorRebalancedTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java 34.69
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSSStreamProcessorRebalancedTest.java 34.69
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AbstractParallelEoSStreamProcessorTestBase.java 30.01
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java 45.22
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java 33.08
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java 43.72
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java 33.08
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java 90.34 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java 89.68 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java 89.68 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/BrokerPollSystemDrainTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/BrokerPollSystemDrainTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/DrainingMemberRebalanceIT.java 31.54
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ExceptionConstructorsTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ExceptionConstructorsTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/InternalRuntimeExceptionTest.java 30.08
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/InternalRuntimeExceptionTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/InternalRuntimeExceptionTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ExceptionConstructorsTest.java 30.08
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/PCModuleTestEnv.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/PCModuleTestEnv.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/PCModule.java 32.97
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ProducerManagerTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ProducerManagerTest.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java 30.64
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 31.14
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureUnitTest.java 40.08
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureUnitTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureUnitTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureTest.java 40.08
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/CommitHistorySubject.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/CommitHistorySubject.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/LongPollingMockConsumerSubject.java 36.66
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/LongPollingMockConsumerSubject.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/LongPollingMockConsumerSubject.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/CommitHistorySubject.java 36.66
parallel-consumer-mutiny/src/main/java/io/confluent/parallelconsumer/mutiny/MutinyProcessor.java

📄 parallel-consumer-mutiny/src/main/java/io/confluent/parallelconsumer/mutiny/MutinyProcessor.java

File Similarity (%)
parallel-consumer-reactor/src/main/java/io/confluent/parallelconsumer/reactor/ReactorProcessor.java 52.23 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java 78.97 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 50.73 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java 49.07
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java 71.2 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorTest.java 32.74
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyUnitTestBase.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyUnitTestBase.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorUnitTestBase.java 32.16
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java 91.13 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java 90.46 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java 89.68 ⚠️
parallel-consumer-reactor/src/main/java/io/confluent/parallelconsumer/reactor/ReactorProcessor.java

📄 parallel-consumer-reactor/src/main/java/io/confluent/parallelconsumer/reactor/ReactorProcessor.java

File Similarity (%)
parallel-consumer-mutiny/src/main/java/io/confluent/parallelconsumer/mutiny/MutinyProcessor.java 52.23 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java 78.97 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 52.04 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java 50.33 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java 71.2 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyTest.java 32.74
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorUnitTestBase.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorUnitTestBase.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyUnitTestBase.java 32.16
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java 91.13 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java 90.46 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java 89.68 ⚠️
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java 41.54
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 40.4
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 39.88
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java 35.43
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 32.44
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 39.88
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java 39.29
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 32.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 31.47
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 30.22
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java 41.75
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 41.54
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ExternalEngine.java 39.59
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java 41.75
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 39.29
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 35.43
parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java

📄 parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 39.24
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 30.02
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java

📄 parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java 91.13 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java 91.13 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java 90.34 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java

📄 parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java 50.33 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java 49.07
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 44.86

@github-actions

Copy link
Copy Markdown

✅ SpotBugs Report

No bugs found (new bugs only — baseline from base branch excluded).

@codecov-commenter

codecov-commenter commented Jul 29, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 27.77778% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.36%. Comparing base (755c248) to head (10047d8).
⚠️ Report is 8 commits behind head on ci/grumpy-runner-workflow.

Files with missing lines Patch % Lines
...confluent/parallelconsumer/state/ShardManager.java 0.00% 8 Missing and 1 partial ⚠️
.../confluent/parallelconsumer/state/WorkManager.java 55.55% 3 Missing and 1 partial ⚠️

❗ There is a different number of reports uploaded between BASE (755c248) and HEAD (10047d8). Click for more details.

HEAD has 2 uploads less than BASE
Flag BASE (755c248) HEAD (10047d8)
performance 1 0
unit 1 0
Additional details and impacted files
@@                       Coverage Diff                       @@
##             ci/grumpy-runner-workflow      #80      +/-   ##
===============================================================
- Coverage                        78.01%   68.36%   -9.65%     
+ Complexity                        1072      851     -221     
===============================================================
  Files                               81       76       -5     
  Lines                             4039     3806     -233     
  Branches                           372      370       -2     
===============================================================
- Hits                              3151     2602     -549     
- Misses                             712     1007     +295     
- Partials                           176      197      +21     
Flag Coverage Δ
integration 68.36% <27.77%> (-0.23%) ⬇️
performance ?
unit ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

astubbs and others added 3 commits July 29, 2026 23:36
…anch experiment

Checked both in-flight stall PRs against the zombie-drain root cause:

- PR #29 (confluentinc#857): drain() still calls signalStop() first and the
  while(!shutdownRequested) short-circuit is intact - the ~10kHz spin and
  zombie partition hold survive unchanged. It fixes a SIBLING mechanism
  (onPartitionsAssigned resets pausedForThrottling - RUNNING-state
  throttle-pause) and even adds trace logging inside the loop that spins.
  Its 10-20% residual chaos-stall rate is a testable prediction: the chaos
  monkey's stop/start cycling is a drain-window factory.
- PR #31 (confluentinc#909): main-code diff is only ProcessingShard.java - no overlap.

All three efforts chase the same 'alive but not progressing' symptom via
different, non-conflicting mechanisms, so the report now recommends an
uber-branch experiment: merge #29 + #31 + the minimal drain fix (defer
signalStop() to CLOSING), then measure #29's chaos run and this report's
forkCount=16 recipe - if the residual stall rate drops to ~0, the
zombie-drainer mechanism explains the residue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
The check name is "<workflow> / <job>", and both halves carried "High-CPU"
plus verbose filler ("Build & Test - ...", "self-hosted, optional"), pushing
past the PR merge-box truncation width.

- workflow name: "PR High-CPU Fast Feedback" -> "highcpu"
- job name: "Build & Test - <suite> (high-CPU self-hosted, optional)"
           -> "<suite> (optional)"  (keeps the non-gating signal)

Result: "highcpu / Unit (optional)", "highcpu / Integration (optional)", etc.
- longest ~35 chars, well under the cutoff.

Kept the concede matcher in sync (it resolves the highcpu run/jobs by name):
bin/ci-concede-check.sh WORKFLOW default -> "highcpu", JOB_PREFIX -> "${SUITE}"
(the job is now named "<suite> (optional)", so a suite-name prefix still
uniquely matches). Added a keep-in-sync comment on the job. Updated the
SELF_HOSTED_RUNNER.md reference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ytagqk6daL4uTtbebQNNv
… never invoked while draining

BrokerPollSystemDrainTest parks in-flight work on a latch, starts
close(DRAIN) on another thread, and counts consumer.poll() invocations on
the consumer spy across three long-poll periods of the drain window.

CHARACTERISATION (asserts the CURRENT broken behaviour): the count is ZERO.
drain() fires ConsumerManager.signalStop() before entering DRAINING, and
poll()'s while(!shutdownRequested) guard then short-circuits without ever
calling consumer.poll() - so the loop's intended sleep (the paused 2s long
poll, per handlePoll()'s own comment) never happens (~10kHz spin measured),
and the consumer cannot participate in rebalances while background
heartbeats keep it a live member zombie-holding its partitions.

The follow-up commit collapses the duplicated lifecycle flag and flips this
test to assert the desired behaviour (poll continues at long-poll cadence).

Also adds the implementation plan:
docs/plans/2026-07-29-002-fix-drain-zombie-spin-and-uber-experiment-plan.md

Full unit suite green (one unrelated pre-existing ReactorPCTest flake,
passed on rerun).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
@astubbs astubbs changed the title docs+diag: grumpy Integration red is a real silent stall (drain-path spin + zombie partition hold, #857 family) fix(core): draining PC stops polling - 10kHz busy-spin + zombie partition hold (#857-family silent stall) Jul 29, 2026
astubbs and others added 3 commits July 30, 2026 00:16
…down flag into poll-system lifecycle

ConsumerManager.shutdownRequested was a private shadow of
BrokerPollSystem.runState, settable out of phase - and it was: drain() set
it on entry to DRAINING, so poll()'s while(!shutdownRequested) guard
short-circuited and consumer.poll() was never invoked again during the
drain window. Measured consequences: the poll loop busy-spun at ~10k
iterations/s (the paused 2s long poll that handlePoll()'s own comment
designates as the loop's sleep never ran), and the consumer became a
rebalance-unresponsive zombie group member - background heartbeats kept it
alive holding its full partition assignment (up to max.poll.interval.ms)
while consuming nothing, starving same-group siblings. Maps onto upstream
issue confluentinc#857's 'paused consumption after rebalance'.

The fix collapses the duplicated state rather than re-timing it:

- ConsumerManager: shutdownRequested + signalStop() deleted. The poll
  guard, SASL retryBackOff abort, and commitSync retry abort now consult an
  injected closeInProgressSignal (defaults to 'never' for standalone use).
  close() no longer raises a flag - by then the poll system is already
  CLOSING/CLOSED so the signal reports true to in-flight retry loops.
  Side-benefit: commits/retries during DRAIN are no longer wrongly aborted.
- BrokerPollSystem: wires closeInProgressSignal = (runState == CLOSING or
  CLOSED) in its constructor - runState is the single source of truth, so
  the desync class is structurally impossible. Both signalStop() call sites
  removed; a draining consumer keeps polling (paused, long-poll cadence)
  and can promptly ack revokes/rejoin. runState is now volatile (it was
  already read cross-thread; the signal adds committer-thread readers).

Test flipped RED->GREEN: BrokerPollSystemDrainTest, committed first as a
characterisation of the defect (0 polls during drain), now asserts the
desired property (>=1 poll per window at long-poll cadence, bounded above
- no spin) and that close still completes cleanly.

Full unit suite green (one unrelated pre-existing ReactorPCTest flake,
passed on rerun, identical on the pre-fix baseline run).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
The build's README generator embeds CHANGELOG.adoc; this syncs the generated
README.adoc with the changelog entry added in the drain-fix commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
…ring handover during drain

Integration-level guard for the drain fix, calibrated against the planted
defect on the experiment arms:

- GREEN on this branch (fix present): B, joining mid-drain, consumed 200
  records while A was still draining; A closed promptly on release; ledger:
  A=1100, B=200, duplicates=100 - exactly the parked in-flight tail
  (maxConcurrency), NOT a wholesale reprocess: the handover honoured A's
  commits.
- RED on the no-fix arm (defect present): the group stayed frozen while A
  drained (B starved) until the worker-pool force-interrupt bailed A out -
  the mid-drain liveness window could never be established.

Encodes the drain semantics explicitly (see report design review): a
draining member CORRECTLY keeps its partitions to finish + commit (that is
what bounds duplicates); what it must also do is stay rebalance-responsive
so a mid-drain join never freezes the group.

Report updated in the same spirit: design-review option 3 (eager LeaveGroup
at drain start) REJECTED - it would guarantee duplicate reprocessing of
in-flight work; explicit LeaveGroup belongs only in the deadline-expiry
fail-safe (option 2). PR #29/#31 non-fix verification notes sharpened.

Also the W1 skateboard scenario of the Chaos Pain Suite design (separate
branch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbtaCN1Re14pJ99VFW4R18
astubbs added a commit that referenced this pull request Aug 5, 2026
…nst #80

This branch was cut before the rebrand and before the rest of the confluentinc#857 family
landed, so it still targeted `master-confluent` and sat 61 commits behind.
Three conflicts, none of them mechanical:

- `ConsumerManager` - the branch added `claimConsumerOwnership()` and
  `signalStop()` side by side. #80 deleted the whole `shutdownRequested` flag,
  collapsing it into the poll system's `runState` (see `BrokerPollSystemDrainTest`),
  and rewrote the drain path that was `signalStop()`'s only caller. Kept the
  ownership claim, dropped `signalStop()` as dead - reinstating it would restore
  the second source of truth #80 removed.

- `ManagedPCInstance` - both sides added it. Master's copy is a strict superset
  (MDC cleanup on pooled threads, `extraConsumerProps`, try/finally), so master's
  wins outright.

- `pom.xml` - took master's test dependency versions and the byte-buddy pin, and
  dropped the branch's duplicate `archunit-junit5` declaration; master already
  declares it at 1.4.2 for all modules.

Also brought the branch's headers under the fork's provenance policy, which
postdates it: fork-original files (`ThreadConfinedConsumer`, `ArchitectureTest`,
`ShardManagerStaleContainerTest`, `ManagedPCInstanceLifecycleTest`) now carry the
fork header rather than a Confluent one, and the five modified upstream-derived
files carry the modifications line. `MultiInstanceRebalanceTest` also had its
Confluent year bumped to 2026 on the branch; restored to 2020-2022 per policy.

Compiles clean across main, test and test-integration sources.
astubbs added a commit that referenced this pull request Aug 6, 2026
…ach the gate about anchors

Two things the reference sweep surfaced in Java sources.

The quarantine script tests built their fixture registries with
"Owner: PR #999", "PR #80" and "PR #123". The last two are real fork PRs,
so the fixtures read as genuine references to anyone grepping, and #999
is close enough to the live range to be mistaken for one. They are now
#999999 and #999998 - unmistakably fake, and above the threshold where a
bare number is ambiguous. Two distinct values, because the owner-mismatch
tests compare a @Quarantined value against a registry value and need them
to differ. 27 tests pass.

The gate also flagged references that were already qualified by an html
anchor - TransactionMarkersTest has
<a href=".../issues/329">Github issue #329</a>, where the href names the
repo and the number in the link text is unambiguous to any reader.
stripQualified removed bare URLs but not the anchor element, so the
visible "#329" looked bare. It now strips the whole element, with a test
confirming a bare number elsewhere on the same line is still caught.

Together these take the tree-wide backlog from 390 to 374, and the Java
share from 53 to 36.

The follow-up note now carries the finished classification of all 36
Java references - file, line, and which repo each means, resolved
against both - so that pass does not repeat this research. Also records
that @tag("#355") is a tag-string rename rather than a prose prefix, and
that nothing selects on that tag.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
astubbs added a commit that referenced this pull request Aug 6, 2026
…r repo

Mirrors all 78 open issues from confluentinc/parallel-consumer into this
fork (#44, #117-#195, label upstream-mirror), each
carrying a code-backed diagnosis, and each backlinked from its upstream
original while that is still possible - archival kills writes, not reads,
so the backlinks were the half with a deadline. Seven are closed against
a released version.

Everything else here follows from that.

Mirroring made bare issue numbers ambiguous. The fork numbers from 1 and
confluentinc reaches confluentinc#922, so the ranges overlap completely: of the 51
numbers cited across the files this touches, 48 exist in BOTH repos
meaning different things. #29 is our rebalance fix and
confluentinc#29 is an async-sending request; #114 is a docs PR and
confluentinc#114 is a GPG key issue. So a reference now names its repo
below #1000, and a CI gate enforces it on added lines.

The gate went through three designs, and the discarded two look
plausible enough to be worth recording. Comparing against "the fork is
at #N" raced - CI read 196 while #197 already existed. Checking
whether a number resolves here fails worse: `#200` resolves, to a fork
issue about ManagedTruth, while the author meant confluentinc#200,
shared-nothing architecture. A wrong reference that resolves is worse
than a broken one, because nothing looks amiss. The rule is textual, so
it makes no API calls and cannot race.

The qualifier names the owner rather than the role - confluentinc#857,
not "upstream confluentinc#857". "Upstream" describes a relationship and is not
stable: this repo is upstream to anyone who forks it. "Fork" is out for
the same reason.

Also swept every reference in the files touched here, fixed the source
comments behind the generated TODO index rather than the index, and
stopped the quarantine fixtures borrowing real PR numbers - #80 and #123
are live fork PRs, so the fixtures read as genuine references.

The map shrinks to match: upstream-map.yaml tracks upstream PRs only,
because issues now live in the mirror, and the manifest-driven backlink
tooling is retired - it commented one issue per map entry, and the map no
longer holds issues.

Two corrections the work surfaced: the sweep was reporting our own
backlink comments as upstream activity, hiding the two real replies among
all 78; and confluentinc#548 was recorded open when it merged in 2023 and
is already in this fork.

Remaining tree-wide references are deliberately out of scope, tracked in
docs/inflight/next-qualify-remaining-refs.md with the Java set already
classified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
astubbs added a commit that referenced this pull request Aug 6, 2026
…r repo

Mirrors all 78 open issues from confluentinc/parallel-consumer into this
fork (#44, #117-#195, label upstream-mirror), each
carrying a code-backed diagnosis, and each backlinked from its upstream
original while that is still possible - archival kills writes, not reads,
so the backlinks were the half with a deadline. Seven are closed against
a released version.

Everything else here follows from that.

Mirroring made bare issue numbers ambiguous. The fork numbers from 1 and
confluentinc reaches confluentinc#922, so the ranges overlap completely: of the 51
numbers cited across the files this touches, 48 exist in BOTH repos
meaning different things. #29 is our rebalance fix and
confluentinc#29 is an async-sending request; #114 is a docs PR and
confluentinc#114 is a GPG key issue. So a reference now names its repo
below #1000, and a CI gate enforces it on added lines.

The gate went through three designs, and the discarded two look
plausible enough to be worth recording. Comparing against "the fork is
at #N" raced - CI read 196 while #197 already existed. Checking
whether a number resolves here fails worse: `#200` resolves, to a fork
issue about ManagedTruth, while the author meant confluentinc#200,
shared-nothing architecture. A wrong reference that resolves is worse
than a broken one, because nothing looks amiss. The rule is textual, so
it makes no API calls and cannot race.

The qualifier names the owner rather than the role - confluentinc#857,
not "upstream confluentinc#857". "Upstream" describes a relationship and is not
stable: this repo is upstream to anyone who forks it. "Fork" is out for
the same reason.

Also swept every reference in the files touched here, fixed the source
comments behind the generated TODO index rather than the index, and
stopped the quarantine fixtures borrowing real PR numbers - #80 and #123
are live fork PRs, so the fixtures read as genuine references.

The map shrinks to match: upstream-map.yaml tracks upstream PRs only,
because issues now live in the mirror, and the manifest-driven backlink
tooling is retired - it commented one issue per map entry, and the map no
longer holds issues.

Two corrections the work surfaced: the sweep was reporting our own
backlink comments as upstream activity, hiding the two real replies among
all 78; and confluentinc#548 was recorded open when it merged in 2023 and
is already in this fork.

Remaining tree-wide references are deliberately out of scope, tracked in
docs/inflight/next-qualify-remaining-refs.md with the Java set already
classified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
astubbs added a commit that referenced this pull request Aug 6, 2026
…r repo

Mirrors all 78 open issues from confluentinc/parallel-consumer into this
fork (#44, #117-#195, label upstream-mirror), each
carrying a code-backed diagnosis, and each backlinked from its upstream
original while that is still possible - archival kills writes, not reads,
so the backlinks were the half with a deadline. Seven are closed against
a released version.

Everything else here follows from that.

Mirroring made bare issue numbers ambiguous. The fork numbers from 1 and
confluentinc reaches confluentinc#922, so the ranges overlap completely: of the 51
numbers cited across the files this touches, 48 exist in BOTH repos
meaning different things. #29 is our rebalance fix and
confluentinc#29 is an async-sending request; #114 is a docs PR and
confluentinc#114 is a GPG key issue. So a reference now names its repo
below #1000, and a CI gate enforces it on added lines.

The gate went through three designs, and the discarded two look
plausible enough to be worth recording. Comparing against "the fork is
at #N" raced - CI read 196 while #197 already existed. Checking
whether a number resolves here fails worse: `#200` resolves, to a fork
issue about ManagedTruth, while the author meant confluentinc#200,
shared-nothing architecture. A wrong reference that resolves is worse
than a broken one, because nothing looks amiss. The rule is textual, so
it makes no API calls and cannot race.

The qualifier names the owner rather than the role - confluentinc#857,
not "upstream confluentinc#857". "Upstream" describes a relationship and is not
stable: this repo is upstream to anyone who forks it. "Fork" is out for
the same reason.

Also swept every reference in the files touched here, fixed the source
comments behind the generated TODO index rather than the index, and
stopped the quarantine fixtures borrowing real PR numbers - #80 and #123
are live fork PRs, so the fixtures read as genuine references.

The map shrinks to match: upstream-map.yaml tracks upstream PRs only,
because issues now live in the mirror, and the manifest-driven backlink
tooling is retired - it commented one issue per map entry, and the map no
longer holds issues.

Two corrections the work surfaced: the sweep was reporting our own
backlink comments as upstream activity, hiding the two real replies among
all 78; and confluentinc#548 was recorded open when it merged in 2023 and
is already in this fork.

Remaining tree-wide references are deliberately out of scope, tracked in
docs/inflight/next-qualify-remaining-refs.md with the Java set already
classified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
astubbs added a commit that referenced this pull request Aug 6, 2026
…r repo

Mirrors all 78 open issues from confluentinc/parallel-consumer into this
fork (#44, #117-#195, label upstream-mirror), each
carrying a code-backed diagnosis, and each backlinked from its upstream
original while that is still possible - archival kills writes, not reads,
so the backlinks were the half with a deadline. Seven are closed against
a released version.

Everything else here follows from that.

Mirroring made bare issue numbers ambiguous. The fork numbers from 1 and
confluentinc reaches confluentinc#922, so the ranges overlap completely: of the 51
numbers cited across the files this touches, 48 exist in BOTH repos
meaning different things. #29 is our rebalance fix and
confluentinc#29 is an async-sending request; #114 is a docs PR and
confluentinc#114 is a GPG key issue. So a reference now names its repo
below #1000, and a CI gate enforces it on added lines.

The gate went through three designs, and the discarded two look
plausible enough to be worth recording. Comparing against "the fork is
at #N" raced - CI read 196 while #197 already existed. Checking
whether a number resolves here fails worse: `#200` resolves, to a fork
issue about ManagedTruth, while the author meant confluentinc#200,
shared-nothing architecture. A wrong reference that resolves is worse
than a broken one, because nothing looks amiss. The rule is textual, so
it makes no API calls and cannot race.

The qualifier names the owner rather than the role - confluentinc#857,
not "upstream confluentinc#857". "Upstream" describes a relationship and is not
stable: this repo is upstream to anyone who forks it. "Fork" is out for
the same reason.

Also swept every reference in the files touched here, fixed the source
comments behind the generated TODO index rather than the index, and
stopped the quarantine fixtures borrowing real PR numbers - #80 and #123
are live fork PRs, so the fixtures read as genuine references.

The map shrinks to match: upstream-map.yaml tracks upstream PRs only,
because issues now live in the mirror, and the manifest-driven backlink
tooling is retired - it commented one issue per map entry, and the map no
longer holds issues.

Two corrections the work surfaced: the sweep was reporting our own
backlink comments as upstream activity, hiding the two real replies among
all 78; and confluentinc#548 was recorded open when it merged in 2023 and
is already in this fork.

Remaining tree-wide references are deliberately out of scope, tracked in
docs/inflight/next-qualify-remaining-refs.md with the Java set already
classified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
astubbs added a commit that referenced this pull request Aug 7, 2026
Reviewing the new solution doc surfaced a hole in the checklist that same PR
had just added: it said to check open PRs, which is a collision check. The PR
that already solved something in your file is by definition merged, so
searching only the open list finds nothing and feels like diligence - worse
than not looking, because it produces false confidence. Same for issues: the
useful ones are usually closed.

Searching merged PRs BY TOUCHED FILE - not by keywords in their titles - finds,
for this investigation:

- #110, the sibling flake on this same producerTransactionLock, fixed
  four days earlier and the source of the control-arm method
- #86, which introduced the ambient probe whose "probe clean" verdict
  this work had to qualify
- #98, the backpressure test that only passed by racing its own setup -
  the sibling rule this doc deliberately does not merge with

None would surface from a symptom search or from the open list. All three are
now cited in the solution doc, with #80, #115 and #68
from the same family, and the confluentinc#803 / confluentinc#809 / confluentinc#833 cluster upstream.

Adds to the doc what the prior-art search actually covered, including what it
did NOT (the highcpu and quarantine lanes), so the next reader knows where the
gaps are instead of assuming there are none.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
astubbs added a commit that referenced this pull request Aug 12, 2026
…e upstream map

Every remaining line-number citation in the tree had already drifted onto
something else, which is the failure mode this PR exists to remove: the file and
the section are both intact, so the pointer still reads as valid.

The chaos-suite plan's pom pointer now lands on `<skipTests>`, an unrelated build
property. It meant the `-Dexcluded.groups=` override comment, so it names that
instead.

The drain/zombie-spin plan cited `BrokerPollSystem` and `ConsumerManager`
throughout its research section. None of those numbers resolves today, because
the two names the plan turns on - `signalStop` and `shutdownRequested` - were
deleted by the very fix the plan proposed, landed in bd71724 (#80). The
bullets keep their method names as anchors and gain a pointer to `bd7172418^` for
the pre-fix code, plus the `closeInProgressSignal` sites that succeeded the flag.
The wakeup-guard pointer did not resolve even before that fix, so it says which
guard was meant rather than guessing which line was.

The silent-stall write-up verified its finding against PR #29's branch,
which has since merged master and so no longer contains either name - both cited
lines there are now blank. The finding stands as a dated record; the repair says
where to look and states that it does not re-verify.

The untracked-flakes note pins its number to "the commit CI ran", which is never
named, and on master that number now lands on a different `waitAtMost` block -
close enough to the description to be believed by anyone who checks. The number
stays, because it is what the failure report said rather than a pointer the note
chose, and the assertion the note already quotes becomes the anchor.

Widening the sweep past `docs/` found one more that every earlier pass had missed
for that reason alone: the upstream map's `PartitionState` pointer, whose field
and constructor citations had each drifted onto a neighbouring line.

Captured tool output is not a citation and is untouched - the PIT rows, the
surefire rows and the stack-trace frame - as are `#L` permalinks, which are
pinned to a SHA and do not drift. No claim, finding or conclusion is changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fpk9yEDEhPnbad2WKvZUmP
astubbs added a commit that referenced this pull request Aug 12, 2026
…283)

Documents cited source locations as `file:line`. Line numbers drift: a commit
inserting lines above the target invalidates the citation while the file and the
section are both still intact, and nothing checks it, so the citation goes on
reading as valid. Every such citation now uses an anchor that cannot drift - the
file path plus a distinctive greppable string.

This is a repair, not a tidy-up, because most of the citations had already
broken. A pom citation landed on `<skipTests>`. Two landed on blank lines. One
in `ParallelConsumerOptions` pointed at a field it described as deprecated,
which is not deprecated - the deprecated one is several fields further down. Two
in `PartitionState` landed on plausible neighbours (`private final PCMetrics
pcMetrics;`), which is the dangerous failure: a reader who checks finds
something credible and wrong.

Several drifted for the same reason, and it is worth stating because it will
recur. The citations named `signalStop` and `shutdownRequested` - the fields the
documents proposed removing - and those fields were deleted by #80, the
fix those documents argued for. A document that succeeds invalidates its own
citations.

References to `docs/inflight.md` were dangling outright: it was deleted when the
ledger became a directory. Live instructions that told a reader to go update it
now name the successor note; historical mentions keep their wording and gain
`git show 0de96fc^:docs/inflight.md`, so the record still resolves. Where
nothing succeeded an item - the deleted flaky-gate entry, whose own text said to
remove it once its fix merged, and it did - the repair says so rather than
naming a plausible neighbour.

The search had to be widened five times, and each widening found citations the
narrower one could not see. `ClassName:NN` forms carry no file extension, so an
extension-anchored pattern misses them. Bare `:NN` continuations carry no
filename. Approximate prose - "~line 1348", "~lines 1340-1425" - drifts exactly
like an exact form while surviving any search for a colon followed by digits.
Bare `L218:` lists carry neither extension nor colon-prefix. And a `docs/`
pathspec cannot see `src/docs/`. One sweep reported clean because `git grep -E`
was given `\b`, which POSIX ERE does not support: it matched nothing and exited
non-zero, which is indistinguishable from a clean tree.

That last failure is the general one. A verification result is worth only what
its detector could have caught, and every under-report here came from an
instrument that could not have fired - a link check that only matched markdown
link syntax when the references were bare backticked paths, a `file:line` sweep
that could not match a deleted-file reference carrying no line number.

Every anchor was verified by running the grep it implies and confirming exactly
one match. That step earned itself twice: review found an anchor naming a local
variable reused in two methods, and a later round rejected `commitAndWait`,
`doStep` and `syncBeginTransaction` for the same reason. A unique-looking
identifier is not a unique thing; the anchors now use declaration-level forms.

AGENTS.md gains the rule, with a distinction it was missing. Dated documents
under docs/plans/ and docs/solutions/ are historical records and must not be
rewritten to say what they did not say. That convention is right and was being
read too broadly, as though it also forbade fixing a broken pointer. Rewriting a
document's claims to match today's code falsifies what was known at the time;
repairing a reference so it still finds what the document pointed at is
required, because a citation that no longer resolves makes the record less
faithful, not more. The repair procedure itself moved to docs/citations.md - it
fires only when editing a dated record, and the root file is for what every
agent needs whatever it is doing.

Four rejected alternatives are worth recording.

Converting everything matching the pattern would have been wrong. Several
`file:line` forms are deliberately preserved - PIT survivor listings, a verbatim
stack trace, surefire failure rows - because they are captured tool output, not
citations, and rewriting them would falsify a record of what a tool printed. The
test is not whether something looks like `file:line`, but whether it is a
pointer or a transcript. GitHub permalinks pinned to a full SHA are kept for the
same reason: they do not drift.

Repairing the citations in docs/inflight/release-0.6.0.0.md was also wrong, and
review caught it. Two entries there describe finished work, so repairing their
anchors made two closed jobs point more precisely at themselves and read as
outstanding. docs/inflight/ is a live ledger, not a historical record: its rules
say a closed entry is deleted, not made accurate.

Pointing a repair at the nearest plausible successor was rejected after review
found two cases. A flake fixed by #110 had been pointed at an adjacent
open item, and a report about one race had been pointed at a different,
still-open one. Worse, a live entry exists under the same test name for a
different defect entirely. Where the correct successor does not exist, the
pointer names the history and says what it does not establish.

Making this a standing check was rejected last. A permanent gate would have to
name the pattern it forbids, and the enforcement this needs is a review habit,
not a job that runs forever on a problem that has been fixed once.

Nothing any document claims, concludes or reports was changed.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
astubbs added a commit that referenced this pull request Aug 12, 2026
… expires

Chaos Pain Suite went red on this branch with an ambient-probe kill in
ChaosChurnStormIT.churnStormMeetsSlosAndBalancesLedger. The sighting joins the
confluentinc#857 family's existing ones.

The reason it is captured on a fork-identity branch rather than left in CI is
that the replay seed cannot be recovered once the log and artifact expire, and
the seed is what makes the run reproducible at all. Everything else in the entry
is retrievable; that number is not.

The signature is ZOMBIE_MEMBER/REBALANCE_BLOCKED - a member not answering the
rebalance - with rebalance dwell at 15426ms against a 15s bound and 23 partitions
frozen around 100s. That is a detector firing on its own terms rather than a
short window clipping a threshold, which is worth stating because the project's
standing caution runs the other way: a clean probe is only evidence when its
detectors could have fired.

The two sibling chaos tests in the same run are recorded as a control arm rather
than a footnote. Both passed, on their own seeds, on the same runner and broker
that hour - so the failure is not an ambient property of the machine, and the
revoke-under-work scenarios did not draw this interleaving.

The entry does not claim which defect this is. The zombie-member defect is
recorded as landed via #80 and the family's original deadlock in
#29 is still open; deciding between them is what the replay is for, and
asserting it here would put a guess into the ledger.

Also recorded: the autopsy was not in the CI log. GitHub truncated the job's
stream partway through, so neither gh run view --log nor --log-failed contained
the block and the annotations carried only an exit code. It came from the
uploaded test-report artifact, inside the failsafe XML for the failing class.
The next investigator would lose the same time, and the console will look like
the verdict does not exist rather than like it was cut off. The durable home for
that is the ambient-probe section of docs/testing.md, which currently says every
failure log includes the block; that file was owned by another branch, so the
note sits here and names where it belongs.

Nothing is remediated here: no test quarantined, disabled, retried or weakened,
and no lane re-run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fpk9yEDEhPnbad2WKvZUmP
astubbs added a commit that referenced this pull request Aug 18, 2026
… record the mode

The family ledger held six sightings and recorded the commit mode for none of
them. Mode is the discriminator: it decides which defect can explain a sighting,
and its absence let a transactional-mode failure be logged as "live confirmation
the deadlock is still present" for a cycle that cannot occur in that mode.

Recovered each sighting's mode from test source and verified it:
RebalanceEoSDeadlockTest is PERIODIC_TRANSACTIONAL_PRODUCER; both
ChaosRevokeUnderWork variants inherit PERIODIC_CONSUMER_SYNC from
AbstractRevokeUnderWorkScenario; ChaosChurnStormIT is
PERIODIC_CONSUMER_ASYNCHRONOUS.

Split one file per item, per docs/inflight/AGENTS.md:

- bug-857-transactional-revoke-wait.md - the unbounded `while
  (isTransactionCommittingInProgress()) Thread.sleep(100)` on the revoke path,
  transactional mode only, on master and predating #29. Carries the
  corrected first sighting and #44 (confluentinc#803), the only issue
  upstream ever labelled a verified bug, re-triaged onto this block off
  #29.
- test-857-revoke-under-work-sightings.md - PERIODIC_CONSUMER_SYNC, the only
  sightings whose mode permits #29's AB-BA cycle to close.
- test-857-churn-storm-async-stalls.md - PERIODIC_CONSUMER_ASYNCHRONOUS, where
  the cycle cannot close, the transactional wait cannot run, and #100 and
  #80 are landed. Three sightings no known defect explains; either a
  fourth defect or the harness's own teardown races. Nobody had said this,
  because modes were never recorded.
- test-857-parallel-integration-proof.md - the Step-2 experiment, a work item
  with a trigger rather than an observation.

bug-857-family.md keeps the decomposition and gains the mode table.

None of the five captured seeds has ever been replayed. That, not a release date
and not #29 merging, is what should retire these files - so the deletion
trigger is recorded per sighting as "seed replayed and explained".

All seeds, job links and replay invocations verified preserved across the split.
Repaired the citations the move stranded, address-only, leaving every claim
alone: two solutions docs, the W4 plan, two live inflight notes, and the actor
ideation doc, whose `bug-857-family.md:33,110` line-number citations the split
invalidated - repaired beside the original rather than over it, since it is a
dated record.
astubbs added a commit that referenced this pull request Aug 18, 2026
… correct cluster 3's record

RENAME: pausedForThrottling -> subscriptionsPausedForBackPressure

"paused" means three different things in this codebase and the wrong reading is easy
to reach - I reached it myself while reviewing this branch, and concluded the flag
was a redundant mirror of ConsumerManager.getPausedPartitionSize() when it is not.
The javadoc now separates them explicitly:

  1. this flag        - WE called consumer.pause(assignment) to apply back pressure
                        because the pipeline is full. Set only by doPause(), cleared
                        only by resumeIfPaused(), both on the poll thread.
  2. State.PAUSED     - the USER asked PC to stop. Stops the poll loop and work
                        registration; does NOT pause any partition. Unrelated.
  3. consumer.paused() - Kafka's own record, and the source of truth. This flag
                        mirrors it.

It also records why being a mirror is the hazard, which is the actual defect in this
cluster: Kafka clears pause state for every partition on an EAGER rebalance (the
assignment map is replaced - SubscriptionState.assignFromSubscribed) but KEEPS it for
partitions retained across a COOPERATIVE one. resumeIfPaused() is gated on the flag,
so when the two disagree nothing resumes and consumption stops silently - which is
confluentinc#857's own symptom.

Also updates the one caller, which used Lombok's generated isPausedForThrottling().
Worth noting for the next rename: grepping the field name does not find callers of a
Lombok getter, because the generated name capitalises differently.

CORRECTION to the cluster decomposition plan

An earlier draft called cluster 3's threading problem "pre-existing". It is not. On
master every mutation of numberRecordsOutForProcessing runs on the CONTROL thread, so
a plain int is correct there. The cluster adds a fifth site,
adjustOutForProcessingOnRevoke, called from onPartitionsRevoked - the POLL thread,
inside the rebalance callback. It makes a single-threaded counter cross-thread, on
the very counter whose drift is the silent-stall signature. Corrected in place rather
than silently, because "pre-existing" is the judgement that would have let it land.

The plan now also states what the drift measurement is FOR: not how to fix the two
defects, but whether the cluster should exist. Its target symptom predates
#100, #80 and confluentinc#882. If the drift is gone on current master,
all 42 lines go; if it remains, it gets rewritten with the control thread owning the
counter.
astubbs added a commit that referenced this pull request Aug 18, 2026
…ract nobody wrote

Name the defect class behind four separate incidents (three in the
confluentinc#857 family): a component kept its own copy of a fact another
component is the authority for, and the copy drifted. Instances: the deleted
shutdown-request flag (#80), pausedForThrottling (deleted, replaced by
asking Kafka), metaCache (repaired), and commitCommand as the boundary case
where the unwritten obligation was a monitor rather than a copy.

The write-up deliberately records the counter-pressure: each mirror was the
cheap local fix for a threading constraint, which is the argument for fixing
the constraint (#142, confluentinc#200). Mechanisms are cited from the
owning docs, not restated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiZYbruWmTFGkfepmZn2er
astubbs added a commit that referenced this pull request Aug 19, 2026
…t by what kind of work it is

`feature` carried no impact, on the reasoning that proposed work has an opportunity rather than a
consequence. That made it the bin for anything not yet broken: 21 of 72 notes were `feature` with no
impact, including CI work, process notes, refactors and test debt. The tag stopped sorting anything.

Two rules fix it, both from review:

**A feature is something a USER of the library would notice.** CI automation, process, refactors and
test work are not features however new they are - they are `task`, which forces an impact, which
forces the question of what it costs to not do them.

**A feature that exists to prevent a consequence carries that consequence.** The point of the tag is
that work falls out in priority order, not that it is filed under the correct part of speech. A
commit-failure seam whose motivation is PC shutting down is `feature` + `crash`, so it sorts with
crashes rather than being buried among cosmetic features. Producer fencing likewise carries
`reliability`. So `feature` may now carry an impact, and should whenever one applies.

New impacts, all on the existing "what does it cost you not to know" axis: `crash` (the process dies
or exhausts a resource until it does), `reliability` (survives less than it should, no single defect
named yet), `refactor` (the code is harder to change than it needs to be), `ci`, `process`, and
`test-debt`. `security` is extended from bugs to tasks, for the CVE backlog.

23 notes retagged. Two filenames were lying and are renamed: `parked-docs-site` is in planning draft,
so it is open and its state tag is removed; `parked-stale-arrival-guard-...` was already tagged
`blocked`, not parked. Citations to the old name in two dated plans and a solutions doc are
repointed - a path repair, not a rewrite of what those records claim.

Two judgements recorded because they went against the first reading:

- `branch-stall-experiments` stays `stranded-work` rather than becoming `stall`. Its own first line
  is "one result worth keeping, then delete", and the composition experiment behind #80 has
  merged. It is stranded branches, not an open stall.
- `parked-stale-arrival-guard-...` becomes `task`/`reliability`, not `bug`. Checked against master:
  `addWorkContainer` tests the RESIDENT for staleness, which is #31's merged half; the ARRIVAL
  check is still absent. But the note itself records that stale arrivals are harmless today -
  `couldBeTakenAsWork` refuses them and `getWorkIfAvailable` evicts them inline - so `bug` would
  overstate a live defect. It is work that prevents churn rather than cleans it up.

The vocabulary itself and its gate live one PR up, and change with it.
astubbs added a commit that referenced this pull request Aug 19, 2026
…t by what kind of work it is

`feature` carried no impact, on the reasoning that proposed work has an opportunity rather than a
consequence. That made it the bin for anything not yet broken: 21 of 72 notes were `feature` with no
impact, including CI work, process notes, refactors and test debt. The tag stopped sorting anything.

Two rules fix it, both from review:

**A feature is something a USER of the library would notice.** CI automation, process, refactors and
test work are not features however new they are - they are `task`, which forces an impact, which
forces the question of what it costs to not do them.

**A feature that exists to prevent a consequence carries that consequence.** The point of the tag is
that work falls out in priority order, not that it is filed under the correct part of speech. A
commit-failure seam whose motivation is PC shutting down is `feature` + `crash`, so it sorts with
crashes rather than being buried among cosmetic features. Producer fencing likewise carries
`reliability`. So `feature` may now carry an impact, and should whenever one applies.

New impacts, all on the existing "what does it cost you not to know" axis: `crash` (the process dies
or exhausts a resource until it does), `reliability` (survives less than it should, no single defect
named yet), `refactor` (the code is harder to change than it needs to be), `ci`, `process`, and
`test-debt`. `security` is extended from bugs to tasks, for the CVE backlog.

23 notes retagged. Two filenames were lying and are renamed: `parked-docs-site` is in planning draft,
so it is open and its state tag is removed; `parked-stale-arrival-guard-...` was already tagged
`blocked`, not parked. Citations to the old name in two dated plans and a solutions doc are
repointed - a path repair, not a rewrite of what those records claim.

Two judgements recorded because they went against the first reading:

- `branch-stall-experiments` stays `stranded-work` rather than becoming `stall`. Its own first line
  is "one result worth keeping, then delete", and the composition experiment behind #80 has
  merged. It is stranded branches, not an open stall.
- `parked-stale-arrival-guard-...` becomes `task`/`reliability`, not `bug`. Checked against master:
  `addWorkContainer` tests the RESIDENT for staleness, which is #31's merged half; the ARRIVAL
  check is still absent. But the note itself records that stale arrivals are harmless today -
  `couldBeTakenAsWork` refuses them and `getWorkIfAvailable` evicts them inline - so `bug` would
  overstate a live defect. It is work that prevents churn rather than cleans it up.

The vocabulary itself and its gate live one PR up, and change with it.
astubbs added a commit that referenced this pull request Aug 20, 2026
…assert, and even out the discriminator

Two findings from the round-2 review, both about a claim reading wider than the evidence behind it.

**The ledger's scope.** "Asserts ordering under churn" reads as "no two owners ever concurrently touch
a key across a revoke", and it does not mean that. Overlap is compared only WITHIN a window, so a
cross-epoch overlap - an old-epoch delivery still executing on a stopped-but-not-drained owner while
the new owner processes the same key - lands in two windows and cannot raise LEDGER_KEY_CONCURRENCY
by construction. That is the window working: a new epoch legitimately opens a new window, which is
what stops at-least-once redelivery after a revoke from reading as a violation.

It needs saying out loud because that gap is the shape of a product bug this repo has already found
once - the drain-path zombie fixed in #80 - so a reader could reasonably assume the new ledger
covers it. It does not, and is not trying to; detecting cross-epoch overlap needs an instrument that
outlives an epoch.

**The discriminator was asymmetric and I had it backwards.** The RED side of the uncontended-replay
test is positive evidence - the schedule crossed the bound with no contention - and one instance
carries it. The GREEN side is an ABSENCE, and this family is intermittent: the ledger records the same
seed swinging 5 / 7 / 10 violations across otherwise-identical uncontended runs. So an intermittent
occurrence that simply does not fire on one replay is indistinguishable from contention, which makes a
single green the WEAKEST cell in the table while it was being read as decisive. The green side now
asks for two or three, and the occurrence recorded there is marked as having one.
astubbs added a commit that referenced this pull request Aug 27, 2026
…Kafka rather than mirroring it (#376)

`BrokerPollSystem` kept a `volatile boolean pausedForThrottling` in step with its own
`consumer.pause()` / `resume()` calls. It is a copy of a fact Kafka owns, and the contract
for keeping it in step was written nowhere. This deletes the copy and asks Kafka.

## Why the mirror cannot be kept correct, so this is a deletion and not a fix

Kafka does opposite things under the two rebalance protocols - verified against
kafka-clients 3.9.2 source, not inferred from behaviour:

- **Eager**: `ConsumerCoordinator.onJoinPrepare` calls `assignFromSubscribed(emptySet())`,
  replacing the assignment map. Every `TopicPartitionState` is destroyed, so every partition
  comes back unpaused.
- **Cooperative**: `assignFromSubscribed` reuses the existing per-partition state object for
  retained partitions, and that object holds the `paused` boolean, so retained partitions stay
  paused. When the revoked set is empty it is not called at all.

A mirror therefore has to model both protocols and stay right as Kafka changes. Deriving the
answer makes the protocol irrelevant and the logic self-correcting: after a cooperative
rebalance the retained partitions are still paused, so `resumeIfPaused` resumes them; after an
eager one there is nothing to do.

**No reset-on-assignment hook is needed, and adding one is the specific mistake this shape
prevents.** A reset is right for eager and leaves cooperative permanently paused - consumption
stopping with no error.

## Two accessors, because two threads

`consumer.paused()` is a consumer call and `KafkaConsumer` is not thread-safe, so the poll
thread gets `subscriptionsArePausedForBackPressure()` and the control thread gets
`isSubscriptionsPausedForBackPressure()`, which reads `ConsumerManager`'s cache - refreshed
once per poll, and acceptable ONLY for the heuristic that wakes a poller it believes is paused.

`isPausedForThrottling()`, the Lombok getter on the deleted field, had one caller
(`AbstractParallelEoSStreamProcessor.maybeWakeupPoller`), re-pointed at the control-thread
accessor.

## The hot path reads Kafka once per pass, not three to five times

`paused()` is a real call, and `managePauseOfSubscription` plus the three methods below it were
each asking again. The set is now read once and threaded down as a PARAMETER rather than held
in a field - a local cannot outlive the pass, so there is no invalidation to get wrong and
nothing that can go stale between iterations, which is exactly the failure mode of the mirror
it replaces. The resume path makes strictly fewer calls than before, since it used to fetch the
set a second time to act on it.

## What this is NOT

**It is not a fix for a live master defect**, and it closes no issue. Master has the mirror but
never resets it on assignment, so the cooperative failure is not reachable here - it was
reachable on #29, where the reset was added, and that is where the
symptom was found: a fix for confluentinc#857 reintroducing confluentinc#857's own symptom.

`BrokerPollSystemCooperativeRebalancePauseTest` therefore passes on master too. It is a
REGRESSION GUARD against reintroducing the reset, not a red control for this diff. Stated
because a test that passes on both arms proves nothing about the change it ships with, and
reading it as evidence would be wrong.

## The defect class, and what else carries it

Ships `docs/solutions/architecture-patterns/a-mirror-of-state-another-component-owns-is-a-contract-nobody-wrote.md`,
which names the class - state carrying a synchronisation obligation nobody wrote down - and
inventories every instance in this codebase: the consumer-manager shutdown flag (deleted,
#80), this one (deleted), `metaCache` (repaired with `volatile` on the confluentinc#857
branch, and STILL A LIVE MIRROR), and `commitCommand`, whose monitor silently became the lock
guarding commit execution - the AB-BA deadlock at the centre of confluentinc#857.

The honest counter-pressure is recorded with it: a mirror is usually a threading constraint
wearing a field's clothes, and the seam that makes asking the owner hard is the poll/control
split over a consumer that is not thread-safe - the shared-nothing refactor, still open as
#142 / confluentinc#200.

Extracted from #29 so it can be reviewed on its own merits while that
PR stays blocked on its dependencies.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@astubbs astubbs added this to the 0.6.0.0 milestone Sep 1, 2026
astubbs added a commit that referenced this pull request Sep 1, 2026
Checked every issue and PR the transactional registers name, against GitHub rather than against
memory. Four claims had gone false, and one of them is the kind that stops a reader looking.

**#177's mirror is closed while confluentinc#833 is open.** The map listed it as open; it was
closed as completed on 2026-09-01 by the fork owner, with no reason on the issue and no linking
commit, and the upstream report it mirrors is still open and still unanswered. The last comment on
the mirror, five days earlier, argues the opposite - #267 renames the type in the title but
does not fix the report - and ends "Left open". Nothing written down says what changed.

That matters beyond bookkeeping: AGENTS.md makes the fork mirror the owner of an upstream issue's
live status, so the mirror is currently asserting a status confluentinc#833 contradicts. Both
`branch-transactional-battle-test.md` and `next-tell-809-833-they-are-likely-fixed.md` now say so,
the latter with its own section, because that note's whole purpose is "tell the reporters" and
closing the mirror is not telling anyone. Task 3 in it is half unreachable now - commenting on a
closed mirror reaches nobody - and task 4 has grown to include reopening it or recording why it
closed. No reason is invented here; only what is observable is written.

**#29 targets `master`, not `master-confluent`, and is out of draft. #31 has merged.**
The blockers register still said both target the pinned pre-rebrand mirror and needed retargeting.
The retarget happened; what survives is the half that was never mechanical - #29's deadlock fix
predates the internals #80 reshaped, so it needs reconciling rather than replaying.

**Both of #262's parents have merged**, so the transactional stack section is rewritten from a
land order into what it is now: history, plus one debt.

**The debt is real and worth naming.** #257's merged commit message describes redelivery -
"handed records back for a second delivery" - and never says *stall*. What #262 established is
more severe: only a success marks a partition dirty, so every batch failing meant no commit was ever
attempted and the source offset froze at 3 of 201. `git log -1 --format=%B b36ad94 | grep -i stall`
returns nothing. Release notes are generated from the commit log, so 0.6.0.0 publishes the weaker
claim unless the release section is amended or a follow-up commit says so.

Also confirmed unchanged, so the map is not merely un-contradicted but checked: #44,
#175, #189, #232 and #241 are all still open; confluentinc#809 and
confluentinc#833 are both still open upstream; #100 is merged.

`docs/inflight/handoff-262-master-merge.md` was already deleted in b99377b and is confirmed absent
from the tree; this commit does not touch it.
astubbs added a commit that referenced this pull request Sep 2, 2026
… it actually answered

Help text says what each command does and when to reach for it. What it cannot carry
is what the answers look like on a real question - and, more to the point, why the
working-tree version of each answer is wrong. That is what this document is for, and
every example in it is a lookup that happened rather than one composed to read well.

THE FIRST EXAMPLE IS THIS PR'S OWN CI FAILURE.
`PartitionStateCommittedOffsetIT.committedOffsetRemoved[1]` went red on a branch that
changes no Java at all. One `prior-art --headings committedOffsetRemoved` returned
three hits:

  - a dated plan on master: it re-flaked after #80 un-quarantined it
  - a SOLVED write-up on master: a previous instance, an offset-reset race in the
    test harness
  - docs/inflight/test-load-tightness-flakes.md, NOT on master, on sixteen refs,
    carrying entries dated 2026-09-01 that track this exact test and parameter and
    say it is still re-flaking

A working-tree search finds the first two and concludes the flake is fixed. The ledger
saying otherwise is on sixteen branches and none of them is master. The tool caught its
own thesis on its own pull request, which is a better argument for it than anything
written in its header.

The other examples cover the same ground for the commands that answer a different
question: `note drift` before editing a shared note, where 198 of 274 carrying refs are
merely behind and reporting them would bury the two dozen that differ; `stranded` and
the three filters that run before it reports; and `note find` for the path `note drift`
wants.

Also states the exit-code contract in plain terms, because it is load-bearing rather
than decorative: both P0s found while building this were failures rendering as
confident empty results.

Routed from AGENTS.md's topic table, since a document nobody opens is a document that
does not exist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTX8obQMsjs9kq2rkpU5cZ
astubbs added a commit that referenced this pull request Sep 4, 2026
…ng PC waits on the coordinator that is waiting on it

THE FRAME, FROM RUN 33824474506 (3 failures in 60)

  RUNNABLE parked-at=sun.nio.ch.EPoll.wait
    via NetworkClient.poll <- ConsumerNetworkClient.poll
        <- ConsumerNetworkClient.awaitPendingRequests(ConsumerNetworkClient.java:355)
        <- AbstractCoordinator.close(AbstractCoordinator.java:1140)
        <- ConsumerCoordinator.close(ConsumerCoordinator.java:987)
        <- ClassicKafkaConsumer.close(ClassicKafkaConsumer.java:1140)

The poll thread is inside consumer.close(), waiting on the group coordinator. Three candidates are
refuted by this one frame: the RetryQueue write lock (already refuted by experiment),
ConsumerManager.close's Thread.sleep wait for pendingRequests, and a commitSync retry. None of them
appear; the thread is waiting on the BROKER.

THE CYCLE, WHICH IS WHY IT NEVER RECOVERS

closeDontDrainFirst transitions straight to CLOSING. handlePoll is guarded on RUNNING || DRAINING, so
the instance stops calling consumer.poll() while still an open group member. doClose then hands
Kafka's close a 30-second budget, and Kafka's close waits for pending coordinator requests - which
the coordinator cannot answer, because the group is in PreparingRebalance waiting for JoinGroup from
the very members now sitting in that wait. Each closing member waits for a coordinator that is
waiting for it. The 23-25s poll-pass age is that budget being burned; waitForClose has a shorter one,
which is why ten instances logged a TimeoutException while still CLOSING.

IT IS THE #80 DEFECT, ONE LIFECYCLE STATE ALONG

#80 fixed "draining PC stops polling - zombie partition hold" for DRAINING, and its guard's javadoc
already states the general reason: rebalance participation happens inside consumer.poll(), so a
member that stops polling but keeps its membership cannot answer. CLOSING never got that fix, and
close() bypasses DRAINING entirely - so the most common close takes the unprotected path.

The invariant this makes explicit: A PC INSTANCE THAT HAS NOT YET LEFT THE GROUP MUST KEEP POLLING
IT. DRAINING honours it; CLOSING does not.

Found by re-running the prior-art sweep against the NEW mechanism rather than the old one. The first
sweep searched the retry-queue/rebalance-callback shape and could not have found this; searching
closeDontDrainFirst and waitForClose surfaced #80, its write-up and its guard test immediately. The
sweep is per-mechanism, not per-investigation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WErnxQd9Ew57F9SsqzdPU5
astubbs added a commit that referenced this pull request Sep 4, 2026
… has actually left the group

THE DEFECT

A member that has stopped polling but has NOT yet left the group cannot answer a rebalance - rejoin
and revoke-ack both happen inside consumer.poll(). PC stopped polling the moment it entered CLOSING,
while its consumer was still subscribed, and then handed that consumer to close().

The cost is a distributed livelock, not a slow shutdown. With a JoinGroup already in flight,
consumer.close() reaches AbstractCoordinator.close -> ConsumerNetworkClient.awaitPendingRequests and
waits for that request; the coordinator will not answer a JoinGroup until every member has joined -
including the members already stuck in that same wait. Each closing member waits for a coordinator
that is waiting for it, for the whole DEFAULT_TIMEOUT budget, as a silent group member. Peers see the
group frozen in PreparingRebalance and stop making progress entirely.

Captured stack from a stalled instance:

  RUNNABLE  EPoll.wait <- ... <- ConsumerNetworkClient.awaitPendingRequests(355)
            <- AbstractCoordinator.close(1140) <- ConsumerCoordinator.close(987)
            <- ClassicKafkaConsumer.close(1140)

IT IS #80's DEFECT ONE LIFECYCLE STATE ALONG

#80 fixed exactly this for DRAINING - "draining PC stops polling - busy-spin + zombie partition
hold" - and CLOSING never got the fix. That mattered more than it sounds, because
closeDontDrainFirst() is what a bare close() calls and it reaches CLOSING WITHOUT passing through
DRAINING at all: the commonest close took the unprotected path. BrokerPollSystemDrainTest's javadoc
had already written down the general reason; only the DRAINING half was implemented.

TWO GUARDS, BOTH LOAD-BEARING, AND THE SECOND WAS NEARLY MISSED

BrokerPollSystem.handlePoll() skipped CLOSING, and ConsumerManager.poll()'s retry loop ALSO
short-circuits on closeInProgressSignal. Fixing only the first still yields zero polls; the new test
caught that. The commit path one method away already had the right shape -
"allow to try to commit at least once during close / shutdown regardless of the signal",
while (tryCount == 0 || !closeInProgressSignal...) - and the poll path simply never got the same
allowance. It now does, so a closing instance gets exactly ONE poll attempt, never a retry loop:
bounding retries during shutdown is what that signal is actually for.

WHAT CHANGED FOR A USER

Closing one PC instance no longer freezes its peers' consumer group for the close timeout. This is
not test-only: a rolling restart of a PC fleet is the ordinary case that hits it.

EVIDENCE, AND WHAT IS NOT YET CLAIMED

Measured on the capacity profile at 2 failures in 30 and 3 in 60 before this change, always the same
signature, with ten of twelve instances parked in the stack above. BrokerPollSystemCloseTest asserts
the poll happens, and is proven red with EITHER guard reverted and green with both. Full core unit
suite green.

The end-to-end rate is NOT yet re-measured against this fix - that run is what turns this from a
fix that should work into one that does, and the note carries the pre-fix baseline to beat.

Test asserts on poll(1ms) rather than a poll COUNT deliberately: pollBrokerForRecords gives every
state that is not RUNNING/DRAINING a 1ms timeout and CLOSING is the only such state reaching
handlePoll, so the argument identifies a closing poll exactly, where a count would race the loop's
ordinary long polls and could pass with the defect present.

No @GuardedBy annotation: this adds no shared state, it removes a state exclusion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WErnxQd9Ew57F9SsqzdPU5
astubbs added a commit that referenced this pull request Sep 5, 2026
…etire the two notes this PR overrode

A ce-doc-review pass over this branch's three commits falsified six factual claims
they made and found two inflight notes the PR had silently overridden. Each is a
claim that read as verified and was not, which is the class this repo's own rules
call a false green: none of them would have gone red anywhere.

1. The `@Disabled` grep claim was wrong in two places - the new test-hardening
   entry and release-0.6.0.0.md's gate section both said
   `grep -rn "@disabled" --include="*.java" .` returns nothing but historical
   prose. Running it returns a live `@DisabledOnOs(OS.WINDOWS)` on
   AbstractQuarantineScriptTest and two `@Disabled` string literals built into
   TransactionalClaimCoverageTest's assertion messages, on top of the prose.
   Both sentences now describe what the command actually returns and why the gate
   still holds - no live bare `@Disabled` on a test class or method - and name the
   command to re-run rather than a count that will drift.

2. The new ChaosRevokeUnderWorkTransactionalIT sighting said the PR "touches no
   Java" in the same sentence that named the Java file it deletes. Replaced with
   ground the deletion does not undermine: nothing under `src/main` and nothing in
   the `chaostests` package changed, and `.github/workflows/maven.yml` gives each
   chaos shard a hardcoded `scenarios:` list (verified - Suite 2/4 is
   ChaosRevokeUnderWorkTransactionalIT,ChaosRevokeUnderWorkKeyOrderIT, passed as
   CHAOS_SCENARIOS), so removing a sanity-package class cannot reshuffle a shard.
   The opening parenthetical's artefact counts become the shape plus
   `git diff --name-status <base>..<head>`, and the bare
   `AbstractRevokeUnderWorkScenario.java:211` becomes the seed banner's own
   greppable literal, matching how its sibling citation two lines up already cites.

3. The blockers recheck said "every occurrence is already conditional" of
   module-maturity.yaml's production-use wording. Half true: the `support_posture`
   lines are conditional, the `maturity: production-use` field values are bare.
   The record now says exactly that, so the second recheck starts from the state
   rather than from the first pass's summary of it. No yaml value changed - whether
   an unqualified maturity value is a claim the open confluentinc#857 family
   falsifies is a release call for the maintainer.

4. release-0.6.0.0.md's opening block said #80 emptied the quarantine
   registry so release.yml's gate now passes, while the section this PR rewrote
   records MultiInstanceRebalanceTest.largeNumberOfInstances as quarantined and
   blocking. docs/quarantined-tests.md confirms the entry is live and unowned, so
   rule 5 still bites; the opening block now says the gate does NOT pass and points
   at the registry as the enforced copy.

5. Retired docs/inflight/test-progressbar-width-needs-a-machine-assertion.md. It
   argued for splitting the test into a machine assertion plus a tagged demo rather
   than deleting it, and this PR deleted it without naming that argument. Per
   AGENTS.md - record the reasoning you are overriding, where you override it - the
   note's alternative and why deletion won (the test asserted nothing, so the split
   describes a test still to be written rather than one being preserved;
   ProgressBarUtils.getNewMessagesBar keeps its other in-tree callers; and
   reinstating a tagged demo stays a maintainer's call this deletion does not block)
   are migrated into the test-hardening entry before the note is removed.

6. Retired docs/inflight/test-disabled-tests-before-v6.md. Its stated delete-when
   condition is met - #263 landed and no test carries a live bare
   `@Disabled` - and its four-name list is the same stale one this PR already
   replaced. Its one framing not owned elsewhere, that the disabled tests were
   inherited debt rather than a rule broken here, is migrated to
   release-0.6.0.0.md's gate section, which points at the 2026-08-08 audit for the
   per-test provenance behind it. No inbound links to fix - `grep -rn` over the tree
   returned none for either note.

7. docs/refactoring.md described ProgressBarTest.width in the present tense as a
   deliberate manual check. Past tense now, citing the deletion entry.

8. Reconciled "three of four races refound" (the new testing-evidence entry) with
   "Lincheck refound four real races unaided" (release-0.6.0.0.md, untouched by the
   earlier commits). docs/plans/2026-08-25-001-test-lincheck-poc-plan.md's verdict
   table supports the first: three of four found by the stress strategy plus one
   nobody had named, with the fourth half-found once by model checking and not
   reproducible. The release note now says that, and says to use that wording in the
   announcement.

Left alone deliberately, because they are decisions rather than errors: the lincheck
entry's merge_gate field versus the CI leg, and the jcstress anomaly disposition.

Gates: bin/check-all.sh (16 passed, 0 failed), plus check-issue-refs.sh,
check-docs-data.sh and check-file-refs.sh individually. Docs only - no code, no test
behaviour, no changelog entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019SVm2cT6ZgUyPMim9CukYK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

0.6.0.0 Targeted at the 0.6.0.0 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants