fix(stream): key stream metadata by namespace-qualified name (#46) - #48
Merged
Conversation
This was referenced Aug 29, 2026
oreofeolurin
force-pushed
the
fix/46-stream-metadata-namespace
branch
2 times, most recently
from
August 30, 2026 09:35
964db19 to
55eba9a
Compare
Stream metadata — partition count and all three retention settings — was keyed
by the bare stream name while `stream_names` was already keyed by the
namespace-qualified one. Two namespaces holding a same-named stream therefore
shared a single metadata entry, and creating the second silently rewrote the
first's configuration:
flo stream create solo --partitions 4 -n ns1 # info: Partitions: 4
flo stream create solo --partitions 1 -n ns2
flo stream info solo -n ns1 # Partitions: 1
Partition count drives routing, so a tenant could re-route another tenant's
stream by picking the same name, with no error and no log line. Retention
collided identically, letting one namespace shorten another's and delete its
data.
Metadata is now qualified at every read and write, matching the name registry.
Two distinct read paths needed it, not one. Qualifying the key fixed
`stream info`, but `stream list` still reported the wrong partition count: it
strips the namespace prefix before looking metadata back up, and it is served
by the ShardWalker (`serializeWalkStreamNames`) rather than by `handleList`.
Both serializers now take the namespace and re-qualify — the same shape
`queue_list`, `processing_list` and `action_list` already use.
`deleteStream` removes the qualified key and still sweeps the raw one, so
entries written by earlier builds do not leak.
Three e2e tests cover partition count via `info`, partition count via `list`
(the separate path), and retention. All three fail against the unfixed code.
test-unit and test-integration pass. test-e2e: 576/580, the 4 failures being
the `kv/cluster` set that fails identically on a stashed baseline.
oreofeolurin
force-pushed
the
fix/46-stream-metadata-namespace
branch
from
August 30, 2026 13:16
55eba9a to
3e6c091
Compare
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.
Fixes #46. Found while verifying #42 items 2/3.
The bug
Stream metadata — partition count plus all three retention settings — was keyed by the bare stream name, while
stream_nameswas already keyed by the namespace-qualified one. Two namespaces holding a same-named stream shared a single metadata entry, so creating the second silently rewrote the first's configuration:Partition count drives routing, so a tenant could re-route another tenant's stream just by picking the same name — no error, no log line. Retention collided the same way, letting one namespace shorten another's and delete its data.
The fix
Metadata is qualified at every read and write, matching what the name registry already does.
Two distinct read paths needed it, not one. Qualifying the key fixed
stream info, butstream liststill reported the wrong count — it strips the namespace prefix before looking metadata back up, and it's served by the ShardWalker (serializeWalkStreamNames), not byhandleList. Both serializers now take the namespace and re-qualify, the same shapequeue_list,processing_listandaction_listalready use. I'd have shipped a half-fix if I'd only checkedinfo.deleteStreamremoves the qualified key and still sweeps the raw one, so entries written by earlier builds don't leak.Verified
Tests
Three e2e tests: partition count via
info, partition count vialist(the separate path), and retention isolation. All three fail against the unfixed code.test-unit✅ ·test-integration✅test-e2e576/580 — the 4 failures are thekv/clusterset, confirmed failing identically on a stashed baseline.Note on stacking
Branched off
dev, independent of #45 and #47. It touchessrc/stream/handler.zignear #45'shandleInfochange, so expect a small conflict depending on merge order — happy to rebase whichever lands second.