Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
bc13c70
WIP
xDarksome May 7, 2025
81bd234
Bump VERSION to 250507.0
WalletConnectBot May 7, 2025
8b4b5a2
impl ClusterView
xDarksome May 7, 2025
65fd668
transferOwnership
xDarksome May 7, 2025
ed6b201
more tests
xDarksome May 7, 2025
471018f
remove Rust prototype
xDarksome May 7, 2025
8cfd935
Bump VERSION to 250508.0
WalletConnectBot May 8, 2025
bf8f6f9
more tests / bug fixes
xDarksome May 8, 2025
510d8b0
merge remote
xDarksome May 8, 2025
eecceee
make gas reporter work
xDarksome May 9, 2025
5bf775b
more tests / bug fixes
xDarksome May 13, 2025
f4b2ed6
generate alloy bindings
xDarksome May 13, 2025
4dfd645
Bump VERSION to 250513.0
WalletConnectBot May 13, 2025
bb07f92
WIP
xDarksome May 14, 2025
54e6ad1
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome May 14, 2025
aca8a7c
Bump VERSION to 250514.0
WalletConnectBot May 14, 2025
a244a36
smart contract overhaul
xDarksome May 20, 2025
de63784
regenerate bindings
xDarksome May 20, 2025
70cb4d9
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome May 20, 2025
226e49f
Bump VERSION to 250520.0
WalletConnectBot May 20, 2025
438753c
rename things
xDarksome May 20, 2025
87e04fe
WIP
xDarksome May 20, 2025
6939230
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome May 20, 2025
8a971b5
WIP
xDarksome May 26, 2025
3c96b1c
Bump VERSION to 250526.0
WalletConnectBot May 26, 2025
1c45587
upgrade alloy to 1.0 & use sol! macro to generate bindings
xDarksome May 27, 2025
96e0aa4
merge remote
xDarksome May 27, 2025
147f239
Bump VERSION to 250527.0
WalletConnectBot May 27, 2025
414a3cf
impl event sourcing
xDarksome May 28, 2025
78e5918
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome May 28, 2025
16ddff4
Bump VERSION to 250528.0
WalletConnectBot May 28, 2025
906dee9
switch to ABI / more events / SC improvements
xDarksome May 29, 2025
4cbc577
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome May 29, 2025
b6817f9
Bump VERSION to 250529.0
WalletConnectBot May 29, 2025
27451ed
another SC overhaul
xDarksome Jun 2, 2025
eaefed2
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome Jun 2, 2025
ace793e
Bump VERSION to 250602.0
WalletConnectBot Jun 2, 2025
c6939cd
WIP
xDarksome Jun 4, 2025
e9996c9
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome Jun 4, 2025
a790e9e
Bump VERSION to 250604.0
WalletConnectBot Jun 4, 2025
0f3de13
WIP
xDarksome Jun 5, 2025
f0eec90
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome Jun 5, 2025
1aa1f32
Bump VERSION to 250605.0
WalletConnectBot Jun 5, 2025
508630c
fix constructor bug
xDarksome Jun 5, 2025
51b3440
move things around
xDarksome Jun 5, 2025
5bfd6d4
fix tests
xDarksome Jun 5, 2025
ed1df75
integration tests
xDarksome Jun 6, 2025
9b955d9
Merge branch 'feat/contract' of github.com:WalletConnectFoundation/wc…
xDarksome Jun 6, 2025
8af8b74
Bump VERSION to 250606.0
WalletConnectBot Jun 6, 2025
76b393a
remove cluster
xDarksome Jun 6, 2025
44994f2
merge remote
xDarksome Jun 6, 2025
7b1daf2
fix: axum
xDarksome Jun 6, 2025
0381b77
fix: axum
xDarksome Jun 6, 2025
e04d3b1
fix: dockerfile
xDarksome Jun 6, 2025
3cc33d7
fix: dockerfile
xDarksome Jun 6, 2025
bbd0f94
feat: 2.0 cluster machinery
xDarksome Jun 6, 2025
48a4bc0
fix: deps
xDarksome Jun 6, 2025
36a61d9
fixes
xDarksome Jun 9, 2025
6382773
Bump VERSION to 250609.0
WalletConnectBot Jun 9, 2025
f1a5e19
fixes
xDarksome Jun 9, 2025
7c8ae2f
merge remote
xDarksome Jun 9, 2025
1b03591
fix: dockerignore
xDarksome Jun 9, 2025
56ee6c4
merge main
xDarksome Jun 10, 2025
f084b87
WIP
xDarksome Jun 12, 2025
1db787e
Bump VERSION to 250612.0
WalletConnectBot Jun 12, 2025
d32eb9f
WIP
xDarksome Jun 16, 2025
b5180a8
WIP
xDarksome Jun 18, 2025
4344eb9
WIP
xDarksome Jun 19, 2025
873375e
WIP
xDarksome Jun 20, 2025
5dfe8f1
WIP
xDarksome Jun 20, 2025
8c31c95
WIP
xDarksome Jun 25, 2025
68eaaaa
WIP
xDarksome Jun 26, 2025
973e78a
type checks 🎉
xDarksome Jun 27, 2025
2587d68
merge main
xDarksome Jun 27, 2025
f826ce9
Bump VERSION to 250627.0
WalletConnectBot Jun 27, 2025
0efc451
remove unused files
xDarksome Jun 27, 2025
e80d526
merge remote
xDarksome Jun 27, 2025
e68503f
remove Config AsRef
xDarksome Jun 27, 2025
8585d99
fix clippy
xDarksome Jun 27, 2025
471b334
Namespace::from_str test
xDarksome Jun 27, 2025
8ceb1e2
cleanup
xDarksome Jun 27, 2025
2a7f149
fix: missing match arms
xDarksome Jun 30, 2025
0efe983
Bump VERSION to 250630.0
WalletConnectBot Jun 30, 2025
a22d4cf
integration tests
xDarksome Jun 30, 2025
addccd1
Merge branch 'feat/storage-api-2.0' of github.com:WalletConnectFounda…
xDarksome Jun 30, 2025
c543fa8
fix: remove unused #[allow]
xDarksome Jun 30, 2025
65a4a1d
fix: clippy
xDarksome Jun 30, 2025
1f4d65a
fix: missing .await
xDarksome Jun 30, 2025
cdb1a1e
fix: clippy
xDarksome Jun 30, 2025
8539323
feat(wcn_rpc): client load balancer
xDarksome Jul 1, 2025
99ed0bb
use LB in integration tests
xDarksome Jul 1, 2025
e154b2a
Bump VERSION to 250701.0
WalletConnectBot Jul 1, 2025
66652d2
fix: comment
xDarksome Jul 1, 2025
d10df60
merge remote
xDarksome Jul 1, 2025
4972b39
merge main
xDarksome Jul 3, 2025
4e55c46
Bump VERSION to 250703.0
WalletConnectBot Jul 3, 2025
97552be
fix: clippy
xDarksome Jul 3, 2025
9d0c106
merge remote
xDarksome Jul 3, 2025
c11526a
fix: clippy
xDarksome Jul 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
250702.0
250703.0
2 changes: 0 additions & 2 deletions crates/rpc/src/client2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,5 +566,3 @@ impl metrics::Enum for ErrorKind {
self.into()
}
}

