fix(call-to-play): compact expired snapshots
Expired call histories were removed on the next store insertion, so an otherwise idle peer could continue carrying stale payload through handshakes after the five-minute UI retention ended. Run the same inactive-call compaction before local and handshake snapshots. This makes the expiry boundary exact without trimming any event from an active call. Test Plan: - `just fmt` -- passed - `just clippy` -- passed - `just test` -- passed, 147 peer tests - `git diff --cached --check` -- passed
This commit is contained in:
@@ -30,7 +30,12 @@ pub(crate) struct CallToPlayStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CallToPlayStore {
|
impl CallToPlayStore {
|
||||||
pub(crate) fn snapshot(&self) -> Vec<CallToPlayEvent> {
|
pub(crate) fn snapshot(&mut self) -> Vec<CallToPlayEvent> {
|
||||||
|
self.snapshot_at(now_ms())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn snapshot_at(&mut self, now: i64) -> Vec<CallToPlayEvent> {
|
||||||
|
self.compact_inactive_calls(now);
|
||||||
self.events.clone()
|
self.events.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,8 +439,6 @@ mod tests {
|
|||||||
.insert(create_event("create"))
|
.insert(create_event("create"))
|
||||||
.expect("active call should fit");
|
.expect("active call should fit");
|
||||||
|
|
||||||
store.compact_inactive_calls(TEST_NOW + 5 * 60_000 + 60_001);
|
assert!(store.snapshot_at(TEST_NOW + 5 * 60_000 + 60_001).is_empty());
|
||||||
|
|
||||||
assert!(store.snapshot().is_empty());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ async fn handle_peer_commands(
|
|||||||
let _ = reply.send(result);
|
let _ = reply.send(result);
|
||||||
}
|
}
|
||||||
PeerCommand::GetCallToPlayEvents { reply } => {
|
PeerCommand::GetCallToPlayEvents { reply } => {
|
||||||
let events = ctx.call_to_play.read().await.snapshot();
|
let events = ctx.call_to_play.write().await.snapshot();
|
||||||
events::send(tx_notify_ui, PeerEvent::CallToPlayEvents(events.clone()));
|
events::send(tx_notify_ui, PeerEvent::CallToPlayEvents(events.clone()));
|
||||||
if let Some(reply) = reply {
|
if let Some(reply) = reply {
|
||||||
let _ = reply.send(events);
|
let _ = reply.send(events);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ pub(super) async fn build_hello_ack(ctx: &PeerCtx) -> eyre::Result<HelloAck> {
|
|||||||
let library_guard = ctx.local_library.read().await;
|
let library_guard = ctx.local_library.read().await;
|
||||||
build_library_snapshot(&library_guard)
|
build_library_snapshot(&library_guard)
|
||||||
};
|
};
|
||||||
let call_to_play_events = ctx.call_to_play.read().await.snapshot();
|
let call_to_play_events = ctx.call_to_play.write().await.snapshot();
|
||||||
Ok(HelloAck {
|
Ok(HelloAck {
|
||||||
peer_id: ctx.peer_id.as_ref().clone(),
|
peer_id: ctx.peer_id.as_ref().clone(),
|
||||||
proto_ver: PROTOCOL_VERSION,
|
proto_ver: PROTOCOL_VERSION,
|
||||||
@@ -84,7 +84,7 @@ async fn build_hello_from_state(ctx: &HandshakeCtx) -> eyre::Result<Hello> {
|
|||||||
let library_guard = ctx.local_library.read().await;
|
let library_guard = ctx.local_library.read().await;
|
||||||
build_library_snapshot(&library_guard)
|
build_library_snapshot(&library_guard)
|
||||||
};
|
};
|
||||||
let call_to_play_events = ctx.call_to_play.read().await.snapshot();
|
let call_to_play_events = ctx.call_to_play.write().await.snapshot();
|
||||||
Ok(Hello {
|
Ok(Hello {
|
||||||
peer_id: ctx.peer_id.as_ref().clone(),
|
peer_id: ctx.peer_id.as_ref().clone(),
|
||||||
proto_ver: PROTOCOL_VERSION,
|
proto_ver: PROTOCOL_VERSION,
|
||||||
@@ -538,7 +538,7 @@ mod tests {
|
|||||||
.expect("current protocol hello should be accepted");
|
.expect("current protocol hello should be accepted");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ctx.call_to_play.read().await.snapshot(),
|
ctx.call_to_play.write().await.snapshot(),
|
||||||
[call_to_play_event()]
|
[call_to_play_event()]
|
||||||
);
|
);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
|
|||||||
Reference in New Issue
Block a user