[refactor](trx-rs): resolve all P1/P2 improvement areas

P1 (High Priority):
- Fix LIFO command batching in rig_task.rs (batch.pop→batch.remove(0))
- Add ±25% jitter to ExponentialBackoff to prevent thundering herd
- Add 10,000-entry capacity bounds to decoder history queues
- Add rig task crash detection with Error state broadcast
- Decompose FrontendRuntimeContext 50-field god-struct into 9 sub-structs
  (AudioContext, DecodeHistoryContext, HttpAuthConfig, HttpUiConfig,
   RigRoutingContext, OwnerInfo, VChanContext, SpectrumContext, PerRigAudioContext)
- Migrate std::sync::RwLock to tokio::sync::RwLock in background_decode.rs
- Extract find_input_device/find_output_device helpers from audio pipeline

P2 (Medium Priority):
- Introduce SoapySdrConfig builder struct (replaces 20+ positional params)
- Add define_command_mappings! macro for ClientCommand↔RigCommand mapping
- Replace silent lock poison recovery with lock_or_recover() warning logger
- Make timeouts configurable via RigTaskConfig/ListenerConfig and TOML
- Extract shared config types to trx-app/src/shared_config.rs

Documentation updated in CLAUDE.md, Architecture.md, Improvement-Areas.md.

https://claude.ai/code/session_01P9G7QCWfiYbPVJ7cgiXznf
Signed-off-by: Claude <noreply@anthropic.com>
This commit is contained in:
Claude
2026-03-28 23:26:55 +00:00
committed by Stan Grams
parent 0a60684e28
commit 16426548de
22 changed files with 1245 additions and 916 deletions
@@ -129,7 +129,7 @@ async fn handle_client(
}
if let Some(rig_id) = envelope.rig_id.as_ref() {
if let Ok(mut active) = context.remote_active_rig_id.lock() {
if let Ok(mut active) = context.routing.active_rig_id.lock() {
*active = Some(rig_id.clone());
}
}
@@ -148,7 +148,8 @@ async fn handle_client(
}
let active_rig_id = context
.remote_active_rig_id
.routing
.active_rig_id
.lock()
.ok()
.and_then(|v| v.clone());
@@ -245,6 +246,7 @@ async fn handle_client(
fn snapshot_remote_rigs(context: &FrontendRuntimeContext) -> Vec<RigEntry> {
context
.routing
.remote_rigs
.lock()
.ok()
@@ -333,7 +335,7 @@ async fn send_response(
}
fn authorize(token: &Option<String>, context: &FrontendRuntimeContext) -> Result<(), String> {
let validator = SimpleTokenValidator::new(context.auth_tokens.clone());
let validator = SimpleTokenValidator::new(context.http_auth.tokens.clone());
validator.validate(token)
}
@@ -436,7 +438,7 @@ mod tests {
let addr = loopback_addr();
let (rig_tx, _rig_rx) = mpsc::channel::<RigRequest>(8);
let mut runtime = FrontendRuntimeContext::new();
runtime.auth_tokens = HashSet::from(["secret".to_string()]);
runtime.http_auth.tokens = HashSet::from(["secret".to_string()]);
let ctx = Arc::new(runtime);
let handle = tokio::spawn(serve(addr, rig_tx, ctx));