// TODO: Vec<Connection> Load Balancer
90 changes: 74 additions & 16 deletions crates/storage_api2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ pub use {
use {
futures::FutureExt as _,
serde::{Deserialize, Serialize},
std::{borrow::Cow, future::Future, str::FromStr, time::Duration},
std::{
borrow::Cow,
future::Future,
str::FromStr,
sync::{atomic, atomic::AtomicUsize},
time::Duration,
},
time::OffsetDateTime as DateTime,
};

Expand Down Expand Up @@ -55,13 +61,13 @@ pub type KeyspaceVersion = u64;
/// servers).
/// - Replicas use it to finally execute the operations on their local WCN
/// Database instances.
pub trait StorageApi: Clone + Send + Sync + 'static {
pub trait StorageApi: Send + Sync + 'static {
/// Executes the provided [`operation::Get`].
fn get<'a>(
&'a self,
get: &'a operation::Get<'a>,
) -> impl Future<Output = Result<Option<Record<'a>>>> + Send + 'a {
self.execute_ref(get)
self.execute_ref(OperationRef::Get(get))
.map(operation::Output::downcast_result)
}

Expand All @@ -70,7 +76,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
set: &'a operation::Set<'a>,
) -> impl Future<Output = Result<()>> + Send + 'a {
self.execute_ref(set)
self.execute_ref(OperationRef::Set(set))
.map(operation::Output::downcast_result)
}

