后端:游玩计数排序移出互斥锁

- game_play_counter.rs:drain 只负责在锁内取走增量,新增 sort_deltas 在释放锁后排序,避免 O(n log n) 排序阻塞并发 record
This commit is contained in:
2026-10-03 19:19:57 +08:00
parent 9de9f4b419
commit 03f1828561
@@ -157,13 +157,17 @@ impl GamePlayCounter {
return None;
}
state.last_flush_at = now;
Some(drain_pending(&mut state.pending))
let deltas = drain_pending(&mut state.pending);
drop(state);
Some(sort_deltas(deltas))
}
/// 无条件取走全部增量,供关停 flush 使用。
pub fn take_pending(&self) -> Vec<GamePlayCountDelta> {
let mut state = self.lock();
drain_pending(&mut state.pending)
let deltas = drain_pending(&mut state.pending);
drop(state);
sort_deltas(deltas)
}
/// 写库失败时把增量放回,等待下一次 flush。
@@ -207,11 +211,14 @@ impl GamePlayCounter {
}
fn drain_pending(pending: &mut HashMap<String, u64>) -> Vec<GamePlayCountDelta> {
let mut deltas = pending
pending
.drain()
.filter_map(|(game_id, delta)| (delta > 0).then_some(GamePlayCountDelta { game_id, delta }))
.collect::<Vec<_>>();
// 稳定批次顺序,便于测试与日志比对。
.collect()
}
/// 稳定批次顺序,便于测试与日志比对;调用方已释放计数锁,排序不阻塞并发 `record`。
fn sort_deltas(mut deltas: Vec<GamePlayCountDelta>) -> Vec<GamePlayCountDelta> {
deltas.sort_by(|left, right| left.game_id.cmp(&right.game_id));
deltas
}