Skip to content

Commit 69f6e56

Browse files
astubbsclaude
andcommitted
merge: origin/master into fix/803-bound-transactional-revoke-wait - #466 wins the transactional revoke path
Master landed #466 (the revoke-path commit hands itself to the control thread), #468 (WorkContainer equality is identity) and #471, and this PR went CONFLICTING. #466 is a different answer to the question this branch answered: in transactional mode onPartitionsRevoked no longer commits on the poll thread at all - it posts a request, wakes the control loop through the mailbox, and waits, bounded by commitLockAcquisitionTimeout; the confluentinc#548 spin is gone; and it refutes this branch's decline by experiment (a revoke that commits nothing leaves its output in the open transaction for the next commit to publish without the offset - the same duplicate through a different door). Master's own re-premising of docs/inflight/bug-857-transactional-revoke-wait.md says what is left for this PR: not the absence of a bound, but whether the bound is the right value - five minutes, against a max.poll.interval.ms it can exceed. So the resolution is master's on that path, per file: - AbstractParallelEoSStreamProcessor: master's onPartitionsRevoked, commitOnRevokeViaTheControlThread and the no-argument consumer-commit tryCommitOffsetsOnRevoke replace this branch's parameterised decline, its performCommit extraction and its post-catch wake (moot: the served commit runs on the control thread, which recovers itself); commitOffsetsThatAreReady is master's again; the mailbox loop keeps master's wake-up message skip in front of #410's first-failure try; one of two identical assertOnControlThread helpers (#410's and master's) is kept - master's, which names the new design. - RebalanceEoSDeadlockTest: master's whole file. Its unamended assertion that committed offsets advance inside the callback holds again by construction under #466, and it now reads the output topic at read_committed for duplicates; this branch's decline amendment is superseded. - ArchitectureTest: master's whole file (#465). This branch's interface-hop widening does not merge onto it; its note now records that the blind spot is still open on master and the widening is to be re-applied on top of #465 as its own change. - ProducerManagerTest: master's revoke-request tests and this branch's five revocation tests, both kept; PartitionState: master's onSuccess(long) javadoc with #410's ledger cross-reference folded in; TransactionalClaim: master's scope note plus #410's C15. - config/infer-known-findings.txt, bug-857-family.md, core-recoverable-producer-fencing.md: master; bug-wedged-after-poisoned-transaction.md: master's deletion (the grooming sweep); the three vetted notes keep master's markers and this branch's concurrency label; test-untracked-ci-flakes keeps master's rows and this branch's three later sightings. - ProducerRecoveryTest's revoke-path fence test is retargeted to the served-commit shape: the fence now fires on the control thread inside the served pass, the callback returns promptly on the failed pass, nothing is stranded, and the replacement is built. Its wake assertion is gone with the wake. What is red, on purpose: Revoke857TransactionalWaitProbeIT, 5/5, with the callback at 19.2s of a 20s in-flight dwell against its 10s poll-interval budget - and never the 79s starvation the spin produced. That is the measurement of #466's bound, and it is this PR's remaining acceptance test, not a broken instrument. What is now dead main code, held for the owner's call: the three ProducerManager revocation lock helpers and the DeclineCountingProducerManager instrument, which count a decline the transactional path no longer makes. Verified: ProducerRecoveryTest, ProducerManagerTest, ProducerManagerDetectionTest, ArchitectureTest and the convention rules, PartitionStateAbortedTransactionReplayTest, TransactionalClaimCoverageTest; RebalanceEoSDeadlockTest 5/5, ProducerFencingRecoveryIT 2/2. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PVL2FEJ645T76PbybEBUZ6
2 parents 7ce2c4e + 0d5cbad commit 69f6e56

329 files changed

