Files
soulseek-rs-modded/soulseek-rs-lib/src/client/operations/tree.rs
T
Michel de Graaf 62252588a4 refactor: split the files that had grown past reading size
Five files ran between 1.2k and 2.4k lines, and one function past the
length the quality gate allows. None of it was doing anything wrong; they
had simply accumulated until you had to scroll to hold one in your head.

The move throughout is into *child* modules rather than siblings, because
a child still sees its parent's private items. So `ClientContext` keeps
its private fields and `ServerActor` keeps its private state, while the
methods that work on them move out — no encapsulation is widened for the
sake of the split. Three `ServerActor` methods become `pub(super)`, which
is only acknowledging the calls the parent already made.

The client's operation loop and the actor's standing-message match are
split by subject: the arms move out whole, so the bodies read exactly as
they did inside. Where an arm said `continue` it now says `return` — the
match was the last thing the loop did, and none of the arms that moved
holds a loop of its own, so skipping the rest of an arm and ending its
handler are the same move.

The test modules split by topic the same way, which is most of the size:
main_tui's alone was 2.1k of the 2.4k lines.

No behaviour changes. Verified against a live server: the full e2e suite
passes, including the 98 CLI and 19 daemon-protocol cases that drive the
dispatch loop this touches.
2026-09-10 11:48:17 +02:00

104 lines
3.9 KiB
Rust

//! Dispatch arms for our place in the distributed search tree.
//!
//! Lifted out of the dispatch loop whole, so the bodies read exactly as they
//! did inside it.
use super::{Arc, Client, ClientContext, ClientOperation, RwLock, RwLockExt};
impl Client {
pub(super) fn on_tree(
operation: ClientOperation,
client_context: &Arc<RwLock<ClientContext>>,
) {
match operation {
ClientOperation::ParentSearch {
parent,
link,
username,
token,
query,
} => {
let Ok(mut ctx) = client_context.write_safe() else {
return;
};
if let Some(branch) = ctx.leaf.search_from(&parent, link) {
crate::client::distributed::announce_move(
&mut ctx, &branch, true,
);
}
if ctx.leaf.is_parent(&parent, link) {
// The tree's stream is not ours to throttle: every
// search goes down to our children. The budget
// below bounds only the share scan we do for our
// own reply.
ctx.children.broadcast_search(&username, token, &query);
if let Some(ops) = &ctx.operations {
let _ = ops.send(ClientOperation::IncomingSearch {
username,
token,
query,
from_parent: true,
});
}
}
}
ClientOperation::ParentBranchLevel {
parent,
link,
level,
} => {
let Ok(mut ctx) = client_context.write_safe() else {
return;
};
if let Some(branch) =
ctx.leaf.branch_level(&parent, link, level)
{
crate::client::distributed::announce_move(
&mut ctx, &branch, true,
);
}
}
ClientOperation::ParentBranchRoot { parent, link, root } => {
let Ok(mut ctx) = client_context.write_safe() else {
return;
};
if let Some(branch) = ctx.leaf.branch_root(&parent, link, &root)
{
crate::client::distributed::announce_move(
&mut ctx, &branch, true,
);
}
}
ClientOperation::ParentClosed { parent, link } => {
let Ok(mut ctx) = client_context.write_safe() else {
return;
};
if ctx.leaf.closed(&parent, link) {
let branch = ctx.leaf.branch();
crate::client::distributed::announce_move(
&mut ctx, &branch, false,
);
}
}
// Also what a fresh login means: whatever tree we hung
// from belongs to the old session.
ClientOperation::ResetDistributed => {
let Ok(mut ctx) = client_context.write_safe() else {
return;
};
ctx.leaf.reset();
// A fresh session feeds us nothing until the tree (or
// the server) starts again, so the children we were
// carrying are let go rather than left starving.
ctx.set_fed_by(false);
let branch = ctx.leaf.branch();
crate::client::distributed::announce_move(
&mut ctx, &branch, false,
);
}
// The dispatch loop routes only the variants above to here.
_ => {}
}
}
}