Skip to content

Commit 817ddee

Browse files
committed
fix: pin wire format version at 1 until 1.0
Pre-1.0 there are no deployed clusters and MIN_WIRE_FORMAT_VERSION equals WIRE_FORMAT_VERSION, so every wire-version feature gate is unconditionally true or false inside any cluster that can actually form — bumping the version only invents a fake rolling-upgrade requirement. Reset WIRE_FORMAT_VERSION and the rolling-upgrade gate constants to 1, and drop the now-dead TENANT_ADMIN_ATOMIC_VERSION gate and its check in favor of always allowing the atomic tenant-creation path.
1 parent 8c1d7ca commit 817ddee

4 files changed

Lines changed: 56 additions & 38 deletions

File tree

nodedb-types/src/wire_version.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,42 @@
1010
//! `nodedb_cluster::rpc_codec::header` (a private constant of that
1111
//! module).
1212
//!
13-
//! Bump this when the SPSC bridge, WAL, or RPC payload schemas change
14-
//! in a way that requires a coordinated upgrade. Readers MUST reject
15-
//! messages stamped with a version other than their own.
13+
//! # DO NOT BUMP THIS BEFORE 1.0
14+
//!
15+
//! It stays at `1` until the first stable release. Read this before
16+
//! changing it — the reflex to bump on any wire-shape change is wrong here:
17+
//!
18+
//! - **There is nothing to be compatible with.** Pre-1.0 there are no
19+
//! deployed clusters, so there is no older peer a new build must talk to.
20+
//! - **A bump cannot buy a rolling upgrade.** `MIN_WIRE_FORMAT_VERSION ==
21+
//! WIRE_FORMAT_VERSION` (floor == ceiling), so a node rejects *any* peer
22+
//! whose version differs. Mixed-version clusters cannot form at all, which
23+
//! makes every `wire_version >= V` feature gate dead code: inside a cluster
24+
//! that exists, all nodes are provably on this exact version. Adding such a
25+
//! gate is unreachable-branch hardening, not safety.
26+
//! - **This value is NOT persisted.** It is stamped on `NodeInfo` for the
27+
//! handshake and drives `ClusterVersionView`, nothing more. The version
28+
//! written into stored raft-log and metadata entries is
29+
//! `nodedb_cluster::wire_version::WireVersion::CURRENT`, which is separate
30+
//! and independent. Changing the constant here therefore cannot orphan or
31+
//! corrupt anything already on disk.
32+
//!
33+
//! So: adding a new enum variant, RPC, or payload field needs NO bump. Every
34+
//! node in a working cluster runs the same build by construction. Ratcheting
35+
//! this pre-1.0 only invents a stop-the-world upgrade requirement that does
36+
//! not otherwise exist, and would leave 1.0 shipping as "wire version 20" for
37+
//! no reason.
38+
//!
39+
//! After 1.0, when real deployments exist and a genuine compatibility window
40+
//! is introduced, this becomes meaningful — bump it then, deliberately, and
41+
//! only alongside an actual `MIN_WIRE_FORMAT_VERSION < WIRE_FORMAT_VERSION`
42+
//! support window.
1643
1744
/// Cluster-wide wire format version. Stamped on every `NodeInfo` and
1845
/// returned by `nodedb::version::WIRE_FORMAT_VERSION` (a re-export).
19-
pub const WIRE_FORMAT_VERSION: u16 = 8;
46+
///
47+
/// WARNING: pinned at 1 until 1.0. See the module docs above before changing.
48+
pub const WIRE_FORMAT_VERSION: u16 = 1;
2049

2150
/// Minimum wire format version this build can read. Equal to
2251
/// `WIRE_FORMAT_VERSION`: floor == ceiling, no backward compat window.

nodedb/src/control/metadata_proposer.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,6 @@ pub fn propose_catalog_entry_with_timeout(
139139
return Ok(0);
140140
};
141141

142-
if matches!(entry, CatalogEntry::PutTenantWithAdmin { .. }) {
143-
let versions = shared.cluster_version_view();
144-
let required = crate::control::rolling_upgrade::TENANT_ADMIN_ATOMIC_VERSION;
145-
if !versions.can_activate_feature(required) {
146-
return Err(Error::VersionCompat {
147-
detail: format!(
148-
"CREATE TENANT requires every cluster node at wire version {required} or \
149-
newer (minimum observed {})",
150-
versions.min_version
151-
),
152-
});
153-
}
154-
}
155-
156142
// Rolling-upgrade gate: until every node in the cluster reports
157143
// at least `DISTRIBUTED_CATALOG_VERSION`, fall back to the legacy
158144
// direct-write path on the originating node. Mixing the

nodedb/src/control/rolling_upgrade/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ pub mod view;
2323

