Repository navigation
fix(mq): drain partitions a lower N leaves; quiet close - #644
Merged
EricAndrechek merged 2 commits intoSep 29, 2026
Merged
Conversation
ExternalNATS's worker consumed only partitions 0..N-1, so rows left in a partition an operator removed by lowering mq.nats.partitions were never written, while the verifier's finding said they were drained. It now also consumes, through wh-ingest, every stream holding ingest subjects outside the N partitions, and the operator deleting one once it is empty ends only that stream's delivery. The finding counts the stream's rows and says when it has no durable to drain it. Close logged "disconnected from nats; reconnecting" at WARN with a nil error; a deliberate close now logs nothing, a lost server still warns. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJr5tY4WQUy2sc4MbW67vL
Review round 1: the shrink test keeps the old-N process publishing during the rollout and waits for the removed partition's delivery to end; the split of prefetch counts only the N partitions; the docs say how to delete a drained stream under preventDelete and qualify the other 'durable deleted ends the worker' claims. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJr5tY4WQUy2sc4MbW67vL
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #613. Fixes two defects in
ExternalNATSthat D4 (#639) found. Base:feat/mq-nats-wiring(#639), so review after #636 and #639.1. A deliberate close logged a WARN
ExternalNATS.Closeloggedmq: disconnected from nats; reconnectingat WARN witherror=null. This was measured in D4's integration run. The cause is that nats.go calls the disconnect callback fromClose/Drainwith a nil error.Closenow sets aclosingflag before it drains, and the callback does not warn once that flag is set. A real disconnect still warns.2. Rows in removed partitions were never drained
D2's verifier said that streams outside the N partitions were "drained until the operator deletes them". D3's
CreateConsumeronly consumed partitions0..N-1, and deployment.md told operators to stop ingest before lowering N.Choice: (a), drain them.
CreateConsumernow also bindswh-ingeston every stream that holds<prefix>.ingest.>subjects outside the N partitions, and consumes it beside the partitions.Why (a) and not (b), refusing to boot while an extra partition holds rows:
preventDelete, so the stream and its durable outlive their removal from the manifests. Nothing is lost unless the operator deletes a partition that still holds rows, and deleting any partition that holds rows already loses them.Details:
failed, so the worker keeps running. Client errors on an extra's delivery are logged at INFO too, because they are expected once the operator deletes it. An extra with no pullwh-ingestdurable, or one already gone, is skipped.extraPartitions, still recommended) now counts the stream's rows. It also says when the stream has no durable, so nothing drains it. With interest retention, rows with no durable have already been dropped by the server, unless some other consumer still holds them (inferred from nats-server's cleanup when a consumer is deleted, not tested).Tests
TestExternalNATS_CloseLogsNoWarning(integration, serial because it captures the default logger). It closes a broker that has a running consumer and a hub subscription, and asserts nothing was logged at WARN or above. It then stops the server and asserts that another broker still warns. It fails on the base with the nil-error WARN (measured).TestExternalNATS_LoweringNDrainsTheRemovedPartition(integration, serial). Steps:wavehouse mq manifests --partitions 2.natstest.Manifests.Apply(create-or-update, as nack does).WH_INGEST_1withdrains its 5 rows.WH_INGEST_1then empties.failedstays quiet, and partition 0 keeps delivering.The earlier version of this test fails on the base with a 15s receive timeout (measured).
TestVerifyNATSTopology_Findings: the extra-partition case checks the new text, plus a new case for an extra partition without its durable.Evidence
make ci(queued,GOTOOLCHAIN=go1.26.6) was green on 6d42f5a. Coverage: unit 93.5%, integration 56.9%, e2e 60.8%, Go total 94.3%.internal/mqunit package's 15s timeout under heavy load; the running test was 2s in, so it was not a hang.make build-docspasses.TestEmbeddedNATS_PacesTheRetriesOfAQueueThatCannotOpenfailed 9 of 10 runs with-count=10on a cleanorigin/feat/mq-nats-wiringcheckout (measured). The error isopen …/streams/DLQ_acme: invalid argument/no such file or directory. It passed on its own inside the greenmake ci.pre-push-reviewer(opus):docs-reviewer(opus):preventDelete. Now fixed.Expected conflicts
feat/coord-nats-kv) adds a KV bucket to the topology spec, the verifier and the manifests. This PR'snats_topology.goedit is confined to the body ofextraPartitionsand its doc comment. A conflict is only likely if B2 touchesextraPartitionsor the lines right around it. B2 may also add a stream that holds subjects under<prefix>.ingest.>; it should not, or the new drain would treat it as an extra partition.natstest/natstest.go: a newManifests.Applymethod, added betweenCreateandAwaitSources. It merges trivially unless B2 edits the same spot.Left to later PRs
Sharded, partition claiming): extras need an owner there too. The simplest option is that every claimant drains every extra, since extras are temporary.CreateConsumer. That is fine, because an extra appears only when N changes, which requires a restart.🤖 Generated with Claude Code
https://claude.ai/code/session_01EJr5tY4WQUy2sc4MbW67vL