Expand All @@ -79,7 +85,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
del: &'a operation::Del<'a>,
) -> impl Future<Output = Result<()>> + Send + 'a {
self.execute_ref(del)
self.execute_ref(OperationRef::Del(del))
.map(operation::Output::downcast_result)
}

Expand All @@ -88,7 +94,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
get_exp: &'a operation::GetExp<'a>,
) -> impl Future<Output = Result<Option<RecordExpiration>>> + Send + 'a {
self.execute_ref(get_exp)
self.execute_ref(OperationRef::GetExp(get_exp))
.map(operation::Output::downcast_result)
}

Expand All @@ -97,7 +103,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
set_exp: &'a operation::SetExp<'a>,
) -> impl Future<Output = Result<()>> + Send + 'a {
self.execute_ref(set_exp)
self.execute_ref(OperationRef::SetExp(set_exp))
.map(operation::Output::downcast_result)
}

Expand All @@ -106,7 +112,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hget: &'a operation::HGet<'a>,
) -> impl Future<Output = Result<Option<Record<'a>>>> + Send + 'a {
self.execute_ref(hget)
self.execute_ref(OperationRef::HGet(hget))
.map(operation::Output::downcast_result)
}

Expand All @@ -115,7 +121,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hset: &'a operation::HSet<'a>,
) -> impl Future<Output = Result<()>> + Send + 'a {
self.execute_ref(hset)
self.execute_ref(OperationRef::HSet(hset))
.map(operation::Output::downcast_result)
}

Expand All @@ -124,7 +130,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hdel: &'a operation::HDel<'a>,
) -> impl Future<Output = Result<()>> + Send + 'a {
self.execute_ref(hdel)
self.execute_ref(OperationRef::HDel(hdel))
.map(operation::Output::downcast_result)
}

Expand All @@ -133,7 +139,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hget_exp: &'a operation::HGetExp<'a>,
) -> impl Future<Output = Result<Option<RecordExpiration>>> + Send + 'a {
self.execute_ref(hget_exp)
self.execute_ref(OperationRef::HGetExp(hget_exp))
.map(operation::Output::downcast_result)
}

Expand All @@ -142,7 +148,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hset_exp: &'a operation::HSetExp<'a>,
) -> impl Future<Output = Result<()>> + Send + 'a {
self.execute_ref(hset_exp)
self.execute_ref(OperationRef::HSetExp(hset_exp))
.map(operation::Output::downcast_result)
}

Expand All @@ -151,7 +157,7 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hcard: &'a operation::HCard<'a>,
) -> impl Future<Output = Result<u64>> + Send + 'a {
self.execute_ref(hcard)
self.execute_ref(OperationRef::HCard(hcard))
.map(operation::Output::downcast_result)
}

Expand All @@ -160,16 +166,16 @@ pub trait StorageApi: Clone + Send + Sync + 'static {
&'a self,
hscan: &'a operation::HScan<'a>,
) -> impl Future<Output = Result<MapPage<'a>>> + Send + 'a {
self.execute_ref(hscan)
self.execute_ref(OperationRef::HScan(hscan))
.map(operation::Output::downcast_result)
}

/// Executes the provided [`StorageApi`] [`OperationRef`].
fn execute_ref<'a>(
&'a self,
operation: impl Into<OperationRef<'a>> + Send + 'a,
operation: OperationRef<'a>,
) -> impl Future<Output = Result<operation::Output<'a>>> + Send + 'a {
self.execute(operation.into().to_owned())
self.execute(operation.to_owned())
}

/// Executes the provided [`StorageApi`] [`Operation`].
Expand Down Expand Up @@ -410,6 +416,58 @@ impl From<ErrorKind> for Error {
}
}

/// [`StorageApi`] Load balancer.
///
/// Load balances execution of [`Operation`]s across a list of [`StorageApi`]
/// implementors using a round-robin strategy.
pub struct LoadBalancer<S> {
/// List of [`StorageApi`]s of this [`LoadBalancer`].
///
/// Can be safely modified at any point.
pub apis: Vec<S>,

counter: AtomicUsize,
}

impl<S: StorageApi> LoadBalancer<S> {
/// Creates a new [`LoadBalancer`].
pub fn new(connections: impl IntoIterator<Item = S>) -> Self {
Self {
apis: connections.into_iter().collect(),
// overflows and starts from `0`
counter: usize::MAX.into(),
}
}

fn next_api(&self) -> Result<&S> {
if self.apis.is_empty() {
return Err(Error::new(
ErrorKind::Internal,
Some("LoadBalancer::apis is empty".to_string()),
));
}

let n = self.counter.fetch_add(1, atomic::Ordering::Relaxed);
Ok(&self.apis[n % self.apis.len()])
}
}

impl<S: StorageApi> StorageApi for LoadBalancer<S> {
async fn execute_ref<'a>(
&'a self,
operation: OperationRef<'a>,
) -> Result<operation::Output<'a>> {
self.next_api()?.execute_ref(operation).await
}

async fn execute<'a>(
&'a self,
operation: crate::Operation<'a>,
) -> Result<operation::Output<'a>> {
self.next_api()?.execute(operation).await
}
}

#[cfg(test)]
#[test]
fn test_namespace_from_str() {
Expand Down
4 changes: 2 additions & 2 deletions crates/storage_api2/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ where

async fn execute_ref<'a>(
&'a self,
operation: impl Into<crate::OperationRef<'a>> + Send + 'a,
operation: crate::OperationRef<'a>,
) -> Result<operation::Output<'a>> {
match operation.into() {
match operation {
OperationRef::Get(get) => self.get(get).await.map(Into::into),
OperationRef::Set(set) => self.set(set).await.map(Into::into),
OperationRef::Del(del) => self.del(del).await.map(Into::into),
Expand Down
10 changes: 5 additions & 5 deletions crates/storage_api2/src/rpc/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ use {
};

/// Creates a new [`CoordinatorApi`] RPC server.
pub fn coordinator(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server {
pub fn coordinator(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server {
new::<api_kind::Coordinator>(storage_api)
}

/// Creates a new [`ReplicaApi`] RPC server.
pub fn replica(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server {
pub fn replica(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server {
new::<api_kind::Replica>(storage_api)
}

/// Creates a new [`DatabaseApi`] RPC server.
pub fn database(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server {
pub fn database(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server {
new::<api_kind::Database>(storage_api)
}

fn new<Kind>(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server
fn new<Kind>(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server
where
Kind: Clone + Send + Sync + 'static,
Api<Kind>: wcn_rpc::Api<RpcId = RpcId>,
Expand All @@ -43,7 +43,7 @@ struct ConnectionHandler<S: StorageApi, Kind> {

impl<S, Kind> HandleConnection for ConnectionHandler<S, Kind>
where
S: StorageApi,
S: StorageApi + Clone,
Kind: Clone + Send + Sync + 'static,
Api<Kind>: wcn_rpc::Api<RpcId = RpcId>,
{
Expand Down
19 changes: 12 additions & 7 deletions crates/storage_api2/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use {
operation,
Bytes,
KeyspaceVersion,
LoadBalancer,
MapEntry,
MapPage,
Namespace,
Expand Down Expand Up @@ -75,9 +76,9 @@ async fn test_rpc_api<API, S>(
port: server_port,
keypair: server_keypair,
connection_timeout: Duration::from_secs(10),
max_connections: 1,
max_connections_per_ip: 1,
max_connection_rate_per_ip: 1,
max_connections: 2,
max_connections_per_ip: 2,
max_connection_rate_per_ip: 2,
max_concurrent_rpcs: 10,
priority: transport::Priority::High,
};
Expand All @@ -95,14 +96,18 @@ async fn test_rpc_api<API, S>(
let client = client(client_config).unwrap();

let server_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, server_port);
let client_conn = client
let client_conn1 = client
.connect(server_addr, &server_peer_id, ())
.await
.unwrap();
let client_conn2 = client
.connect(server_addr, &server_peer_id, ())
.await
.unwrap();

let ctx = &TestContext {
storage,
client_conn,
lb: LoadBalancer::new([client_conn1, client_conn2]),
};

ctx.test_operations().await;
Expand All @@ -112,7 +117,7 @@ async fn test_rpc_api<API, S>(

struct TestContext<API: Api> {
storage: TestStorage,
client_conn: Connection<API>,
lb: LoadBalancer<Connection<API>>,
}

impl<API: Api> TestContext<API>
Expand Down Expand Up @@ -146,7 +151,7 @@ where

let expect = (operation.clone(), result.clone());
let _ = self.storage.expect.lock().unwrap().insert(expect);
assert_eq!(self.client_conn.execute(operation).await, result);
assert_eq!(self.lb.execute(operation).await, result);
}

async fn test_get(&self) {
Expand Down
Loading