Skip to content

refactor(mesh): remove v1 mesh from gateway and public API - #1476

Merged
CatherineSue merged 5 commits into
mainfrom
refactor/mesh-v1-removal
May 13, 2026
Merged

CatherineSue merged 5 commits into
mainfrom
refactor/mesh-v1-removal

Conversation

@CatherineSue

@CatherineSue CatherineSue commented May 12, 2026 •

Copy link
Copy Markdown
Member

Description

Problem

The v1 mesh sync stack (MeshSyncManager, TreeOperation, TreeState, WorkerStateSubscriber, TreeStateSubscriber, …) was the original gateway↔cluster bridge. It is now superseded by the v2 TreeSync / WorkerSync / RateLimitSync adapters layered on top of MeshKV's typed CRDT/stream namespaces. The two paths have coexisted while v2 baked; that's over.

Leaving v1 in place blocks the next round of work: redesigning the e2e integration (topology / service_discovery.rs, gossip dispatch in controller.rs / ping_server.rs / node_state_machine.rs) without dragging the legacy types and admin surface along.

Solution

This is the first PR in a short sequence:

  1. (this PR) Rip v1 out of the gateway and drop the v1 public API surface from smg-mesh. Mesh-internal modules that still reference v1 types remain as private mod declarations during the transition.
  2. (follow-up) Redesign the topology / service_discovery / gossip dispatch and delete the now-orphaned v1 modules from smg-mesh.

