Skip to content

Both languages read the same values of TS_META_ADDR as no metaserver - #1343

Merged
bjmeetsfo merged 2 commits into
mainfrom
both-languages-read-the-same-sentinels
Sep 8, 2026
Merged

Both languages read the same values of TS_META_ADDR as no metaserver#1343
bjmeetsfo merged 2 commits into
mainfrom
both-languages-read-the-same-sentinels

Conversation

@bjmeetsfo

Copy link
Copy Markdown
Collaborator

storage_backend::single_node says of itself:

This is the one implementation of that rule. The datanode decides whether to register with a
metaserver from it … A second copy would let the name in the log drift away from the topology
it claims to describe, which is the failure this function exists to make impossible.

There is a second copy. matrixark_deployment_plan.META_SENTINELS is the same five values of
TS_META_ADDR in python — "", local, none, standalone, off — and nothing compared
them. The python test checks that list against itself, and no test under tools/ mentioned the
rust constant at all
, so the two could drift in either direction without a word.

Drift here is not hypothetical

It already happened, in the other direction. matrixark_rust_proxy_impl::open_remote_store
re-derived the rule with is_empty() and got a narrower answer, so a one-box — which sets
TS_META_ADDR=local — handed "local" to the client as a literal socket address:

record_log_remote_execute_failed: http error: io error: invalid socket address

Every write failed, 123,435 of them in one soak, while the sample column read all zeros. That
call site now routes through single_node() and carries the incident in a comment. This checks
the copy that is left — the one in another language, where the compiler cannot help.

What it pins

  • The two lists hold the same values. The rust side is read out of the source (it cannot be
    imported from tools/), including its [&str; N] length annotation, so a list that grew
    without the annotation being updated is caught rather than silently trimmed.
  • Normalisation, on both sides. The list is only half the rule: rust compares
    value.trim().to_ascii_lowercase() and python compares _clean(...).lower(), so " Local "
    is a sentinel to both. Either side losing that is the same failure as either list changing —
    a value one side calls standalone and the other hands over as an address.

The python half is driven, not read: is_standalone() is called with the spellings a unit
file or a heredoc actually leaves (" local ", "LOCAL", "\tOff\n", "None",
"Standalone").

It discriminates

Checked by perturbing each side and watching it fail, then restoring:

  • a sixth spelling added to the rust list alone → fails, printing both lists;
  • .trim().to_ascii_lowercase() removed from the rust comparison → fails naming that.

There is a positive control (10.0.0.4:17001 must still read as a real address), without which
every other assertion would pass against a function that answered "standalone" to everything.
And the readability of the constant is asserted first, since the comparisons would otherwise pass
on an empty tuple.

The normalisation check searches with re.search rather than assertRegex, whose failure
message prints the whole haystack — 45 KB of storage_backend.rs to report that one line moved.

No production code changes.

🤖 Generated with Claude Code

storage_backend::single_node calls itself the one implementation of that rule, and there is a
second copy: matrixark_deployment_plan.META_SENTINELS holds the same five values in python.
Nothing compared them - the python test checks that list against itself and no test under tools/
mentioned the rust constant at all.

Drift already happened in the other direction: open_remote_store re-derived the rule with
is_empty(), so a one-box setting TS_META_ADDR=local handed "local" to the client as a literal
socket address and every write failed. This pins the copy that is left, in the language the
compiler cannot check, and pins normalisation on both sides because the list is only half the
rule. Verified to fail on a sixth spelling added to one list and on the trim/lowercase being
removed, with a positive control so it cannot pass against a function that answers standalone to
everything.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bjmeetsfo
bjmeetsfo merged commit ed78a47 into main Sep 8, 2026
7 checks passed
@bjmeetsfo
bjmeetsfo deleted the both-languages-read-the-same-sentinels branch September 8, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants