game sizes?
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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())),
|
||||
|
||||
Reference in New Issue
Block a user