Lines changed: 14866 additions & 3790 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/hooks/after-push-check-ci.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ print(json.dumps({
8484
"checks that have already cost it once, both recorded in "
8585
"docs/inflight/ci-duplication-report-can-fail-to-post.md:\n"
8686
"\n"
87-
"1. A RED CHECK CAN HAVE NO COMMENT. `dups: clones` is a required check, and it has "
87+
"1. A RED CHECK CAN HAVE NO COMMENT. `dups: clones` is a step of the required `scan: repo` check, and it has "
8888
"failed on this repo with its finding posted nowhere - GitHub rejected the inline "
8989
"annotation and nothing fell back to a summary comment. If a check is red and you "
9090
"cannot find a comment explaining it, the finding is in the job log: "

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
## Checklist
1818

19-
<!-- Keep this checklist and resolve EVERY box: tick it [x], or mark it "N/A - <reason>". The "PR Checklist"
19+
<!-- Keep this checklist and resolve EVERY box: tick it [x], or mark it "N/A - <reason>". The "repo: hygiene"
2020
CI check fails a human PR when the checklist is missing entirely, or when a box has no [x] and no N/A.
2121
Only real bot authors (Dependabot/Renovate etc.) are exempt. -->
2222

.github/dependabot.yml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,31 @@ updates:
5151
- "version-update:semver-minor"
5252
- "version-update:semver-major"
5353
# The second Jackson pin: the jackson-bom import in
54-
# parallel-consumer-example-streams, which holds that module at 2.18.9. It needs
54+
# parallel-consumer-example-streams, which holds that module on the 2.18 line
55+
# (jackson.examples.version in the examples parent says which patch). It needs
5556
# the same hand management as the databind pin above, and it is a *different*
5657
# coordinate, so the rule above does not cover it.
5758
#
5859
# This one is not just hygiene. Jackson's fixed-version ranges are per-line, and
5960
# an automated bump can move you INTO a vulnerability: CVE-2026-59889 was
6061
# introduced in 2.18.0 and fixed only in 2.18.9, and CVE-2026-54518 applies to
6162
# 2.21.0-2.21.3 only. The root pom greenlights CVE-2026-54518 as a false positive
62-
# *because this module resolves 2.18.9*; a bump into 2.21.0-2.21.3 would make that
63+
# *because this module resolves a 2.18.x*; a bump into 2.21.0-2.21.3 would make that
6364
# finding real while the exclusion silently hid it. Leaving the LINE is therefore a
6465
# hand-managed decision, and the exclusion list gets re-checked when it happens.
6566
#
6667
# Allow patches within the pinned line; block minor/major - the same shape as the
6768
# micrometer entry below, but here the patch allowance is load-bearing rather than
6869
# tidy. This started out blanket, which was wrong in a way worth recording: every
6970
# danger named above is a LINE change (2.18 -> 2.21), while a patch inside 2.18 is
70-
# the exact thing we are waiting for. The root pom's TEMPORARY exclusions for
71-
# CVE-2026-68497 and CVE-2026-19032 retire when jackson-databind 2.18.10 reaches
72-
# Central - a patch bump IS the retirement mechanism - and a blanket ignore
73-
# suppressed the only PR that would have announced it. Neither id is in OSV, NVD or
74-
# GHSA, so no Dependabot alert can arrive instead: the ignore was covering the one
71+
# the exact thing we are waiting for. The worked case: the root pom's TEMPORARY
72+
# exclusions for CVE-2026-68497 and CVE-2026-19032 retired when jackson-databind
73+
# 2.18.10 reached Central (astubbs/parallel-consumer#445, 2026-09-04) - a patch bump
74+
# WAS the retirement mechanism - and while this entry was blanket it suppressed the
75+
# only PR that would have announced it. Neither id is in OSV, NVD or GHSA, so no
76+
# Dependabot alert could arrive instead: the ignore was covering the one
7577
# notification we were relying on. bin/check-cve-exclusions.sh is the backstop for
76-
# when that happens anyway. See docs/inflight/deps-cve-backlog.md.
78+
# when that happens again. See docs/inflight/deps-cve-backlog.md.
7779
- dependency-name: "com.fasterxml.jackson:jackson-bom"
7880
update-types:
7981
- "version-update:semver-minor"

.github/scripts/changelog-ref-gate.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright (C) 2026 Antony Stubbs and contributors
22

33
// Pure logic behind the "Verify new changelog entries cite an issue" step in
4-
// .github/workflows/pr-checklist.yml. It lives here rather than inline in the workflow YAML so it
5-
// can be unit tested - the same job runs changelog-ref-gate.test.js before the gate, so a
6-
// regression here fails the PR Checklist rather than silently misjudging changelogs.
4+
// .github/workflows/repo-hygiene.yml (the `repo: hygiene` job, where the former PR Checklist steps
5+
// now live). It lives here rather than inline in the workflow YAML so it can be unit tested - the
6+
// same job runs changelog-ref-gate.test.js before the gate, so a regression here fails the required
7+
// check rather than silently misjudging changelogs.
78
//
89
// This is a reminder for ourselves, not a defence against someone gaming it. Where being exactly
910
// right would need real cleverness, it takes the simple option and says so: a check nobody can

.github/scripts/changelog-ref-gate.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2026 Antony Stubbs and contributors
22

3-
// Unit tests for changelog-ref-gate.js, run by the PR Checklist job before the gate itself.
3+
// Unit tests for changelog-ref-gate.js, run by the `repo: hygiene` job before the gate itself.
44
// Plain node, no dependencies, no runner: `node .github/scripts/changelog-ref-gate.test.js`.
55
// Exits non-zero on the first sign of trouble, so a broken gate fails CI loudly.
66

.github/scripts/file-ref-gate.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ function citationsIn(line) {
268268

269269
/**
270270
* The oracle resolves() reads, built from `git ls-files`. It lives here because BOTH callers need
271-
* one - the CI job in pr-checklist.yml and bin/check-file-refs.sh - and two hand-copied versions are
271+
* one - the CI gate in repo-hygiene.yml and bin/check-file-refs.sh - and two hand-copied versions are
272272
* how they would come to disagree about what exists, which is the single thing they cannot differ
273273
* on. Same reasoning that puts formatFailure here rather than at each call site.
274274
*
@@ -483,7 +483,7 @@ function newFindings(current, base) {
483483

484484
/**
485485
* The single copy of what an author is told when either rule fires - rendered by both callers, the
486-
* CI job in pr-checklist.yml and the local bin/check-file-refs.sh, so the two cannot tell different
486+
* CI gate in repo-hygiene.yml and the local bin/check-file-refs.sh, so the two cannot tell different
487487
* stories. Its sibling gate learned that the hard way: hand-written copies of one message disagreed
488488
* in both directions within hours of the second being written.
489489
*/

.github/scripts/file-ref-gate.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2026 Antony Stubbs and contributors
22

3-
// Unit tests for file-ref-gate.js. Run by the PR Checklist job before the gate itself, so a broken
3+
// Unit tests for file-ref-gate.js. Run by the `repo: hygiene` job before the gate itself, so a broken
44
// rule fails loudly rather than silently passing - or failing - every PR.
55
//
66
// The cases that matter most here are the NEGATIVE ones. This gate's failure mode is not missing a

.github/scripts/issue-ref-gate.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ function prBodyEntry(body) {
296296

297297
/**
298298
* The single copy of what an author is told when the gate fires. Both callers render this - the CI
299-
* job in pr-checklist.yml and the local bin/check-issue-refs.sh - so the two cannot tell different
299+
* gate in repo-hygiene.yml and the local bin/check-issue-refs.sh - so the two cannot tell different
300300
* stories. They did exactly that once: hand-written copies disagreed in *both* directions within
301301
* hours of the second one being created, each carrying a correction the other lacked. The script's
302302
* own header already says "NO SECOND COPY OF THE RULE" about the matching logic; the message an

.github/scripts/issue-ref-gate.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2026 Antony Stubbs and contributors
22

3-
// Unit tests for issue-ref-gate.js. Run by the PR Checklist job before the gate itself, so a
3+
// Unit tests for issue-ref-gate.js. Run by the `repo: hygiene` job before the gate itself, so a
44
// broken rule fails loudly rather than silently passing - or failing - every PR.
55
const assert = require("assert");
66
const {

.github/scripts/roadmap-stage-gate.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2026 Antony Stubbs and contributors
22

3-
// Unit tests for roadmap-stage-gate.js. Run by the PR Checklist job before the gate itself, so a
3+
// Unit tests for roadmap-stage-gate.js. Run by the `repo: hygiene` job before the gate itself, so a
44
// broken rule fails loudly rather than silently passing - or failing - every PR.
55
// issue-refs: exempt-file - fixtures and check names are deliberately full of bare PR numbers;
66
// qualifying them would stop testing what the parser actually sees.

0 commit comments

Comments
 (0)