Repository navigation
Conversation
…ith the controls that keep it honest Adds parallel-consumer-example-streams-pc: a main() that starts its own broker in Docker and runs one workload twice - stock dispatch, then PC dispatch - varying only PcDispatchSwitch, then prints both latency distributions side by side. The topology is ordinary Kafka Streams with no Parallel Consumer API in it; taking the dependency is the whole integration. The effect it shows is head-of-line blocking: one 1500ms record at the head of a single partition with 24 fast 25ms records behind it on other keys. Under stock dispatch every fast record waits for it; under PC dispatch they do not. Measured on this machine at 13.3x on the median fast record and 1.51x on the whole-batch drain, with the median reading between 13.3x and 19.0x across five consecutive runs. No figure from the branch this was copied from is repeated: those were measured without wake-on-work and do not describe this build. The switch is turned on EXPLICITLY, in both arms. It defaults off here, so an arm that merely omitted the call would silently be a second stock arm and the comparison would be of one thing against itself. That default is also the demo's subject: unsupported topology shapes are not yet refused, so an opt-in preview is the honest configuration, and this module is exactly the artifact that opts in. WHAT THE DEMO REFUSES TO LEAVE TO TRUST - ClasspathGuard. The patched Kafka classes take effect only by winning classpath order, and when they lose nothing throws - the run would print plausible numbers meaning nothing at all. It resolves each patched class first, prints where it loaded from, and aborts loudly if the stock jar won. It then asks the loaded StreamTask for the pcDispatcher field the patch adds and prints its declared TYPE, because provenance and content are different questions with the same happy answer. Its unpatched control is now PartitionGroup: not in this branch's patch set, and the exact thing the seam routes around, so seeing it come from the stock jar says the seam replaced dispatch and left Kafka's own queueing alone. - PcDispatchCounters, printed per arm. dispatchedToPool is incremented at exactly one place in the codebase, so 0 in the stock arm and 25 in the PC arm is evidence rather than assertion. splitPollWaits and wakesOnWork are printed beside them, separately, because wake-on-work is a second mechanism that arrives on the same rung and would otherwise be credited to the seam. THE NEGATIVE CONTROL MOVED, AND SO DID THE CHECK ON IT The same workload with every record on ONE key, where PC's key ordering leaves no concurrency to exploit. On the branch this was copied from that arm LOST, at 0.69x, and the demo's prose explained the loss and said the fix was a later change. That fix - the split poll wait - is present here, and the arm now lands on parity: 0.99x, 0.99x, 0.98x, 1.01x across four runs, plus one reading 1.19x. That one reading is why the section's check was rewritten. The inherited check asked which DIRECTION the median went, which is a sound test of an arm that loses and a coin toss for an arm at parity - it fired on the 1.19x run and would fire on roughly half of all healthy runs. It now tests a band around parity, in either direction, because a PC WIN here would void the headline rather than strengthen it. A NOISE FLOOR, MEASURED INSIDE THE RUN The 1.19x run's two STOCK arms differed by 1.20x. They do byte-identical work - stock Kafka Streams ignores keys, and the per-record cost here is chosen by value - so that difference is pure variance, and the control had measured nothing. The summary now prints it as a NOISE FLOOR row and tells the reader to read every ratio against it. Without it on screen that run looks like a finding. PROVEN ABLE TO FAIL, AND THE PREDICTION THAT WAS REFUTED The dispatch switch was neutered so the PC arms ran stock, with six predictions stated first. Five held: dispatchedToPool read 0 and the per-arm warning fired, splitPollWaits read 0 and its warning fired, the summary printed its DO NOT QUOTE banner, the negative control stayed green, and ClasspathGuard still passed - localising the loss to the switch rather than to the build. The sixth was refuted, and it was mine. The headline check asked only whether PC came out ahead at all; the sabotaged run measured 1.01x, satisfied it, and printed "a fast record no longer waits for an unrelated slow one" over a run in which every fast record had waited. A check a broken run can satisfy is not a check. It now requires a margin far outside any measured noise - 2.0x, sitting in the empty space between a sabotaged 1.01x and a real 13x-19x - and re-running the same sabotage fired it, with the negative control still green. That asymmetry is what says the right thing broke. LatencyScenarioTest pins that case in the ordinary build, because a passing demo run never enters the contradiction branch and the demo itself is behind -Pdemo, so nothing in CI would otherwise reach it. Verified red by relaxing the threshold to 1.0: exactly that one case failed. TWO GATES THIS MODULE MET THAT ITS SOURCE BRANCH DID NOT Neither is a copy defect; both fire on our own code and are fixed rather than excluded, as the machinery rung said would happen. - Error Prone ReturnValueIgnored on the guard's reflective getDeclaredField. Fixed by using the result - printing the field's declared type - which is better evidence than the bare presence check it replaced. - forbiddenapis on Console's locale-dependent String.format. Fixed with Locale.ROOT, which the report wanted anyway: it is a fixed-width table of grouped numbers, and a locale that groups differently would misalign the columns a reader compares down. The demo is gated behind -Pdemo and bound to process-classes, so an ordinary build never starts a broker. parallel-consumer-example-streams is untouched: it is the provably-unpatched baseline arm, and a PC dependency there would destroy that evidence. The new module is added to both Maven Central deploy exclusion lists, so a release cannot publish a demo. Copied from #271's feats/ks-streams-pc-example branch and adapted: the Java packages renamed io.confluent to bz.stub, StreamThread moved from the guard's unpatched control into its patched set, and the cross-references to a HeadOfLineBlockingBenchmarkTest that does not exist on this stack removed rather than left pointing at nothing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Um4ssjUsPh8ng73U7iKvdE
…ams seam The workstream signpost listed "the example module" among the things still off master. It is not, now, and the correction is worth more than accuracy: the note's whole complaint is that an agent reading it finds sideways references to the work and no way in. A runnable demo that prints its own evidence is that way in, and leaving it in the not-yet list would send the next reader to the branch forest for something master already has. Says what the demo shows rather than only that it exists - both arms, the dispatch counters as evidence, the negative control and the within-run noise floor - because "there is an example module" does not tell a reader whether it answers their question.
Dependency ReviewThe following issues were found:
License Issuesparallel-consumer-examples/parallel-consumer-example-streams-pc/pom.xml
OpenSSF Scorecard
Scanned Files
|
✅ Duplicate Code ReportTwo 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
No new clones introduced by this PR. ✅ jscpd (language-agnostic)
No new clones introduced by this PR. Powered by astubbs/duplicate-code-cross-check |
🧪🔒 Quarantine Lane Report
🔴 expected while the owner PR is open · 🟡🎲 flapper, pass proves nothing · 🚨 a deterministic quarantined test passing means its fix landed: delete its |
|
… dragging two CVEs onto the runtime classpath Three findings from the module's first CI run, all of them things a new module in this repo has to do and none of them visible until it existed. WIRE UP ARCHUNIT EveryModuleWiresUpArchUnitTest failed the Unit Tests lane: every module with test sources needs its own TestConventionsArchTest, because ArchUnit imports from the classpath of the module it runs in, and without one it silently does not run there at all. A sibling in parallel-consumer-example-streams names the package bz.stub.parallelconsumer.examples.streams, which looks as though it would cover this module's .pc sub-package - it does not, and the file says so, so the next reader does not delete it as a duplicate. The core test-jar comes with it, for the one class that holds the shared rules, at test scope so it cannot reach the demo's runtime classpath and disturb the ordering the whole mechanism depends on. NO SLF4J BINDING, AND THE CLAIM THAT SAID THERE HAD TO BE ONE IS WRONG deps: whole-tree CVE scan flagged logback-classic 1.6.1 (CVE-2026-19880, CVSS 6.3) in this module and nowhere else. That is not a coincidence: the scan audits the RUNTIME scope, logback is test scope everywhere else in this repo and therefore invisible to it, and this module's compile-scope declaration was the first thing in the tree to put it there. The inherited pom comment defended that declaration on the grounds that without a binding, main() warns about missing providers and Kafka's INFO logging then buries the report. The first half is true; the second half is not, and it was worth measuring rather than believing. SLF4J 2.x with no provider is a NO-OP, not a fallback to console. Measured: a run without logback emits three warning lines at startup and then ZERO log lines between the classpath check and the summary. Removing the dependency made the report cleaner, removed the finding at source, and cost the module two dependencies and a config file it did not need. The pom now records that as a decision rather than an omission, with the measurement, so re-adding a binding is a change somebody has to argue for. PIN COMMONS-COMPRESS PAST ITS TWO ADVISORIES Same gate, same cause, different dependency: testcontainers has to be compile scope here because DemoBroker lives in src/main, and it resolves commons-compress 1.24.0, which carries CVE-2024-25710 and CVE-2024-26308. Both are denial-of-service on malformed archives, both first fixed in 1.26.0, and neither is reachable - testcontainers uses this to build Docker contexts and copy files in, never to parse an archive this demo did not create. A fixed version exists, so it is pinned rather than argued about in an exclusion entry, and verified by running the demo end to end against a real broker on 1.28.0 rather than by assuming the API held. Module-local, for the reason example-streams gives for its own jackson pin: this is the only module putting testcontainers on a non-test classpath, so a root pin would change what every other module's tests run against to fix a problem only this one has. NULLAWAY ON THE TWO METHODS THIS BRANCH ADDED Both LatencyScenario.contradiction and stockMedianMillis were designed to return null, and NullAway said so. There is no nullability annotation library on this classpath; the codebase's idiom is Optional, so they return Optional<String> and OptionalLong. The remaining NullAway and Error Prone warnings on these files are inherited from the branch this module was copied from and are triaged in the PR body rather than silently left. Verified: the module's tests pass, and the demo runs end to end - 19.32x on the headline median, 1.00x on the negative control, 1.00x noise floor, no warnings. Two parallel-consumer-core tests (processInKeyOrder, JStreamParallelEoSStreamProcessorTest.testConsumeAndProduce) failed once in two local runs and passed on the second with nothing changed, both with the "expected N, got 0" shortfall that docs/inflight/bug-857-family.md already records as this box being saturated rather than a regression. This branch touches no core code.
…iff that are worth answering bin/check-pr-analysis-surfaces.sh reported seven findings on lines this PR wrote, none inherited. Two of them are right and are fixed; the other five are one detector making the same objection to the same deliberate shape, and are left with the reason recorded here rather than in five suppressions. Fixed: - PSC_PRESIZE_COLLECTIONS - DemoBroker.createTopics allocated its list unsized when the exact count is the varargs length it already has. - OCP_OVERLY_CONCRETE_PARAMETER - printSummary took List where it only iterates, twice. Iterable says what the method actually needs. Not changed, and it is the same finding five times: CE_CLASS_ENVY on printIntroduction, printClosing, printSummary, ClasspathGuard.failLoudly and verifyDispatchSeamIsPresent - each "excessively uses methods of another class", that class being Console. Every one of them is a report section, and Console is the report writer, so calling it repeatedly is what they are for. The refactor the detector is asking for would move this demo's explanatory prose inside the formatting helper, which is where a reader would never look for it. The `static: spotbugs` gate passes either way; this is the advisory surface, answered rather than left.
…ghtings down the stack Merges `feats/ks-streams-execution-seam` (#388), which has just taken #379's post-cut work, into this rung. Three commits arrive: the `prepare-deps` warm for the Kafka `sources` and `test-sources` classifier jars, its ledger note, and the seam rung's own carry of the invalid-timestamps flake ledger. One real conflict, resolved as a UNION rather than to a side. `docs/inflight/test-streamthreadtest-invalid-timestamps-flake.md` exists on both branches - this rung carried it forward with its own seam-off sighting and its CI sighting, and the seam rung then added the two the example rung reported (#391). Diffing the merged file against both parents shows exactly one delta on this side, the example rung's paragraph, and zero on the other: nothing either branch wrote about this flake was dropped. A sighting ledger loses its whole value when a merge picks a side. `bin/check-all.sh` exits 0 in this worktree before and after, 15 runnable gates passing. The repo's pre-commit gate evaluates a different worktree (#382), so this commit uses `--no-verify`.
Merges `feats/ks-streams-reconciled` - the reconciliation of #395, #396, #398 and #391 on top of the refreshed #394 - into this branch, so that #271 can be retargeted onto that rung and its displayed diff collapse to the residue. This is the plan's "retarget move", `docs/plans/2026-08-31-001-process-god-branch-decomposition-plan.md`, and it is an ordinary merge: no history was rewritten and nothing was force-pushed. The pre-merge tip is preserved as `origin/backup/pre-stack-merge-271`. The merge also brings `master` forward, because the stack is current with it and this branch was not. That is most of the volume and all but a handful of the conflicts. ## Which side won, and the check that made it safe to say so The rule was: the rungs' refined versions win wherever both sides have a file; the spike's residue is kept. **The second half of that is only safe if the spike contributed nothing to the shared files, and that was measured rather than assumed.** Both trees were exported with package paths normalised (`io.confluent.parallelconsumer` and `bz.stub.parallelconsumer` folded to one token, and `io.confluent.csid.utils` to its new home) and compared file by file against the branch's own merge base. The answer is clean: outside `parallel-consumer-streams` and the streams example, **every difference this branch carries is the package rename itself plus a copyright-header line** - the same rename `master` performed independently, which is why taking the rungs' side loses nothing. The one substantive exception is the streams example's stock-baseline fixtures, which are already on the stack because #398 depends on them. - **Files on both sides: the rungs' version, 93 of them.** They carry current master, the rename, and every fix the five rungs landed. - **Files only on the spike: kept, 32 of them.** The plan and result documents, the branch handover, the ranked next-work notes, the eight `docs/solutions/` write-ups, and two streams tests the stack deliberately left behind - `HeadOfLineBlockingBenchmarkTest`, which #398 says it is leaving on the forest, and `ProcessorContextConfinementTest`. That residue is what this PR still exists to review. - **Files master deleted: they stay deleted, 12 of them** - `.semaphore/`, `.travis-archived.yml`, `service.yml`, two `.idea` run configurations, the uppercase `docs/` names master lowercased, and the `InternalRuntimeException` pair master renamed to `PCInternalRuntimeException`. - **Two shared ledgers merged as unions, not resolved to a side**: `docs/inflight/pr-strategy-doc-merge-triggers.md` and `docs/inflight/release-0.6.0.0.md` keep this branch's paragraphs alongside master's. **The strongest check is the one that makes a mis-paired rename impossible to hide.** Rather than counting recorded renames, the merged tree was differenced against `feats/ks-streams-reconciled` directly: the only differences are the 32 additions and the two union-merged ledgers. Nothing else survived on the wrong side, in the wrong module, or under an `io/confluent` path - `git ls-files | grep io/confluent` is empty, and the prescribed `grep -rnE 'io[\./]*conflu'` sweep returns only prose in dated documents. **Both sides were already renamed, which is not what the plan predicted.** It expected the spike to be pre-rename; `origin/feats/ks-on-pc-spike` had in fact moved five commits past the worktree's copy and carries the rename. That is the good case AGENTS.md describes - the mis-pairing surfaces as rename/rename conflicts on the right files instead of silently applying one module's edit to another - and it did: three `TestConventionsArchTest.java` files were offered paired across modules, and the right file was taken into each module rather than accepting git's pairing. ## One collision the merge produced, and the reason it is a good one `HeadOfLineBlockingBenchmarkTest` carried a private `sleep(Duration)` helper. Since #395 hoisted the identical helper onto `BrokerStreamsIntegrationTest` - because two arms that simulate cost differently are not comparable - the two now collide, and the compiler said so rather than either winning silently. The local copy is deleted and the shared one inherited, which is what the hoist was for. ## The gates, and the one that is a scoping artefact `bin/check-all.sh` was run in this worktree. Four gates failed on first pass and **three of the four did not exist on this branch before the merge** - they arrived with master, and every finding was on content that predates them. - **`check-inflight-tags`** flagged sixteen notes with no `inflight-type`, all of them this branch's own and all older than the tag scheme. Tagged - a first pass a reviewer should correct where it reads wrong. `bug-core-tests-jar-junit-parallelism-leak.md` additionally carries a `closed` state, because #265 removed the file it is about. - **`check-file-refs`** flagged citations broken by the rename - the exact class [`docs/citations.md`](docs/citations.md) says must be repaired rather than left. Forty-seven paths were re-pointed to their successors, **each verified to exist before the edit was written**; the claims around them are untouched, which is the line that document draws. What genuinely has no repo path - Apache Kafka's own sources inside the published jar, a placeholder in a shell recipe, a class that was only ever proposed - carries a line-scoped `file-refs: N/A` with its reason. Two targets that moved out of the tree point at the history holding them instead. - **`check-issue-refs`** flagged two bare `#NNN` in the handover; qualified. - **`check-branch-self-reference`** is the artefact, and the gate's own header names this exact situation: mid-merge the merge base is still the old one, so master's sentences read as this branch's. Twenty-five of the twenty-eight files it flagged are on `feats/ks-streams-reconciled` too and twenty-four are byte-identical to it, so marking them would be attesting to somebody else's notes - which that header explicitly says not to do. Committing the merge is the documented fix. ## Verified JDK 17, macOS. The whole reactor compiles, main and test. The reconciled branch it merges was verified in its own right before this: seam-off oracle unchanged, module unit suite green, and all 35 broker-backed integration arms green against a real broker.
Serves #255.
depends on #388
Description
The claim this PR makes: the execution seam can be demonstrated to a sceptic in under half a
minute, on their own machine, in a form that tells them when not to believe it.
#388 ships the seam and the tests that show it is load-bearing. A test is
the right place to defend behaviour against regression and a poor place to be convinced by it: it
reports pass or fail to a machine, and a reader who did not run it is being asked to take the claim
on trust. This adds
parallel-consumer-example-streams-pc, amain()that starts its own broker inDocker and runs one workload twice - stock dispatch, then PC dispatch, varying only
PcDispatchSwitch- and prints which classes were actually loaded, which records actually wentthrough Parallel Consumer's pool, and what the latencies actually were.
The topology is ordinary Kafka Streams with no Parallel Consumer API anywhere in the module. Taking
the dependency is the whole integration, which is itself part of what the demo is for.
It is the artifact that opts in, and says so
The seam defaults off, and #388 explains why: joins, windows,
suppression, exactly-once and stream-time punctuation are unsupported on the PC path and are not yet
refused, so a topology using one is dispatched anyway and gets wrong behaviour with nothing in the
log to say so. This demo turns the switch on explicitly, in both arms - stating it in the stock
arm too, so neither arm inherits a default that is documented as moving the day refusal lands.
Its topology is a stateless
mapValues. Nothing was trimmed from the source example to fit thisstack: it never used a window, a join, a punctuator, a state store or exactly-once, so it was
already inside what the seam supports. The run says that out loud rather than leaving it inferred.
The negative control moved, and the check on it had to move too
The single-key arm - every record on one key, so PC's key ordering leaves no concurrency to exploit
On the branch this was copied from, that arm lost, at 0.69x, and the demo's prose explained the
loss and said the fix was a later change. That fix is the split poll wait, and it is on this base. The
arm now lands on parity.
The inherited check asked which direction the median went. That is a sound test of an arm that
loses and a coin toss for an arm at parity - it fires on roughly half of all healthy runs, and it
duly fired on the first run here. It now tests a band around parity, in either direction, because
a PC win in that arm would void the headline rather than strengthen it.
A noise floor, measured inside the run
The run that read 1.19x on the control had two stock arms differing by 1.20x. They do
byte-identical work - stock Kafka Streams ignores keys, and the per-record cost here is chosen by
value - so that difference is pure variance and the control had measured nothing. The summary now
prints it as a
NOISE FLOORrow and tells the reader to read every ratio against it. Without it onscreen, that run looks like a finding.
Figures
Re-derived here with a control arm; none copied. The forest's numbers were measured without
wake-on-work and do not describe this build, so no figure from it appears anywhere in this diff.
Head-of-line median across five consecutive runs on one machine: 13.3x, 14.5x, 14.8x, 17.9x,
19.0x, against a noise floor of 1.00x to 1.20x. The median is the figure quoted; the fastest-record
row approaches the workload's own cost ratio by construction, so it demonstrates the blocking is gone
without measuring how much is typically saved, and the output says so. Whole-batch drain moved 1.34x
to 1.51x, which is what stops the fast records having been sped up at the batch's expense. Negative
control: 0.98x, 0.99x, 0.99x, 1.01x, and one 1.19x explained by that run's floor.
Proven able to fail - including one prediction that was refuted
The dispatch switch was neutered so the PC arms ran stock, with the predictions stated first. Five
held:
dispatchedToPoolread 0 and the per-arm warning fired,splitPollWaitsread 0 and its warningfired, the summary printed its
DO NOT QUOTEbanner, the negative control stayed green, andClasspathGuardstill passed - localising the loss to the switch rather than to the build.The sixth was refuted, and it was this PR's own check. The headline test asked only whether PC
came out ahead at all; the sabotaged run measured 1.01x, satisfied it, and printed a fast record no
longer waits for an unrelated slow one over a run in which every fast record had waited. A check a
broken run can satisfy is not a check. It now requires a margin far outside any measured noise, sitting
in the empty space between a sabotaged 1.01x and a real 13x-19x, and re-running the identical sabotage
fired it with the negative control still green. That asymmetry is what says the right thing broke.
LatencyScenarioTestpins the case, verified red by relaxing the threshold - exactly that one casefailed.
What the first CI run found, and what it did not
Three things a new module in this repo has to do, none visible until it existed, all fixed in
follow-up commits on this branch:
EveryModuleWiresUpArchUnitTestfails a module with test sources and noTestConventionsArchTest. A sibling inparallel-consumer-example-streamsnames the parentpackage, which looks as though it would cover this module's
.pcsub-package; it does not, becauseArchUnit imports from the classpath of the module it runs in, and the new file says so.
anywhere else in the tree, because
deps: whole-tree CVE scanaudits the RUNTIME scope and bothdependencies are test scope in every other module.
commons-compressis pinned past its twoadvisories and verified by running the demo against a real broker on the new version.
logback was dropped entirely, because the inherited pom comment defending it was wrong: SLF4J
2.x with no provider is a no-op, not a fallback to console, so a run without it emits three warning
lines and then zero log lines between the classpath check and the summary. Removing it made the
report cleaner as well as removing the finding.
bin/check-pr-analysis-surfaces.sh 391reported seven findings onlines this PR wrote and none inherited. Two are right and fixed - an unsized collection whose exact
count was to hand, and a
Listparameter that only gets iterated. The other five are one detectormaking the same objection five times:
CE_CLASS_ENVYon the report sections and the guard's failurebranches, for calling
Consolerepeatedly. That is what those methods are; the refactor being askedfor would move this demo's explanatory prose inside the formatting helper. NullAway also flagged the
two methods this branch added as returning null - they now return
OptionalandOptionalLong,matching the codebase's idiom, since there is no nullability annotation library on this classpath.
One flake, named and already diagnosed elsewhere - and it is the only thing red here that is not
expected.
Unit Testsfailed onStreamThreadTest.shouldLogAndRecordSkippedRecordsForInvalidTimestamps:3077, in the upstream-Kafkaoracle that #388 added, at exactly the 419-run count its handover predicts.
Sighting record on this PR, four attempts of that lane: flake, Maven Central read timeout fetching
kafka-streams:jar:sources:3.9.2, green, flake. Two sightings in the three attempts that got farenough to run the suite, against the forest's measured rate of roughly 2 in 5.
It is pre-existing and diagnosed: the test embeds the current thread's name in an expected log line
while
processingThreadsEnabled=truelogs from Kafka's own thread, so the assertion depends on whichthread got there. Its ledger note has not landed on this stack, so on these branches the flake is
untracked and the next agent to meet it has nothing to find. It belongs with the rung that added the
oracle, not with this module, so this PR does not add the note - but it should not merge into a stack
that still has no record of it. Deliberately not re-run again to chase green: the forest's own
write-up names re-running-until-green as the habit this flake creates and warns against.
What the demo refuses to leave to trust
ClasspathGuard. The patched Kafka classes take effect only by winning classpath order, andwhen they lose nothing throws - the run would print plausible numbers meaning nothing at all. It
resolves each patched class, prints where it loaded from, aborts if the stock jar won, then asks the
loaded
StreamTaskfor thepcDispatcherfield the patch adds and prints its declared type,because provenance and content are different questions with the same happy answer. Adapted to this
base:
StreamThreadmoved from the guard's unpatched control into its patched set, andPartitionGrouptook its place - not patched here, and the exact thing the seam routes around, soseeing it come from the stock jar says the seam replaced dispatch and left Kafka's own queueing
alone.
PcDispatchCounters, per arm.dispatchedToPoolis incremented at exactly one place in thecodebase, so 0 in a stock arm and 25 in a PC arm is evidence rather than assertion.
splitPollWaitsandwakesOnWorkprint beside them, separately, because wake-on-work is a secondmechanism arriving on the same rung and would otherwise be credited to the seam.
Two gates this module met that its source branch did not
Both fire on our own code - the module's Kafka exclusion covers the generated
org.apache.kafkatreeonly - and both are fixed rather than excluded, as #379 said would happen.
ReturnValueIgnoredon the guard's reflectivegetDeclaredField. Fixed by usingthe result, printing the field's declared type, which is better evidence than the bare presence
check it replaced.
forbiddenapisonConsole's locale-dependentString.format. Fixed withLocale.ROOT, whichthe report wanted anyway: it is a fixed-width table of grouped numbers, and a locale that groups
differently would misalign the columns a reader compares down.
Release safety
Gated behind
-Pdemoand bound toprocess-classes, so an ordinary build never starts a broker; andadded to both Maven Central deploy exclusion lists, so a release cannot publish a demo module.
parallel-consumer-example-streamsis deliberately untouched - it is the provably-unpatched baselinearm, and a PC dependency there would destroy that evidence.
Not in this PR
The benchmark suite and the seam-on upstream evidence lane; refusing unsupported surfaces; task
lifecycle, rebalance and
revive(); stream time and punctuation. The dated plan document from thesource branch is deliberately left behind: it describes the forest's state, and this module's README
is the durable home for what the demo does.
Where this came from
Copied out of #271, the Kafka Streams feasibility study, from its
feats/ks-streams-pc-examplebranch, and adapted to this stack: Java packages renamedio.confluentto
bz.stub, the guard's patched set brought in line with this branch's patch, and cross-referencesto a
HeadOfLineBlockingBenchmarkTestthat does not exist here removed rather than left pointing atnothing. #271 remains the source god PR and keeps the semantic work, the
measurements and the open review threads.
Checklist
stops the demo flattering itself), and
docs/inflight/branch-ks-streams-workstream.md, whichlisted the example module among the things still off master
docs/features/-N/A - the module is a demo of an unpublished alpha, so there is no artifact for a user to depend on and nothing for the ladder to point at. Same reason astubbs/parallel-consumer#388 gaveLatencyScenarioTestfor the verdict check that a sabotage run got past,and the inherited
ClasspathGuardTestfor the location predicate. Both run in the ordinarybuild, which matters because the demo itself is behind
-Pdemoand would otherwise leave bothdecisions with no coverage anywhere
ce-simplifyandce-code-reviewlocally -N/A - the diff is largely a copy from a branch already reviewed on astubbs/parallel-consumer#271. What is new here - the parity band, the noise floor, the guard's changed patched set, and the threshold the sabotage exposed - is what a reviewer should spend attention on, so asking for review on the PR is the better spend