Skip to content

Commit 76f8a30

Browse files
kariyclaude
andcommitted
refactor(shard): replace ShardRegistry with pluggable ShardManager trait
Introduce a `ShardManager` trait that abstracts shard storage and creation policy, replacing the hard-coded `ShardRegistry`. The current lazy-creation behavior is preserved in `LazyShardManager` (dev mode), while a future `OnchainShardManager` can provide production semantics where shards are created from onchain events instead of RPC requests. Also extract the `ShardApiServer` implementation into a generic `ShardRpc<P: ShardProvider>` in rpc-server, with the node crate providing the concrete `NodeShardProvider` implementation. This moves the RPC delegation boilerplate out of the node crate and keeps the node's bridge code focused on shard resolution and scheduling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2956d5a commit 76f8a30

File tree

6 files changed

+227
-384
lines changed

6 files changed

+227
-384
lines changed
Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashMap;
2+
use std::fmt::Debug;
23
use std::sync::Arc;
34

45
use anyhow::Result;
@@ -11,13 +12,31 @@ use parking_lot::RwLock;
1112

1213
use super::types::{Shard, ShardId};
1314

14-
/// Registry of all active shards, with lazy creation support.
15-
#[derive(Clone)]
16-
pub struct ShardRegistry {
17-
inner: Arc<ShardRegistryInner>,
15+
/// Pluggable abstraction for shard storage and creation policy.
16+
///
17+
/// Implementations decide what happens when a shard is requested:
18+
/// - [`LazyShardManager`] creates shards on first access (dev mode).
19+
/// - A future `OnchainShardManager` would only look up pre-registered shards (production mode,
20+
/// where shards are created from onchain events).
21+
pub trait ShardManager: Send + Sync + Debug + 'static {
22+
/// Resolve a shard by ID. The creation policy is implementation-defined:
23+
/// lazy managers create on miss, strict managers return an error.
24+
fn get(&self, id: ShardId) -> Result<Arc<Shard>>;
25+
26+
/// List all registered shard IDs.
27+
fn shard_ids(&self) -> Vec<ShardId>;
28+
}
29+
30+
/// Dev-mode shard manager that lazily creates shards on first access.
31+
///
32+
/// Holds shared resources (chain spec, executor factory, gas oracle, etc.)
33+
/// needed to construct new shards. Uses double-checked locking to ensure
34+
/// at most one shard instance per ID.
35+
pub struct LazyShardManager {
36+
inner: Arc<LazyShardManagerInner>,
1837
}
1938

20-
struct ShardRegistryInner {
39+
struct LazyShardManagerInner {
2140
shards: RwLock<HashMap<ShardId, Arc<Shard>>>,
2241
// Shared resources for lazy shard creation
2342
chain_spec: Arc<ChainSpec>,
@@ -27,7 +46,7 @@ struct ShardRegistryInner {
2746
task_spawner: TaskSpawner,
2847
}
2948

30-
impl ShardRegistry {
49+
impl LazyShardManager {
3150
pub fn new(
3251
chain_spec: Arc<ChainSpec>,
3352
executor_factory: Arc<dyn ExecutorFactory>,
@@ -36,7 +55,7 @@ impl ShardRegistry {
3655
task_spawner: TaskSpawner,
3756
) -> Self {
3857
Self {
39-
inner: Arc::new(ShardRegistryInner {
58+
inner: Arc::new(LazyShardManagerInner {
4059
shards: RwLock::new(HashMap::new()),
4160
chain_spec,
4261
executor_factory,
@@ -47,13 +66,19 @@ impl ShardRegistry {
4766
}
4867
}
4968

50-
/// Look up a shard by id. Returns `None` if the shard doesn't exist.
51-
pub fn get(&self, id: &ShardId) -> Option<Arc<Shard>> {
52-
self.inner.shards.read().get(id).cloned()
69+
/// Returns the number of registered shards.
70+
pub fn len(&self) -> usize {
71+
self.inner.shards.read().len()
72+
}
73+
74+
/// Returns `true` if no shards are registered.
75+
pub fn is_empty(&self) -> bool {
76+
self.inner.shards.read().is_empty()
5377
}
78+
}
5479

55-
/// Get an existing shard or create a new one lazily.
56-
pub fn get_or_create(&self, id: ShardId) -> Result<Arc<Shard>> {
80+
impl ShardManager for LazyShardManager {
81+
fn get(&self, id: ShardId) -> Result<Arc<Shard>> {
5782
// Fast path: read lock
5883
{
5984
let shards = self.inner.shards.read();
@@ -83,24 +108,13 @@ impl ShardRegistry {
83108
Ok(shard)
84109
}
85110

86-
/// List all registered shard ids.
87-
pub fn shard_ids(&self) -> Vec<ShardId> {
111+
fn shard_ids(&self) -> Vec<ShardId> {
88112
self.inner.shards.read().keys().copied().collect()
89113
}
90-
91-
/// Returns the number of registered shards.
92-
pub fn len(&self) -> usize {
93-
self.inner.shards.read().len()
94-
}
95-
96-
/// Returns `true` if no shards are registered.
97-
pub fn is_empty(&self) -> bool {
98-
self.inner.shards.read().is_empty()
99-
}
100114
}
101115

102-
impl std::fmt::Debug for ShardRegistry {
116+
impl Debug for LazyShardManager {
103117
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104-
f.debug_struct("ShardRegistry").field("shard_count", &self.len()).finish_non_exhaustive()
118+
f.debug_struct("LazyShardManager").field("shard_count", &self.len()).finish_non_exhaustive()
105119
}
106120
}

0 commit comments

Comments
 (0)