8 changed files with 0 additions and 377 deletions
@ -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", |
|
||||||
] |
|
||||||
@ -1,7 +0,0 @@ |
|||||||
[package] |
|
||||||
name = "relay_selector" |
|
||||||
version = "0.1.0" |
|
||||||
edition = "2024" |
|
||||||
|
|
||||||
[dependencies] |
|
||||||
wasm-bindgen = "0.2" |
|
||||||
@ -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<RelaySelector> = 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<u8>) -> Result<String, String> { |
|
||||||
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)) |
|
||||||
} |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
mod relay_variant; |
|
||||||
|
|
||||||
pub use relay_variant::RelayVariant; |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
pub struct Relay { |
|
||||||
variant: RelayVariant, |
|
||||||
url: String, |
|
||||||
} |
|
||||||
|
|
||||||
impl Relay { |
|
||||||
pub fn new(variant: RelayVariant, url: String) -> Self { |
|
||||||
Relay { variant, url } |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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<Self> { |
|
||||||
match s { |
|
||||||
"general" => Some(RelayVariant::General), |
|
||||||
"inbox" => Some(RelayVariant::Inbox), |
|
||||||
"outbox" => Some(RelayVariant::Outbox), |
|
||||||
"local" => Some(RelayVariant::Local), |
|
||||||
_ => None, |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,109 +0,0 @@ |
|||||||
use std::collections::HashMap; |
|
||||||
|
|
||||||
use crate::relay::RelayVariant; |
|
||||||
|
|
||||||
const CONNECTION_WEIGHT: f32 = 0.1; |
|
||||||
|
|
||||||
pub struct RelaySelector { |
|
||||||
initial_weights: HashMap<String, f32>, |
|
||||||
current_weights: HashMap<String, f32>, |
|
||||||
|
|
||||||
active_connections: HashMap<String, u8>, |
|
||||||
|
|
||||||
// Sorted relay lists by variant
|
|
||||||
general: Vec<String>, |
|
||||||
inbox: Vec<String>, |
|
||||||
outbox: Vec<String>, |
|
||||||
} |
|
||||||
|
|
||||||
// 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<String, String> { |
|
||||||
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(()) |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue