@@ -222,15 +222,23 @@ impl PresenceExpiry {
222222 Self { last_check : 0.0 }
223223 }
224224
225- /// Maybe expire stale users. Returns the number removed (0 if check was skipped).
226- pub fn maybe_expire ( & mut self , users : & mut Vec < RoomUser > , now : f64 ) -> usize {
225+ /// Maybe expire stale users. Returns removed users so callers can clean up
226+ /// their scene objects. Empty if the check was throttled.
227+ pub fn maybe_expire ( & mut self , users : & mut Vec < RoomUser > , now : f64 ) -> Vec < RoomUser > {
227228 if now - self . last_check < EXPIRY_CHECK_INTERVAL {
228- return 0 ;
229+ return Vec :: new ( ) ;
229230 }
230231 self . last_check = now;
231- let before = users. len ( ) ;
232- users. retain ( |u| u. is_self || ( now - u. last_seen ) < STALE_TIMEOUT ) ;
233- before - users. len ( )
232+ let mut expired = Vec :: new ( ) ;
233+ let mut i = 0 ;
234+ while i < users. len ( ) {
235+ if !users[ i] . is_self && ( now - users[ i] . last_seen ) >= STALE_TIMEOUT {
236+ expired. push ( users. swap_remove ( i) ) ;
237+ } else {
238+ i += 1 ;
239+ }
240+ }
241+ expired
234242 }
235243}
236244
@@ -266,18 +274,19 @@ mod tests {
266274 let mut expiry = PresenceExpiry :: new ( ) ;
267275
268276 // First call at t=5 — too soon (< 10s from init at 0.0), skipped
269- assert_eq ! ( expiry. maybe_expire( & mut users, 5.0 ) , 0 ) ;
277+ assert ! ( expiry. maybe_expire( & mut users, 5.0 ) . is_empty ( ) ) ;
270278 assert_eq ! ( users. len( ) , 3 ) ; // no one removed
271279
272280 // At t=100 — enough time, bob is stale
273- let removed = expiry. maybe_expire ( & mut users, 100.0 ) ;
274- assert_eq ! ( removed, 1 ) ;
281+ let expired = expiry. maybe_expire ( & mut users, 100.0 ) ;
282+ assert_eq ! ( expired. len( ) , 1 ) ;
283+ assert_eq ! ( expired[ 0 ] . display_name, "bob" ) ;
275284 assert_eq ! ( users. len( ) , 2 ) ;
276285 assert ! ( users. iter( ) . any( |u| u. is_self) ) ;
277286 assert ! ( users. iter( ) . any( |u| u. display_name == "alice" ) ) ;
278287
279288 // Immediately again at t=101 — throttled, skipped
280- assert_eq ! ( expiry. maybe_expire( & mut users, 101.0 ) , 0 ) ;
289+ assert ! ( expiry. maybe_expire( & mut users, 101.0 ) . is_empty ( ) ) ;
281290 }
282291
283292 #[ test]
0 commit comments