game sizes?

This commit is contained in:
2025-11-14 08:12:09 +01:00
parent 6eec74f0f6
commit 567d293455
5 changed files with 152 additions and 6 deletions
+3 -2
View File
@@ -7,10 +7,11 @@ It is designed to run headless other crates (most notably
## Runtime Overview
- `start_peer(game_dir, tx_events)` boots the asynchronous runtime in the
- `start_peer(game_dir, tx_events, peer_game_db)` boots the asynchronous runtime in the
background and returns an `UnboundedSender<PeerCommand>` that the caller uses
for control. The function immediately forwards the supplied game directory via
`PeerCommand::SetGameDir`.
`PeerCommand::SetGameDir` and keeps using the provided `PeerGameDB` so the UI
layer can observe live peer metadata.
- `PeerCommand` represents the small control surface exposed to the UI layer:
`ListGames`, `GetGame`, `DownloadGameFiles`, and `SetGameDir`.
- `PeerEvent` enumerates everything the peer runtime reports back to the UI:
+25 -2
View File
@@ -89,6 +89,7 @@ impl From<eyre::Report> for PeerError {
pub fn start_peer(
game_dir: String,
tx_notify_ui: UnboundedSender<PeerEvent>,
peer_game_db: Arc<RwLock<PeerGameDB>>,
) -> eyre::Result<UnboundedSender<PeerCommand>> {
log::info!("Starting peer system with game directory: {game_dir}");
@@ -97,7 +98,7 @@ pub fn start_peer(
// Start the peer in a background task
let tx_control_clone = tx_control.clone();
tokio::spawn(async move {
if let Err(e) = run_peer(rx_control, tx_notify_ui).await {
if let Err(e) = run_peer(rx_control, tx_notify_ui, peer_game_db).await {
log::error!("Peer system failed: {e}");
}
});
@@ -342,6 +343,27 @@ impl PeerGameDB {
seen.into_values().collect()
}
#[must_use]
pub fn majority_game_size(&self, game_id: &str) -> Option<u64> {
let mut size_counts: HashMap<u64, usize> = HashMap::new();
for peer in self.peers.values() {
if let Some(game) = peer.games.get(game_id) {
if game.size == 0 {
continue;
}
*size_counts.entry(game.size).or_insert(0) += 1;
}
}
size_counts
.into_iter()
.max_by(|(size_a, count_a), (size_b, count_b)| {
count_a.cmp(count_b).then_with(|| size_a.cmp(size_b))
})
.map(|(size, _)| size)
}
/// Validates file sizes across all peers and returns only the files with majority consensus
/// Returns a tuple of (`validated_files`, `peer_whitelist`, `file_peer_map`) where
/// `peer_whitelist` contains peers that have at least one majority-approved file and
@@ -1344,12 +1366,13 @@ impl std::fmt::Debug for PeerCtx {
pub async fn run_peer(
mut rx_control: UnboundedReceiver<PeerCommand>,
tx_notify_ui: UnboundedSender<PeerEvent>,
peer_game_db: Arc<RwLock<PeerGameDB>>,
) -> eyre::Result<()> {
// peer context
let ctx = Ctx {
game_dir: Arc::new(RwLock::new(None)),
local_game_db: Arc::new(RwLock::new(None)),
peer_game_db: Arc::new(RwLock::new(PeerGameDB::new())),
peer_game_db: peer_game_db.clone(),
local_peer_addr: Arc::new(RwLock::new(None)),
downloading_games: Arc::new(RwLock::new(HashSet::new())),
active_downloads: Arc::new(RwLock::new(HashMap::new())),