fix(call-to-play): compact terminal histories
The 4,096-event store retained every completed call forever and local commands only reported that they reached the queue. Once the bound was reached, GUI actions could therefore fail with no user-visible result. The CLI snapshot wait could also be satisfied by an unrelated live event. Keep the complete event and chat history for every active call so late joiners receive full context. When the creator starts or cancels a call, replace its history with a single terminal tombstone; this bounds retained payload while still healing peers that missed the live terminal action. Publish commands now reply with the actual store result, and CLI snapshots use a direct reply. Test Plan: - `just fmt` -- passed - `just clippy` -- passed - `just test` -- passed, including full-cap terminal compaction - `just build` -- passed - `just peer-cli-tests S48` -- passed - `git diff --cached --check` -- passed
This commit is contained in:
@@ -47,7 +47,7 @@ use lanspread_peer_cli::{
|
||||
use serde_json::{Value, json};
|
||||
use tokio::{
|
||||
io::{AsyncBufReadExt, BufReader},
|
||||
sync::{Notify, RwLock, mpsc},
|
||||
sync::{Notify, RwLock, mpsc, oneshot},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -103,7 +103,6 @@ struct CliState {
|
||||
unavailable_games: HashSet<String>,
|
||||
downloads: HashMap<String, DownloadMeasurement>,
|
||||
call_to_play_events: Vec<CallToPlayEvent>,
|
||||
call_to_play_generation: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
@@ -247,24 +246,25 @@ async fn handle_command(
|
||||
CliCommand::ListPeers => list_peers(shared).await,
|
||||
CliCommand::ListGames => list_games(shared).await,
|
||||
CliCommand::ListCallToPlay => {
|
||||
let generation = shared.state.read().await.call_to_play_generation;
|
||||
sender.send(PeerCommand::GetCallToPlayEvents)?;
|
||||
tokio::time::timeout(Duration::from_secs(1), async {
|
||||
loop {
|
||||
if shared.state.read().await.call_to_play_generation > generation {
|
||||
break;
|
||||
}
|
||||
shared.notify.notified().await;
|
||||
}
|
||||
})
|
||||
.await
|
||||
.wrap_err("timed out waiting for Call to Play history")?;
|
||||
let events = shared.state.read().await.call_to_play_events.clone();
|
||||
let (reply, result) = oneshot::channel();
|
||||
sender.send(PeerCommand::GetCallToPlayEvents { reply: Some(reply) })?;
|
||||
let events = tokio::time::timeout(Duration::from_secs(1), result)
|
||||
.await
|
||||
.wrap_err("timed out waiting for Call to Play history")?
|
||||
.wrap_err("peer stopped before returning Call to Play history")?;
|
||||
Ok(json!({ "events": events }))
|
||||
}
|
||||
CliCommand::PublishCallToPlay { event } => {
|
||||
sender.send(PeerCommand::PublishCallToPlay(event.clone()))?;
|
||||
Ok(json!({"queued": true, "event_id": event.id}))
|
||||
let (reply, result) = oneshot::channel();
|
||||
sender.send(PeerCommand::PublishCallToPlay {
|
||||
event: event.clone(),
|
||||
reply,
|
||||
})?;
|
||||
result
|
||||
.await
|
||||
.wrap_err("peer stopped before publishing Call to Play event")?
|
||||
.map_err(eyre::Report::msg)?;
|
||||
Ok(json!({"published": true, "event_id": event.id}))
|
||||
}
|
||||
CliCommand::SetGameDir { path } => {
|
||||
sender.send(PeerCommand::SetGameDir(path.clone()))?;
|
||||
@@ -534,7 +534,6 @@ async fn update_state_from_event(shared: &SharedState, event: PeerEvent) -> (&'s
|
||||
.filter(|event| known.insert(event.id.clone()))
|
||||
.cloned(),
|
||||
);
|
||||
state.call_to_play_generation = state.call_to_play_generation.saturating_add(1);
|
||||
("call-to-play-events", json!({ "events": events }))
|
||||
}
|
||||
PeerEvent::GotGameFiles {
|
||||
|
||||
Reference in New Issue
Block a user