2424
pub use versions::{
2525
DESCRIPTOR_DRAIN_VERSION, DESCRIPTOR_VERSIONING_VERSION, DISTRIBUTED_CATALOG_VERSION,
26-
TENANT_ADMIN_ATOMIC_VERSION, accept_message, should_compat_mode,
26+
accept_message, should_compat_mode,
2727
};
2828
pub use view::{ClusterVersionView, compute_from_topology};

nodedb/src/control/rolling_upgrade/versions.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ use super::view::ClusterVersionView;
99
#[cfg(test)]
1010
use crate::version::WIRE_FORMAT_VERSION;
1111

12+
// PRE-1.0: every gate below is pinned to 1, the value of
13+
// `WIRE_FORMAT_VERSION`, so each feature is unconditionally active.
14+
//
15+
// `MIN_WIRE_FORMAT_VERSION == WIRE_FORMAT_VERSION` (floor == ceiling), so a
16+
// node rejects any peer whose version differs and a mixed-version cluster can
17+
// never form. Inside a cluster that exists, every node is therefore on this
18+
// exact version, which makes `min_version >= V` constant-true for any
19+
// `V <= WIRE_FORMAT_VERSION` and constant-false above it. These gates cannot
20+
// discriminate, so a value above 1 does not protect a rolling upgrade — it just
21+
// switches the feature OFF permanently and silently routes to a legacy
22+
// fallback.
23+
//
24+
// Do NOT raise these while `WIRE_FORMAT_VERSION` is 1 (see
25+
// `nodedb_types::wire_version` for why it stays there until 1.0). The gate
26+
// machinery is kept, not deleted, because it becomes meaningful the moment a
27+
// real support window (`MIN_WIRE_FORMAT_VERSION < WIRE_FORMAT_VERSION`) is
28+
// introduced post-1.0 — at which point these regain their original meanings,
29+
// recorded below.
30+
1231
/// Wire-format version that introduced the replicated catalog DDL
1332
/// path (`CatalogEntry` proposed via the metadata raft group).
1433
///
@@ -20,7 +39,7 @@ use crate::version::WIRE_FORMAT_VERSION;
2039
/// [`ClusterVersionView::can_activate_feature`] and falls back to
2140
/// the legacy direct-write path until every node in the cluster
2241
/// has caught up.
23-
pub const DISTRIBUTED_CATALOG_VERSION: u16 = 2;
42+
pub const DISTRIBUTED_CATALOG_VERSION: u16 = 1;
2443

2544
/// Wire-format version that introduced monotonic descriptor
2645
/// versioning (`descriptor_version: u64` + `modification_hlc: Hlc`
@@ -35,18 +54,13 @@ pub const DISTRIBUTED_CATALOG_VERSION: u16 = 2;
3554
/// `descriptor_version == 0` as "unknown, always re-fetch". Once
3655
/// every node reports `wire_version >= 3`, the applier transitions
3756
/// to stamping.
38-
pub const DESCRIPTOR_VERSIONING_VERSION: u16 = 3;
57+
pub const DESCRIPTOR_VERSIONING_VERSION: u16 = 1;
3958

4059
/// Wire version that introduced the replicated
4160
/// `DescriptorDrainStart` / `DescriptorDrainEnd` metadata entries.
4261
/// Mixed-version clusters below this version skip drain via the
4362
/// compat-mode fallback in `drain_for_ddl`.
44-
pub const DESCRIPTOR_DRAIN_VERSION: u16 = 4;
45-
46-
/// Wire version that introduced the atomic `PutTenantWithAdmin` catalog entry.
47-
/// Older appliers cannot decode this enum variant, so tenant creation must be
48-
/// rejected rather than sent or downgraded while any node is below this gate.
49-
pub const TENANT_ADMIN_ATOMIC_VERSION: u16 = 8;
63+
pub const DESCRIPTOR_DRAIN_VERSION: u16 = 1;
5064

5165
/// Check if a message from a remote node should be accepted.
5266
///
@@ -85,15 +99,4 @@ mod tests {
8599
assert!(accept_message(WIRE_FORMAT_VERSION - 1).is_err());
86100
}
87101
}
88-
89-
#[test]
90-
fn atomic_tenant_admin_requires_the_current_cluster_version() {
91-
assert_eq!(TENANT_ADMIN_ATOMIC_VERSION, WIRE_FORMAT_VERSION);
92-
let mut mixed = ClusterVersionView::single_node();
93-
mixed.min_version = WIRE_FORMAT_VERSION - 1;
94-
assert!(!mixed.can_activate_feature(TENANT_ADMIN_ATOMIC_VERSION));
95-
assert!(
96-
ClusterVersionView::single_node().can_activate_feature(TENANT_ADMIN_ATOMIC_VERSION)
97-
);
98-
}
99102
}

0 commit comments

Comments
 (0)