The gateway loses every v1 caller, the routers/mesh/* admin endpoints, the global-rate-limit gate in the concurrency middleware, and the v1 mesh integration test. The v2 WorkerSyncAdapter keeps using WorkerRegistry::on_remote_worker_state, which survives as an inherent method (was previously the WorkerStateSubscriber trait impl).

Changes

Gateway

  • model_gateway/src/server.rs — drop the mesh_routes admin tree, start_rate_limit_task wiring, and mesh_handler-driven set_mesh_sync / register_worker_state_subscriber.
  • model_gateway/src/middleware/concurrency.rs — drop the MeshSyncManager::check_global_rate_limit gate. Cluster-wide rate limiting will return via the v2 RateLimitSyncAdapter.
  • model_gateway/src/worker/registry.rs — drop the OptionalMeshSyncManager field, set_mesh_sync, all sync_worker_state / remove_worker_state calls, and the v1 WorkerStateSubscriber impl. The remote-apply method on_remote_worker_state is kept as an inherent method (v2 WorkerSyncAdapter calls it).
  • model_gateway/src/policies/{mod,registry,cache_aware}.rs — drop the mesh_sync field on PolicyRegistry / CacheAwarePolicy and every sync_tree_insert_hash / sync_tree_operation / apply_remote_tree_* / apply_tenant_delta / export_tree_state / restore_tree_state_from_mesh hook. apply_repair_page (the v2 cold-start path) and the populate-site hash_index are kept; a repurposed test_apply_known_remote_insert_round_trip now seeds via apply_repair_page.
  • model_gateway/src/routers/mesh/{mod,handlers}.rs — delete (admin endpoints for cluster_status, ha/*, app_config, …).
  • model_gateway/tests/mesh_integration_test.rs — delete; exercised only the v1 sync manager surface.

smg-mesh

  • Stop re-exporting MeshSyncManager, StateStores, TreeOperation, TreeState, TreeInsertOp, TreeKey, TenantInsert, TenantEvict, WorkerStateSubscriber, TreeStateSubscriber, AppState, MembershipState, PolicyState, RateLimitConfig, GLOBAL_RATE_LIMIT_KEY / _COUNTER_KEY, OptionalMeshSyncManager.
  • Add crates/mesh/src/hash.rs (hash_node_path, hash_token_path, GLOBAL_EVICTION_HASH) and crates/mesh/src/types.rs (WorkerState) so the still-needed pieces survive the upcoming v1 file deletion. stores.rs re-exports WorkerState from types.rs so there is a single canonical type during the transition.
  • Delete crates/mesh/benches/mesh_serialization.rs (benched the v1 TreeState codec).

Scope explicitly deferred to the follow-up PR

  • Deleting sync.rs / stores.rs / tree_ops.rs / collector.rs / consistent_hash.rs / rate_limit_window.rs. They're still referenced internally by gossip dispatch (controller.rs, ping_server.rs, node_state_machine.rs); deleting them requires the topology redesign.

Test Plan

Ran against the worktree (/Users/chang/opensource/smg-v1-removal) after the cut:

  • cargo +nightly fmt --check passes
  • cargo clippy --all-targets -p smg -p smg-mesh passes (no warnings)
  • cargo test -p smg --lib — 835 passed, 4 ignored
  • cargo test -p smg-mesh --lib — 262 passed, 2 ignored
  • cargo test -p smg --lib policies::cache_aware::tests — 21 / 21 (incl. v2 apply_repair_page and apply_known_remote_insert_* paths)
  • cargo test -p smg --lib policies::registry::tests — 3 / 3
  • cargo test -p smg --lib worker::registry::tests — 19 / 19
  • cargo test -p smg --lib mesh::adapters — 62 / 62 (worker_sync round-trip + tree_sync repair + rate_limit_sync backfill still green)
Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated
  • (Optional) Please join us on Slack #sig-smg to discuss, review, and merge PRs

Summary by CodeRabbit

  • New Features

    • Added stable 8-byte hashing utilities for node/token identification.
    • Introduced a serializable WorkerState value type for mesh worker info.
  • Bug Fixes

    • Removed cluster-wide global rate-limit enforcement from middleware; local token-bucket limiting remains.
  • Removals

    • Removed v1 mesh cluster management HTTP endpoints and related sync wiring.
    • Removed mesh serialization benchmarks, multi-node integration tests, and the CI benchmark workflow.

@coderabbitai

coderabbitai Bot commented May 12, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Removes v1 mesh synchronization and HA HTTP surface from model_gateway, consolidates mesh crate exports, adds a stable 8-byte hashing module and a shared serde WorkerState type (without Eq/Hash), replaces push-based mesh sync hooks with an inbound on_remote_worker_state handler, and deletes Criterion benches and the benchmark CI workflow.

Changes

Mesh crate: hashing, wire types, and re-exports

Layer / File(s) Summary
Stable 8-byte hashing utilities
crates/mesh/src/hash.rs
Adds GLOBAL_EVICTION_HASH sentinel and two Blake3-based functions hash_node_path(&str) -> u64 and hash_token_path(&[u32]) -> u64. Both remap computed-zero to 1. Includes unit tests for determinism and sentinel remapping.
WorkerState mesh-wire type
crates/mesh/src/types.rs
Introduces pub struct WorkerState as a serde-serializable wire type with worker_id, model_id, url, health, load: f64, version, and spec: Vec<u8> (defaulted for compatibility). Module docs note Eq/Hash are intentionally omitted due to f64 NaN semantics.
Re-export consolidation and manifest change
crates/mesh/src/lib.rs, crates/mesh/src/stores.rs, crates/mesh/src/sync.rs, crates/mesh/src/tree_ops.rs, crates/mesh/Cargo.toml
Adds mod hash;, re-exports hashing utilities from hash, moves WorkerState export to types, removes the OptionalMeshSyncManager alias, removes many prior public re-exports, and drops the criterion dev-dependency from Cargo.toml.

Model Gateway: removal of v1 mesh sync and HA admin surface

Layer / File(s) Summary
HA / mesh HTTP handlers and router removal
model_gateway/src/routers/mesh/handlers.rs, model_gateway/src/routers/mesh/mod.rs, model_gateway/src/routers/mod.rs
Deletes the mesh handlers module (cluster health/status, worker/policy state endpoints, app config, global rate-limit endpoints, graceful-shutdown endpoint) and removes the mesh router from public routers.
Policy registry & worker registry unwiring
model_gateway/src/policies/mod.rs, model_gateway/src/policies/registry.rs, model_gateway/src/worker/registry.rs
Removes set_mesh_sync APIs, drops PolicyRegistry mesh-sync state and TreeStateSubscriber wiring. WorkerRegistry removes outgoing mesh forwarding and set_mesh_sync, and adds an inherent pub fn on_remote_worker_state(&self, state: &smg_mesh::WorkerState) to accept inbound mesh worker updates.
CacheAwarePolicy local-only updates and tests
model_gateway/src/policies/cache_aware.rs
Removes mesh_sync field and all mesh-facing apply/export methods. Cache-update and routing paths now update local trees and hash_index only. Mesh-dependent tests removed or rewritten to seed state locally (apply_repair_page).
Server, middleware, adapters, tests, and CI cleanup
model_gateway/src/server.rs, model_gateway/src/middleware/concurrency.rs, model_gateway/src/mesh/adapters/worker_sync.rs, model_gateway/tests/mesh_integration_test.rs, .github/workflows/benchmark-mesh-serialization.yml
Removes HA/mesh route construction and v1 mesh-startup wiring, deletes the global-rate-limit check from concurrency middleware, adjusts worker_sync docs/imports, removes the mesh integration test suite, and deletes the Criterion benchmark workflow.

Sequence Diagram(s)

(omitted — change is a broad removal/refactor across many components; no new multi-component sequential control flow to visualize)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

ci, mesh

Suggested reviewers

  • tonyluj
  • llfl
  • slin1237
  • key4ng

Poem

🐰
I hopped through crates and trimmed the mesh,
Benches gone, the hashes now enmesh;
WorkerState tucked in one shared place,
Incoming updates find their new embrace,
A tidy burrow, light and fresh.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely describes the primary change: removing v1 mesh components from the gateway and public API, which aligns with the main objective of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/mesh-v1-removal

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added dependencies Dependency updates tests Test changes model-gateway Model gateway crate changes mesh Mesh crate changes labels May 12, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the mesh networking layer by removing legacy "v1" synchronization logic and the MeshSyncManager hooks from the gateway. Key changes include moving shared value types like WorkerState to a new types module, introducing a hash module for stable content hashing, and deleting the v1 management HTTP routes and integration tests. Feedback focuses on the safety of the Eq implementation for types containing floats and an optimization to avoid intermediate allocations during token hashing.

Comment thread crates/mesh/src/types.rs Outdated
// Manual Eq via the derived PartialEq; the f64 comparison is
// bitwise via `PartialEq`, which is acceptable because the
// gateway either advertises a deterministic value or zero.
impl Eq for WorkerState {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Implementing Eq for a struct containing f64 is problematic because f64 does not satisfy the reflexivity requirement of Eq (specifically, NaN != NaN). If WorkerState.load ever becomes NaN, this implementation will violate the Eq trait contract, which can lead to logic errors or panics in collections that rely on it. Additionally, the comment on line 32 mentions an "epsilon discipline" for equality, but the struct uses derived PartialEq which performs standard float comparison. Consider using a wrapper type like ordered_float or removing the Eq implementation if it's not strictly required.

Comment thread crates/mesh/src/hash.rs Outdated
Comment on lines +38 to +40
pub fn hash_token_path(tokens: &[u32]) -> u64 {
let bytes: Vec<u8> = tokens.iter().flat_map(|t| t.to_le_bytes()).collect();
let hash = blake3::hash(&bytes);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The hash_token_path function currently allocates a Vec<u8> to store the byte representation of all tokens before hashing. For large requests (e.g., 32K tokens), this results in a ~128KB intermediate allocation. Since blake3::Hasher supports incremental updates, you can avoid this allocation by updating the hasher directly in a loop.

pub fn hash_token_path(tokens: &[u32]) -> u64 {
    let mut hasher = blake3::Hasher::new();
    for t in tokens {
        hasher.update(&t.to_le_bytes());
    }
    let hash = hasher.finalize();
    let h = u64::from_le_bytes(hash.as_bytes()[..8].try_into().unwrap());
    if h == GLOBAL_EVICTION_HASH {
        1
    } else {
        h
    }
}
References
  1. When computing hashes from a slice of primitives, avoid unnecessary intermediate allocations by using the streaming interface of the hashing library to write bytes incrementally.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7d9698eab

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1311 to +1314
// v1 mesh sync (set_mesh_sync, WorkerStateSubscriber, TreeStateSubscriber)
// is removed in this PR. State sync across mesh peers is not wired in this
// branch — v2 adapters in `model_gateway/src/mesh/adapters/` are built and
// tested but not yet started from `server.rs`. That wiring lands in a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore mesh adapter wiring during server startup

With mesh enabled, startup now explicitly skips all sync wiring and does not start any v2 adapters, so worker/tree/rate-limit state never replicates across peers. I checked model_gateway/src and the only WorkerSyncAdapter/TreeSyncAdapter/RateLimitSyncAdapter constructions are in adapter test code, so production startup has no inbound or outbound mesh sync path; this breaks multi-node routing/failover behavior until another change lands.

Useful? React with 👍 / 👎.

Comment thread model_gateway/src/middleware/concurrency.rs
Comment thread crates/mesh/src/hash.rs
Comment on lines +14 to +45
pub const GLOBAL_EVICTION_HASH: u64 = 0;

/// Compute a compact 8-byte hash of a prefix path. Returns a
/// non-zero hash; `0` is reserved for [`GLOBAL_EVICTION_HASH`].
#[expect(
clippy::unwrap_used,
reason = "blake3 always returns 32 bytes; [..8] into [u8; 8] cannot fail"
)]
pub fn hash_node_path(path: &str) -> u64 {
let hash = blake3::hash(path.as_bytes());
let h = u64::from_le_bytes(hash.as_bytes()[..8].try_into().unwrap());
if h == GLOBAL_EVICTION_HASH {
1
} else {
h
}
}

/// Compute a compact 8-byte hash of a token-id sequence. Returns
/// a non-zero hash; `0` is reserved for [`GLOBAL_EVICTION_HASH`].
#[expect(
clippy::unwrap_used,
reason = "blake3 always returns 32 bytes; [..8] into [u8; 8] cannot fail"
)]
pub fn hash_token_path(tokens: &[u32]) -> u64 {
let bytes: Vec<u8> = tokens.iter().flat_map(|t| t.to_le_bytes()).collect();
let hash = blake3::hash(&bytes);
let h = u64::from_le_bytes(hash.as_bytes()[..8].try_into().unwrap());
if h == GLOBAL_EVICTION_HASH {
1
} else {
h

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Nit: GLOBAL_EVICTION_HASH, hash_node_path, and hash_token_path are now defined in both hash.rs and tree_ops.rs (lines 86–129) with identical implementations. Internal callers (sync.rs:44, sync.rs:551) still reference crate::tree_ops::GLOBAL_EVICTION_HASH.

This duplication is a maintenance hazard — if someone updates the hash logic in one module, the other silently diverges. Consider having tree_ops.rs re-export from crate::hash instead of carrying its own copy:

// in tree_ops.rs, replace the local definitions with:
pub use crate::hash::{hash_node_path, hash_token_path, GLOBAL_EVICTION_HASH};

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean v1 mesh teardown. One nit flagged (duplicate hash function definitions in hash.rs and tree_ops.rs) — no blocking issues.

Summary: 0 🔴 Important · 1 🟡 Nit · 0 🟣 Pre-existing

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
model_gateway/src/mesh/adapters/worker_sync.rs (1)

97-100: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Tombstones are now dropped, so remote removals never leave the registry.

When one node calls on_worker_removed(), peers hit this None branch and only log it. The imported worker then stays registered and potentially routable on every other gateway until some unrelated local cleanup happens. This PR removes the old path, so a real remote-remove hook needs to land with it or worker deletions stop propagating cluster-wide.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@model_gateway/src/mesh/adapters/worker_sync.rs` around lines 97 - 100, The
None branch in worker_sync.rs currently only logs a tombstone and drops it, so
remote removals never clear the registry; replace the debug-only branch with a
call into the remote-remove handler used locally (invoke the same removal flow
as on_worker_removed or a new
Registry::handle_remote_worker_removal/registry.remove_worker_remote(worker_id)
helper) so the imported worker is actually removed and the removal is propagated
via the existing registry/mesh hooks; ensure you pass worker_id and any mesh
context, update any function signatures invoked (e.g., on_worker_removed) if
needed, and keep logging for success/failure rather than silently dropping the
tombstone.
model_gateway/src/worker/registry.rs (1)

1237-1246: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Differentiate between absent and corrupted specs—don't silently register a fallback worker when spec is present but undecodable.

Empty spec is the old-node compatibility path and safely falls back to the minimal builder. A non-empty decode failure, however, signals corruption or schema drift and should not be hidden. Silent fallback registers a worker with default worker_type, connection_mode, runtime_type, and only the single model_id from state—potentially wrong connection mode, worker type, model set, and other config. This mis-configured worker can then route traffic incorrectly.

💡 Suggested fix
-        let worker = match bincode::deserialize::<openai_protocol::worker::WorkerSpec>(&state.spec)
-        {
-            Ok(spec) if !state.spec.is_empty() => {
-                super::builder::BasicWorkerBuilder::from_spec(spec).build()
-            }
-            _ => super::builder::BasicWorkerBuilder::new(&state.url)
-                .model(ModelCard::new(&state.model_id))
-                .build(),
-        };
+        let worker = if state.spec.is_empty() {
+            super::builder::BasicWorkerBuilder::new(&state.url)
+                .model(ModelCard::new(&state.model_id))
+                .build()
+        } else {
+            match bincode::deserialize::<openai_protocol::worker::WorkerSpec>(&state.spec) {
+                Ok(spec) => super::builder::BasicWorkerBuilder::from_spec(spec).build(),
+                Err(err) => {
+                    tracing::warn!(url = %state.url, %err, "dropping mesh worker with invalid spec");
+                    return;
+                }
+            }
+        };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@model_gateway/src/worker/registry.rs` around lines 1237 - 1246, The code
currently falls back to a minimal worker whenever
bincode::deserialize::<openai_protocol::worker::WorkerSpec>(&state.spec) fails,
which hides the difference between an absent/empty spec and a
corrupted/non-decodable spec; change the logic in the match that constructs the
worker so that: if state.spec is empty keep the existing fallback using
BasicWorkerBuilder::new(&state.url).model(ModelCard::new(&state.model_id)).build(),
but if state.spec is non-empty and deserialization returns Err treat it as a
hard failure (do not silently construct a minimal worker) — surface or return
the error (or skip registration) and include the deserialization error context
referencing WorkerSpec, state.spec, and BasicWorkerBuilder::from_spec so callers
can handle corrupted/spec-schema-drift cases appropriately.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/mesh/src/types.rs`:
- Around line 33-48: WorkerState implements Eq despite having an f64 field
(load) which can be NaN, breaking reflexivity; either validate load on
deserialization or use a non-NaN wrapper before asserting Eq. Fix by adding
runtime validation where WorkerState instances are created from untrusted input
(e.g., in model_gateway::mesh::adapters::worker_sync.rs where
bincode::deserialize::<WorkerState>() is called) to reject or normalize NaN
loads, or replace the f64 load with a guaranteed non-NaN type (or newtype)
inside the WorkerState definition and adjust the impl std::hash::Hash and impl
Eq accordingly so Eq is only implemented for a type that cannot contain NaN.

In `@model_gateway/src/middleware/concurrency.rs`:
- Around line 205-209: The cluster-wide gating was removed (the
MeshSyncManager::check_global_rate_limit call) which causes global limits to
degrade to per-node only; restore cluster enforcement until v2 exists by
reintroducing the MeshSyncManager::check_global_rate_limit invocation in the
same path where local token-bucket logic runs (the concurrency middleware in
concurrency.rs), have it short‑circuit/return an error when the global check
fails, and keep the existing per-node token bucket as a fallback; ensure the
restored call uses the same return/err semantics as prior code and add a
unit/integration test exercising multiple nodes (or a mocked MeshSyncManager) to
prevent regression.

---

Outside diff comments:
In `@model_gateway/src/mesh/adapters/worker_sync.rs`:
- Around line 97-100: The None branch in worker_sync.rs currently only logs a
tombstone and drops it, so remote removals never clear the registry; replace the
debug-only branch with a call into the remote-remove handler used locally
(invoke the same removal flow as on_worker_removed or a new
Registry::handle_remote_worker_removal/registry.remove_worker_remote(worker_id)
helper) so the imported worker is actually removed and the removal is propagated
via the existing registry/mesh hooks; ensure you pass worker_id and any mesh
context, update any function signatures invoked (e.g., on_worker_removed) if
needed, and keep logging for success/failure rather than silently dropping the
tombstone.

In `@model_gateway/src/worker/registry.rs`:
- Around line 1237-1246: The code currently falls back to a minimal worker
whenever
bincode::deserialize::<openai_protocol::worker::WorkerSpec>(&state.spec) fails,
which hides the difference between an absent/empty spec and a
corrupted/non-decodable spec; change the logic in the match that constructs the
worker so that: if state.spec is empty keep the existing fallback using
BasicWorkerBuilder::new(&state.url).model(ModelCard::new(&state.model_id)).build(),
but if state.spec is non-empty and deserialization returns Err treat it as a
hard failure (do not silently construct a minimal worker) — surface or return
the error (or skip registration) and include the deserialization error context
referencing WorkerSpec, state.spec, and BasicWorkerBuilder::from_spec so callers
can handle corrupted/spec-schema-drift cases appropriately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6b42962d-941b-4550-82af-55e084d2d17d

📥 Commits

Reviewing files that changed from the base of the PR and between 0adf360 and a7d9698.

📒 Files selected for processing (18)
  • crates/mesh/Cargo.toml
  • crates/mesh/benches/mesh_serialization.rs
  • crates/mesh/src/hash.rs
  • crates/mesh/src/lib.rs
  • crates/mesh/src/stores.rs
  • crates/mesh/src/sync.rs
  • crates/mesh/src/types.rs
  • model_gateway/src/mesh/adapters/worker_sync.rs
  • model_gateway/src/middleware/concurrency.rs
  • model_gateway/src/policies/cache_aware.rs
  • model_gateway/src/policies/mod.rs
  • model_gateway/src/policies/registry.rs
  • model_gateway/src/routers/mesh/handlers.rs
  • model_gateway/src/routers/mesh/mod.rs
  • model_gateway/src/routers/mod.rs
  • model_gateway/src/server.rs
  • model_gateway/src/worker/registry.rs
  • model_gateway/tests/mesh_integration_test.rs
💤 Files with no reviewable changes (9)
  • model_gateway/src/routers/mesh/mod.rs
  • model_gateway/src/routers/mod.rs
  • crates/mesh/benches/mesh_serialization.rs
  • model_gateway/tests/mesh_integration_test.rs
  • model_gateway/src/policies/mod.rs
  • crates/mesh/src/sync.rs
  • crates/mesh/Cargo.toml
  • model_gateway/src/routers/mesh/handlers.rs
  • model_gateway/src/policies/registry.rs

Comment thread crates/mesh/src/types.rs Outdated
Comment thread model_gateway/src/middleware/concurrency.rs
@github-actions github-actions Bot added the ci CI/CD configuration changes label May 12, 2026
The v1 mesh sync (MeshSyncManager, TreeOperation, TreeState, etc.)
is replaced by the v2 TreeSync / WorkerSync / RateLimitSync adapters
that landed in prior PRs. This PR rips out every gateway-side caller
of v1 and drops the v1 types from the smg-mesh public surface so a
follow-up can redesign the e2e topology / service-discovery without
the legacy weight.

Gateway-side removals:
- `model_gateway/src/server.rs`: drop the mesh_routes admin tree,
  start_rate_limit_task wiring, mesh_handler-driven set_mesh_sync /
  register_worker_state_subscriber.
- `model_gateway/src/middleware/concurrency.rs`: drop the
  `MeshSyncManager::check_global_rate_limit` gate. Cluster-wide
  rate limiting will return via the v2 RateLimitSyncAdapter.
- `model_gateway/src/worker/registry.rs`: drop the OptionalMeshSyncManager
  field, set_mesh_sync, all sync_worker_state / remove_worker_state
  calls, and the v1 `WorkerStateSubscriber` trait impl. The remote-
  apply path (`on_remote_worker_state`) survives as an inherent
  method; the v2 `WorkerSyncAdapter` is its only caller.
- `model_gateway/src/policies/{mod,registry,cache_aware}.rs`: drop
  the mesh_sync field on PolicyRegistry / CacheAwarePolicy and every
  sync_tree_insert_hash / sync_tree_operation / apply_remote_tree_*
  / apply_tenant_delta / export_tree_state / restore_tree_state hook.
  `apply_repair_page`, the v2 cold-start path, is kept as-is and a
  repurposed round-trip test now seeds via that path.
- `model_gateway/src/routers/mesh/`: delete the v1 admin endpoints
  (cluster_status, ha/*, app_config, etc.) wholesale.
- `model_gateway/tests/mesh_integration_test.rs`: delete; covered
  the v1 sync manager surface.

smg-mesh surface:
- Stop re-exporting MeshSyncManager, StateStores, TreeOperation,
  TreeState, TreeInsertOp, TreeKey, TenantInsert, TenantEvict,
  WorkerStateSubscriber, TreeStateSubscriber, AppState, PolicyState,
  MembershipState, RateLimitConfig, GLOBAL_RATE_LIMIT_KEY /
  COUNTER_KEY, OptionalMeshSyncManager.
- Move the still-needed pieces (`hash_node_path`, `hash_token_path`,
  `GLOBAL_EVICTION_HASH`, `WorkerState`) into fresh `hash.rs` and
  `types.rs` modules so they survive the v1 file deletion in the
  follow-up PR.
- Delete `crates/mesh/benches/mesh_serialization.rs`; it benchmarked
  v1 TreeState codec performance.

The legacy v1 modules (sync.rs, stores.rs, tree_ops.rs, collector.rs,
consistent_hash.rs, rate_limit_window.rs) remain as private `mod`
declarations during the transition. The inbound gossip dispatch in
controller.rs / ping_server.rs / node_state_machine.rs still
references their types; deleting that requires gutting the dispatch
loop, which is the topology / service_discovery redesign tracked in
the follow-up PR.

Signed-off-by: Chang Su <8605658+CatherineSue@users.noreply.github.com>
The bench file `crates/mesh/benches/mesh_serialization.rs` was deleted
in the previous commit (it measured v1 `TreeState` codec performance,
which doesn't exist anymore). The workflow that runs it via
`cargo bench --bench mesh_serialization` was left behind and now
fails with `no bench target named mesh_serialization in smg-mesh`.

Signed-off-by: Chang Su <8605658+CatherineSue@users.noreply.github.com>
`WorkerState::load` is `f64`, which can be NaN. NaN violates
`Eq`'s reflexivity (`NaN != NaN`), so `impl Eq for WorkerState`
is unsound and a malicious or buggy peer could trip it by
gossiping a non-finite load. The manual `Hash` impl had the
same root issue (coerced `f64` to `i64`, also load-dependent).

Carried over verbatim from v1 `stores.rs:340`; not introduced
in this PR. No call site in the workspace keys a
`HashMap`/`HashSet` by `WorkerState` or otherwise requires
`Eq`/`Hash` trait bounds, so deletion costs nothing. Derived
`PartialEq` still covers `assert_eq!` in tests and the rare
field-by-field comparison.

Flagged by Gemini and CodeRabbit on PR #1476.

Signed-off-by: Chang Su <8605658+CatherineSue@users.noreply.github.com>
The previous implementation collected all `u32` tokens into a
`Vec<u8>` via `flat_map(|t| t.to_le_bytes()).collect()` before
hashing. At 32K tokens × 4 bytes that's a ~128 KB transient
allocation on every request hot path that calls into the
cache-aware policy.

Switch to `blake3::Hasher::update` per token. Blake3's streaming
construction is mathematically identical to hashing the
concatenated bytes — a regression test (`hash_token_path_matches_concat_then_hash`)
locks in wire-compatibility with hashes already stored in the
CRDT or held by peers running the prior version.

Carried over from v1 `tree_ops.rs:120`; not introduced by this
PR. Flagged by Gemini on PR #1476.

Signed-off-by: Chang Su <8605658+CatherineSue@users.noreply.github.com>
Duplicate definitions of GLOBAL_EVICTION_HASH, hash_node_path,
and hash_token_path lived in both modules. tree_ops.rs now
re-exports from crate::hash so internal v1 call sites
(sync.rs:44, 551) keep resolving while the canonical
implementations stay in one place.

Flagged by Claude on PR #1476.

Signed-off-by: Chang Su <8605658+CatherineSue@users.noreply.github.com>
@CatherineSue
CatherineSue force-pushed the refactor/mesh-v1-removal branch from 219dc5b to dadc884 Compare May 13, 2026 02:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@model_gateway/src/server.rs`:
- Around line 1311-1315: startup() currently accepts mesh_server_config and
proceeds to start the mesh/server-discovery path even though v2 peer-state sync
isn’t wired here; update startup() in server.rs to validate mesh_server_config
early and fail fast (return an error) or explicitly skip mesh startup with a
loud error-level log and non-zero exit when the v2 adapters in
model_gateway/src/mesh/adapters/ are not being started; check for the
presence/enablement flag for the v2 adapters (or a boolean like
mesh_server_config.enabled) and if set while adapters aren’t wired, refuse to
proceed or disable mesh with a clear error referencing mesh_server_config and
startup().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ea769b9f-d004-4e3a-bc81-55c6ab329040

📥 Commits

Reviewing files that changed from the base of the PR and between 219dc5b and dadc884.

📒 Files selected for processing (20)
  • .github/workflows/benchmark-mesh-serialization.yml
  • crates/mesh/Cargo.toml
  • crates/mesh/benches/mesh_serialization.rs
  • crates/mesh/src/hash.rs
  • crates/mesh/src/lib.rs
  • crates/mesh/src/stores.rs
  • crates/mesh/src/sync.rs
  • crates/mesh/src/tree_ops.rs
  • crates/mesh/src/types.rs
  • model_gateway/src/mesh/adapters/worker_sync.rs
  • model_gateway/src/middleware/concurrency.rs
  • model_gateway/src/policies/cache_aware.rs
  • model_gateway/src/policies/mod.rs
  • model_gateway/src/policies/registry.rs
  • model_gateway/src/routers/mesh/handlers.rs
  • model_gateway/src/routers/mesh/mod.rs
  • model_gateway/src/routers/mod.rs
  • model_gateway/src/server.rs
  • model_gateway/src/worker/registry.rs
  • model_gateway/tests/mesh_integration_test.rs
💤 Files with no reviewable changes (10)
  • crates/mesh/Cargo.toml
  • crates/mesh/benches/mesh_serialization.rs
  • model_gateway/src/routers/mesh/mod.rs
  • .github/workflows/benchmark-mesh-serialization.yml
  • model_gateway/src/routers/mod.rs
  • model_gateway/tests/mesh_integration_test.rs
  • crates/mesh/src/sync.rs
  • model_gateway/src/routers/mesh/handlers.rs
  • model_gateway/src/policies/mod.rs
  • model_gateway/src/policies/registry.rs

Comment on lines +1311 to +1315
// v1 mesh sync (set_mesh_sync, WorkerStateSubscriber, TreeStateSubscriber)
// is removed in this PR. State sync across mesh peers is not wired in this
// branch — v2 adapters in `model_gateway/src/mesh/adapters/` are built and
// tested but not yet started from `server.rs`. That wiring lands in a
// follow-up PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast while mesh config still boots a non-functional cluster path.

Line 1311 explicitly says peer-state sync is not wired in this branch, but startup() still accepts mesh_server_config and starts the mesh/server-discovery path earlier. That means a deployment can come up looking mesh-enabled while never replicating remote worker or policy state. Please reject that config (or skip mesh startup with a loud warning) until the v2 adapters are actually started here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@model_gateway/src/server.rs` around lines 1311 - 1315, startup() currently
accepts mesh_server_config and proceeds to start the mesh/server-discovery path
even though v2 peer-state sync isn’t wired here; update startup() in server.rs
to validate mesh_server_config early and fail fast (return an error) or
explicitly skip mesh startup with a loud error-level log and non-zero exit when
the v2 adapters in model_gateway/src/mesh/adapters/ are not being started; check
for the presence/enablement flag for the v2 adapters (or a boolean like
mesh_server_config.enabled) and if set while adapters aren’t wired, refuse to
proceed or disable mesh with a clear error referencing mesh_server_config and
startup().

@CatherineSue
CatherineSue merged commit 3670562 into main May 13, 2026
50 checks passed
@CatherineSue
CatherineSue deleted the refactor/mesh-v1-removal branch May 13, 2026 05:22
zach-li-sudo pushed a commit to zach-li-sudo/smg that referenced this pull request May 13, 2026
…ct#1476)

Signed-off-by: Chang Su <8605658+CatherineSue@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci CI/CD configuration changes dependencies Dependency updates mesh Mesh crate changes model-gateway Model gateway crate changes tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant