From d854c19457d274bb9116b853dfd7760d209af853 Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Sat, 23 Aug 2025 19:53:21 -0500 Subject: [PATCH 1/2] Initial commit - Rust relay selector library --- lib/relay_selector/.gitignore | 1 + lib/relay_selector/Cargo.lock | 133 ++++++++++++++++++ lib/relay_selector/Cargo.toml | 7 + lib/relay_selector/src/lib.rs | 94 +++++++++++++ lib/relay_selector/src/relay/mod.rs | 3 + lib/relay_selector/src/relay/relay.rs | 10 ++ lib/relay_selector/src/relay/relay_variant.rs | 20 +++ lib/relay_selector/src/relay_selector.rs | 109 ++++++++++++++ 8 files changed, 377 insertions(+) create mode 100644 lib/relay_selector/.gitignore create mode 100644 lib/relay_selector/Cargo.lock create mode 100644 lib/relay_selector/Cargo.toml create mode 100644 lib/relay_selector/src/lib.rs create mode 100644 lib/relay_selector/src/relay/mod.rs create mode 100644 lib/relay_selector/src/relay/relay.rs create mode 100644 lib/relay_selector/src/relay/relay_variant.rs create mode 100644 lib/relay_selector/src/relay_selector.rs diff --git a/lib/relay_selector/.gitignore b/lib/relay_selector/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/lib/relay_selector/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/lib/relay_selector/Cargo.lock b/lib/relay_selector/Cargo.lock new file mode 100644 index 0000000..d835a42 --- /dev/null +++ b/lib/relay_selector/Cargo.lock @@ -0,0 +1,133 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "relay_selector" +version = "0.1.0" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] diff --git a/lib/relay_selector/Cargo.toml b/lib/relay_selector/Cargo.toml new file mode 100644 index 0000000..eaf9bb5 --- /dev/null +++ b/lib/relay_selector/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "relay_selector" +version = "0.1.0" +edition = "2024" + +[dependencies] +wasm-bindgen = "0.2" diff --git a/lib/relay_selector/src/lib.rs b/lib/relay_selector/src/lib.rs new file mode 100644 index 0000000..a00496d --- /dev/null +++ b/lib/relay_selector/src/lib.rs @@ -0,0 +1,94 @@ +mod relay; +mod relay_selector; + +use std::cell::RefCell; + +use wasm_bindgen::prelude::*; + +use relay::RelayVariant; +use relay_selector::RelaySelector; + +thread_local! { + /// Static lifetime, thread-local `RelaySelector` instance. + /// + /// The `RelaySelector` acts as an in-memory, mutable repository for relay ranking data. When + /// initialized, it loads data from persistent storage, and when it is no longer needed, it + /// saves the data back to persistent storage. The repository data may be mutated via the + /// functions provided in the `relay_selector` crate's API. + static RELAY_SELECTOR: RefCell = RefCell::new(RelaySelector::new()); +} + +#[wasm_bindgen] +pub fn init() { + // TODO: Initialize a reference-counted relay selector. +} + +#[wasm_bindgen] +pub fn add_response_time(relay_url: &str, response_time: f32) { + // TODO: Implement. + // May delegate to other modules. +} + +#[wasm_bindgen] +pub fn add_success(relay_url: &str, relay_type: &str) { + // TODO: Implement. + + let relay_variant = RelayVariant::from_str(relay_type).unwrap_throw(); + + // May delegate to other modules. +} + +#[wasm_bindgen] +pub fn add_relay(relay_url: &str, relay_type: &str) { + // TODO: Implement. + + let relay_variant = RelayVariant::from_str(relay_type).unwrap_throw(); + + // May delegate to other modules. +} + +/// Get a recommended relay URL based on current weights. +/// +/// # Arguments +/// +/// * `relay_type` - The type of relay. May be `"general"`, `"inbox"`, or `"outbox"`. +/// * `relay_rank` - The relay rank based on current weights. Defaults to `0` to select the +/// highest-ranked relay. +/// +/// # Returns +/// +/// A relay URL. +/// +/// # Errors +/// +/// Throws an error if the relay type is invalid, or if an error occurs while selecting the relay. +/// +/// # Remarks +/// +/// When the relay indicated by the returned URL is no longer in use, it should be returned with +/// [`return_relay`] to prevent memory leaks. +#[wasm_bindgen] +pub fn get_relay(relay_type: &str, relay_rank: Option) -> Result { + let variant = RelayVariant::from_str(relay_type).unwrap_throw(); + let rank = match relay_rank { + Some(rank) => rank, + None => 0, + } as usize; + + RELAY_SELECTOR + .with_borrow_mut(|selector| selector.get_relay_by_weighted_round_robin(variant, rank)) +} + +/// Return a relay URL to indicate it that relay is no longer in use. +/// +/// # Arguments +/// +/// * `relay_url` - The URL of the relay to return. +/// +/// # Errors +/// +/// Throws an error if the caller attempts to return a relay URL that is not currently in use. +#[wasm_bindgen] +pub fn return_relay(relay_url: &str) -> Result<(), String> { + RELAY_SELECTOR.with_borrow_mut(|selector| selector.return_relay(relay_url)) +} diff --git a/lib/relay_selector/src/relay/mod.rs b/lib/relay_selector/src/relay/mod.rs new file mode 100644 index 0000000..32b6b3d --- /dev/null +++ b/lib/relay_selector/src/relay/mod.rs @@ -0,0 +1,3 @@ +mod relay_variant; + +pub use relay_variant::RelayVariant; diff --git a/lib/relay_selector/src/relay/relay.rs b/lib/relay_selector/src/relay/relay.rs new file mode 100644 index 0000000..3949230 --- /dev/null +++ b/lib/relay_selector/src/relay/relay.rs @@ -0,0 +1,10 @@ +pub struct Relay { + variant: RelayVariant, + url: String, +} + +impl Relay { + pub fn new(variant: RelayVariant, url: String) -> Self { + Relay { variant, url } + } +} diff --git a/lib/relay_selector/src/relay/relay_variant.rs b/lib/relay_selector/src/relay/relay_variant.rs new file mode 100644 index 0000000..8feb69f --- /dev/null +++ b/lib/relay_selector/src/relay/relay_variant.rs @@ -0,0 +1,20 @@ +#[derive(Debug)] +pub enum RelayVariant { + General, + Inbox, + Outbox, + Local, +} + +// TODO: Define methods to convert from str to RelayType. +impl RelayVariant { + pub fn from_str(s: &str) -> Option { + match s { + "general" => Some(RelayVariant::General), + "inbox" => Some(RelayVariant::Inbox), + "outbox" => Some(RelayVariant::Outbox), + "local" => Some(RelayVariant::Local), + _ => None, + } + } +} diff --git a/lib/relay_selector/src/relay_selector.rs b/lib/relay_selector/src/relay_selector.rs new file mode 100644 index 0000000..4fa09b3 --- /dev/null +++ b/lib/relay_selector/src/relay_selector.rs @@ -0,0 +1,109 @@ +use std::collections::HashMap; + +use crate::relay::RelayVariant; + +const CONNECTION_WEIGHT: f32 = 0.1; + +pub struct RelaySelector { + initial_weights: HashMap, + current_weights: HashMap, + + active_connections: HashMap, + + // Sorted relay lists by variant + general: Vec, + inbox: Vec, + outbox: Vec, +} + +// Constructor and destructor +impl RelaySelector { + pub fn new() -> Self { + // TODO: Initialize with data from persistent storage. + Self { + initial_weights: HashMap::new(), + current_weights: HashMap::new(), + active_connections: HashMap::new(), + general: Vec::new(), + inbox: Vec::new(), + outbox: Vec::new(), + } + } +} + +// Get and return methods +impl RelaySelector { + pub fn get_relay_by_weighted_round_robin( + &mut self, + variant: RelayVariant, + rank: usize, + ) -> Result { + let ranked = match variant { + RelayVariant::General => &self.general, + RelayVariant::Inbox => &self.inbox, + RelayVariant::Outbox => &self.outbox, + _ => { + return Err(format!( + "[RelaySelector] Unsupported variant: {:?}", + variant + )); + } + }; + + // Grab the relay of the requested rank + // Assumes relays are sorted in descending order of rank + let selected = ranked.get(rank).clone().ok_or(format!( + "[RelaySelector] No {:?} relay found at rank {:?}", + variant, rank + ))?; + + // Increment the number of active connections + let count = self.active_connections.get_mut(selected).ok_or(format!( + "[RelaySelector] Relay {:?} not found in active connections", + selected + ))?; + *count = count.checked_add(1).ok_or(format!( + "[RelaySelector] Relay {:?} has reached maximum active connections", + selected + ))?; + + // Update the current weight based on the new number of active connections + let initial_weight = self.initial_weights.get(selected).ok_or(format!( + "[RelaySelector] Relay {:?} not found in initial weights", + selected + ))?; + let current_weight = self.current_weights.get_mut(selected).ok_or(format!( + "[RelaySelector] Relay {:?} not found in current weights", + selected + ))?; + *current_weight = initial_weight + *count as f32 * CONNECTION_WEIGHT; + + // TODO: Invoke sort on current weights. + + Ok(selected.clone()) + } + + pub fn return_relay(&mut self, relay: &str) -> Result<(), String> { + // Decrement the number of active connections + let count = self.active_connections.get_mut(relay).ok_or(format!( + "[RelaySelector] Relay {:?} not found in active connections", + relay + ))?; + *count = count.checked_sub(1).unwrap_or(0); // Quietly ignore lower bound violations + + // Update the current weight based on the new number of active connections + let initial_weight = self.initial_weights.get(relay).ok_or(format!( + "[RelaySelector] Relay {:?} not found in initial weights", + relay + ))?; + let current_weight = self.current_weights.get_mut(relay).ok_or(format!( + "[RelaySelector] Relay {:?} not found in current weights", + relay + ))?; + *current_weight = initial_weight + *count as f32 * CONNECTION_WEIGHT; + + // TODO: Invoke sort on current weights. + + Ok(()) + } +} From adc1db05477c3e27a32ec274cdc2e71236e9e9b3 Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Sat, 23 Aug 2025 21:37:08 -0500 Subject: [PATCH 2/2] Revert "Initial commit - Rust relay selector library" This reverts commit d854c19457d274bb9116b853dfd7760d209af853. --- lib/relay_selector/.gitignore | 1 - lib/relay_selector/Cargo.lock | 133 ------------------ lib/relay_selector/Cargo.toml | 7 - lib/relay_selector/src/lib.rs | 94 ------------- lib/relay_selector/src/relay/mod.rs | 3 - lib/relay_selector/src/relay/relay.rs | 10 -- lib/relay_selector/src/relay/relay_variant.rs | 20 --- lib/relay_selector/src/relay_selector.rs | 109 -------------- 8 files changed, 377 deletions(-) delete mode 100644 lib/relay_selector/.gitignore delete mode 100644 lib/relay_selector/Cargo.lock delete mode 100644 lib/relay_selector/Cargo.toml delete mode 100644 lib/relay_selector/src/lib.rs delete mode 100644 lib/relay_selector/src/relay/mod.rs delete mode 100644 lib/relay_selector/src/relay/relay.rs delete mode 100644 lib/relay_selector/src/relay/relay_variant.rs delete mode 100644 lib/relay_selector/src/relay_selector.rs diff --git a/lib/relay_selector/.gitignore b/lib/relay_selector/.gitignore deleted file mode 100644 index 2f7896d..0000000 --- a/lib/relay_selector/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target/ diff --git a/lib/relay_selector/Cargo.lock b/lib/relay_selector/Cargo.lock deleted file mode 100644 index d835a42..0000000 --- a/lib/relay_selector/Cargo.lock +++ /dev/null @@ -1,133 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - -[[package]] -name = "cfg-if" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "proc-macro2" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "relay_selector" -version = "0.1.0" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "syn" -version = "2.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] diff --git a/lib/relay_selector/Cargo.toml b/lib/relay_selector/Cargo.toml deleted file mode 100644 index eaf9bb5..0000000 --- a/lib/relay_selector/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "relay_selector" -version = "0.1.0" -edition = "2024" - -[dependencies] -wasm-bindgen = "0.2" diff --git a/lib/relay_selector/src/lib.rs b/lib/relay_selector/src/lib.rs deleted file mode 100644 index a00496d..0000000 --- a/lib/relay_selector/src/lib.rs +++ /dev/null @@ -1,94 +0,0 @@ -mod relay; -mod relay_selector; - -use std::cell::RefCell; - -use wasm_bindgen::prelude::*; - -use relay::RelayVariant; -use relay_selector::RelaySelector; - -thread_local! { - /// Static lifetime, thread-local `RelaySelector` instance. - /// - /// The `RelaySelector` acts as an in-memory, mutable repository for relay ranking data. When - /// initialized, it loads data from persistent storage, and when it is no longer needed, it - /// saves the data back to persistent storage. The repository data may be mutated via the - /// functions provided in the `relay_selector` crate's API. - static RELAY_SELECTOR: RefCell = RefCell::new(RelaySelector::new()); -} - -#[wasm_bindgen] -pub fn init() { - // TODO: Initialize a reference-counted relay selector. -} - -#[wasm_bindgen] -pub fn add_response_time(relay_url: &str, response_time: f32) { - // TODO: Implement. - // May delegate to other modules. -} - -#[wasm_bindgen] -pub fn add_success(relay_url: &str, relay_type: &str) { - // TODO: Implement. - - let relay_variant = RelayVariant::from_str(relay_type).unwrap_throw(); - - // May delegate to other modules. -} - -#[wasm_bindgen] -pub fn add_relay(relay_url: &str, relay_type: &str) { - // TODO: Implement. - - let relay_variant = RelayVariant::from_str(relay_type).unwrap_throw(); - - // May delegate to other modules. -} - -/// Get a recommended relay URL based on current weights. -/// -/// # Arguments -/// -/// * `relay_type` - The type of relay. May be `"general"`, `"inbox"`, or `"outbox"`. -/// * `relay_rank` - The relay rank based on current weights. Defaults to `0` to select the -/// highest-ranked relay. -/// -/// # Returns -/// -/// A relay URL. -/// -/// # Errors -/// -/// Throws an error if the relay type is invalid, or if an error occurs while selecting the relay. -/// -/// # Remarks -/// -/// When the relay indicated by the returned URL is no longer in use, it should be returned with -/// [`return_relay`] to prevent memory leaks. -#[wasm_bindgen] -pub fn get_relay(relay_type: &str, relay_rank: Option) -> Result { - let variant = RelayVariant::from_str(relay_type).unwrap_throw(); - let rank = match relay_rank { - Some(rank) => rank, - None => 0, - } as usize; - - RELAY_SELECTOR - .with_borrow_mut(|selector| selector.get_relay_by_weighted_round_robin(variant, rank)) -} - -/// Return a relay URL to indicate it that relay is no longer in use. -/// -/// # Arguments -/// -/// * `relay_url` - The URL of the relay to return. -/// -/// # Errors -/// -/// Throws an error if the caller attempts to return a relay URL that is not currently in use. -#[wasm_bindgen] -pub fn return_relay(relay_url: &str) -> Result<(), String> { - RELAY_SELECTOR.with_borrow_mut(|selector| selector.return_relay(relay_url)) -} diff --git a/lib/relay_selector/src/relay/mod.rs b/lib/relay_selector/src/relay/mod.rs deleted file mode 100644 index 32b6b3d..0000000 --- a/lib/relay_selector/src/relay/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod relay_variant; - -pub use relay_variant::RelayVariant; diff --git a/lib/relay_selector/src/relay/relay.rs b/lib/relay_selector/src/relay/relay.rs deleted file mode 100644 index 3949230..0000000 --- a/lib/relay_selector/src/relay/relay.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub struct Relay { - variant: RelayVariant, - url: String, -} - -impl Relay { - pub fn new(variant: RelayVariant, url: String) -> Self { - Relay { variant, url } - } -} diff --git a/lib/relay_selector/src/relay/relay_variant.rs b/lib/relay_selector/src/relay/relay_variant.rs deleted file mode 100644 index 8feb69f..0000000 --- a/lib/relay_selector/src/relay/relay_variant.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[derive(Debug)] -pub enum RelayVariant { - General, - Inbox, - Outbox, - Local, -} - -// TODO: Define methods to convert from str to RelayType. -impl RelayVariant { - pub fn from_str(s: &str) -> Option { - match s { - "general" => Some(RelayVariant::General), - "inbox" => Some(RelayVariant::Inbox), - "outbox" => Some(RelayVariant::Outbox), - "local" => Some(RelayVariant::Local), - _ => None, - } - } -} diff --git a/lib/relay_selector/src/relay_selector.rs b/lib/relay_selector/src/relay_selector.rs deleted file mode 100644 index 4fa09b3..0000000 --- a/lib/relay_selector/src/relay_selector.rs +++ /dev/null @@ -1,109 +0,0 @@ -use std::collections::HashMap; - -use crate::relay::RelayVariant; - -const CONNECTION_WEIGHT: f32 = 0.1; - -pub struct RelaySelector { - initial_weights: HashMap, - current_weights: HashMap, - - active_connections: HashMap, - - // Sorted relay lists by variant - general: Vec, - inbox: Vec, - outbox: Vec, -} - -// Constructor and destructor -impl RelaySelector { - pub fn new() -> Self { - // TODO: Initialize with data from persistent storage. - Self { - initial_weights: HashMap::new(), - current_weights: HashMap::new(), - active_connections: HashMap::new(), - general: Vec::new(), - inbox: Vec::new(), - outbox: Vec::new(), - } - } -} - -// Get and return methods -impl RelaySelector { - pub fn get_relay_by_weighted_round_robin( - &mut self, - variant: RelayVariant, - rank: usize, - ) -> Result { - let ranked = match variant { - RelayVariant::General => &self.general, - RelayVariant::Inbox => &self.inbox, - RelayVariant::Outbox => &self.outbox, - _ => { - return Err(format!( - "[RelaySelector] Unsupported variant: {:?}", - variant - )); - } - }; - - // Grab the relay of the requested rank - // Assumes relays are sorted in descending order of rank - let selected = ranked.get(rank).clone().ok_or(format!( - "[RelaySelector] No {:?} relay found at rank {:?}", - variant, rank - ))?; - - // Increment the number of active connections - let count = self.active_connections.get_mut(selected).ok_or(format!( - "[RelaySelector] Relay {:?} not found in active connections", - selected - ))?; - *count = count.checked_add(1).ok_or(format!( - "[RelaySelector] Relay {:?} has reached maximum active connections", - selected - ))?; - - // Update the current weight based on the new number of active connections - let initial_weight = self.initial_weights.get(selected).ok_or(format!( - "[RelaySelector] Relay {:?} not found in initial weights", - selected - ))?; - let current_weight = self.current_weights.get_mut(selected).ok_or(format!( - "[RelaySelector] Relay {:?} not found in current weights", - selected - ))?; - *current_weight = initial_weight + *count as f32 * CONNECTION_WEIGHT; - - // TODO: Invoke sort on current weights. - - Ok(selected.clone()) - } - - pub fn return_relay(&mut self, relay: &str) -> Result<(), String> { - // Decrement the number of active connections - let count = self.active_connections.get_mut(relay).ok_or(format!( - "[RelaySelector] Relay {:?} not found in active connections", - relay - ))?; - *count = count.checked_sub(1).unwrap_or(0); // Quietly ignore lower bound violations - - // Update the current weight based on the new number of active connections - let initial_weight = self.initial_weights.get(relay).ok_or(format!( - "[RelaySelector] Relay {:?} not found in initial weights", - relay - ))?; - let current_weight = self.current_weights.get_mut(relay).ok_or(format!( - "[RelaySelector] Relay {:?} not found in current weights", - relay - ))?; - *current_weight = initial_weight + *count as f32 * CONNECTION_WEIGHT; - - // TODO: Invoke sort on current weights. - - Ok(()) - } -}