bb_runtime/contracts/peer_selector.rs
1//! `bb::PeerSelector` — Contract trait for peer-selection protocols.
2//!
3//! Every method takes `ctx: &mut RuntimeResourceRef<'_>` as the first
4//! parameter after `&mut self` (the uniform shape shared by every
5//! Contract trait) plus a [`CompletionHandle`] AND returns
6//! [`ContractResponse`]. See [`crate::contracts::index`] for the
7//! sync (Now) vs async (Later) semantics.
8//!
9//! Selector impls read `ctx.peers.addresses` to walk the local
10//! `AddressBook`, write through it for membership updates from the
11//! `dispatch_atomic` arm (`Announce` / `Forget`), and reach the
12//! shared `Scheduler` via `ctx.time` when they need to plan a delayed
13//! probe. Declared dependencies are reached via
14//! `ctx.dependency::<T>(slot)`.
15
16use crate::completion::{CompletionHandle, ContractResponse};
17use crate::runtime::RuntimeResourceRef;
18use bb_ir::ids::PeerId;
19
20/// Parameters describing what peer set to select. Different
21/// concrete selectors handle the variants they support and return
22/// an error variant for the ones they don't (e.g. `GlobalRegistry`
23/// supports `Random` + `All`; `DhtView` supports `NearKey`).
24///
25/// Open enum - new variants are additive; concrete impls match
26/// the ones they handle + return an unsupported-params error for
27/// the rest.
28#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
29pub enum SelectParams {
30 /// Sample `n` peers uniformly at random from the current view.
31 Random {
32 /// Number of peers requested.
33 n: u32,
34 },
35 /// Sample up to `n` peers whose identifier is closest to `key`
36 /// under whatever metric the selector uses (Kademlia XOR, etc.).
37 NearKey {
38 /// Routing key the selector matches against.
39 key: Vec<u8>,
40 /// Maximum peers to return.
41 n: u32,
42 },
43 /// Return every peer in the current view. Useful for tiny
44 /// fixed-size deployments + tests.
45 All,
46}
47
48/// User-facing Contract trait for a peer-selection protocol.
49pub trait PeerSelector: Send + Sync {
50 /// Library-maker-defined error type.
51 type Error: std::error::Error + std::fmt::Display + Send + Sync + 'static;
52
53 /// Generic selection — `params` carries selector-specific
54 /// config. Concrete impls handle the variants they support
55 /// and fail the unsupported ones via `ContractResponse::Now`
56 /// carrying an error. `ctx` exposes `ctx.peers.addresses`
57 /// (the framework's `AddressBook`), the engine's per-op
58 /// runtime surface, and `ctx.dependency::<T>(slot)` for
59 /// reaching any concrete bound via `#[depends(...)]`.
60 fn select(
61 &mut self,
62 ctx: &mut RuntimeResourceRef<'_>,
63 params: SelectParams,
64 completion: CompletionHandle<Vec<PeerId>, Self::Error>,
65 ) -> ContractResponse<Vec<PeerId>, Self::Error>;
66
67 /// Sample `n` peers from the current view. Calls
68 /// land on `select(SelectParams::Random { n })` by default.
69 /// Concrete impls may override to keep an optimized fast path.
70 fn sample(
71 &mut self,
72 ctx: &mut RuntimeResourceRef<'_>,
73 n: u32,
74 completion: CompletionHandle<Vec<PeerId>, Self::Error>,
75 ) -> ContractResponse<Vec<PeerId>, Self::Error> {
76 self.select(ctx, SelectParams::Random { n }, completion)
77 }
78
79 /// Snapshot the current view of known peers (owned snapshot —
80 /// async serialization needs owned values).
81 fn current_view(
82 &mut self,
83 ctx: &mut RuntimeResourceRef<'_>,
84 completion: CompletionHandle<Vec<PeerId>, Self::Error>,
85 ) -> ContractResponse<Vec<PeerId>, Self::Error>;
86}