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:
ddidderr committed 2026-07-21 22:48:19 +02:00
1 parent 29eacabcc0
commit 4b7725db16
5 files changed
+198 -43

No files matched your search

+19 -7
View File
@@ -60,6 +60,7 @@ pub use peer_db::{
use tokio::sync::{
RwLock,
mpsc::{UnboundedReceiver, UnboundedSender},
oneshot,
};
use tokio_util::{sync::CancellationToken, task::TaskTracker};
@@ -228,7 +229,7 @@ pub enum ActiveOperationKind {
}
/// Commands sent to the peer system from the UI.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub enum PeerCommand {
/// Request a list of all available games.
ListGames,
@@ -264,9 +265,14 @@ pub enum PeerCommand {
/// Connect directly to a peer address without waiting for mDNS discovery.
ConnectPeer(SocketAddr),
/// Publish one local Call to Play action to this peer and the LAN.
PublishCallToPlay(CallToPlayEvent),
PublishCallToPlay {
event: CallToPlayEvent,
reply: oneshot::Sender<Result<(), String>>,
},
/// Request the complete in-memory Call to Play history.
GetCallToPlayEvents,
GetCallToPlayEvents {
reply: Option<oneshot::Sender<Vec<CallToPlayEvent>>>,
},
}
/// Optional startup settings for non-GUI callers and tests.
@@ -497,12 +503,18 @@ async fn handle_peer_commands(
PeerCommand::ConnectPeer(addr) => {
handle_connect_peer_command(ctx, tx_notify_ui, addr).await;
}
PeerCommand::PublishCallToPlay(event) => {
call_to_play::publish(ctx, tx_notify_ui, event).await;
PeerCommand::PublishCallToPlay { event, reply } => {
let result = call_to_play::publish(ctx, tx_notify_ui, event)
.await
.map_err(str::to_owned);
let _ = reply.send(result);
}
PeerCommand::GetCallToPlayEvents => {
PeerCommand::GetCallToPlayEvents { reply } => {
let events = ctx.call_to_play.read().await.snapshot();
events::send(tx_notify_ui, PeerEvent::CallToPlayEvents(events));
events::send(tx_notify_ui, PeerEvent::CallToPlayEvents(events.clone()));
if let Some(reply) = reply {
let _ = reply.send(events);
}
}
}
}