test(peer-cli): add large exact-transfer coverage
Add deeper peer CLI coverage for file-transfer integrity and multi-peer chunking. The alpha fixture now carries a real renamed RAR archive larger than 100 MB for alienswarm, which gives the chunk planner enough work to split a single game archive across multiple peers. Expose completed chunk source details as a peer event and have the CLI print that event as JSONL. This keeps transfer behavior in lanspread-peer while the CLI remains a harness that reports what the peer runtime did. The Tauri shell logs the event at debug level so the shared PeerEvent enum stays exhaustive. Document the new S13/S14 scenarios and record the manual run evidence, including SHA-256 manifests and the per-peer byte split for the large archive. Test Plan: - just fmt - just test - just peer-cli-build - just clippy - just peer-cli-image - unrar t -idq crates/lanspread-peer-cli/fixtures/fixture-alpha/alienswarm/alienswarm.eti - Manual peer CLI: bravo -> deep-small-client bfbc2 download with matching SHA-256 manifests - Manual peer CLI: alpha -> deep-stage-b alienswarm download with matching SHA-256 manifests - Manual peer CLI: alpha + deep-stage-b -> deep-stage-c alienswarm download with chunk events from both peers and matching SHA-256 manifests Refs: PEER_CLI_SCENARIOS.md S13 S14
This commit is contained in:
@@ -109,21 +109,32 @@ pub async fn download_game_files(
|
||||
}
|
||||
|
||||
for chunk_result in results {
|
||||
if let Err(e) = chunk_result.result {
|
||||
log::warn!(
|
||||
"Failed to download chunk from {}: {e}",
|
||||
chunk_result.peer_addr
|
||||
);
|
||||
if chunk_result.chunk.retry_count < MAX_RETRY_COUNT {
|
||||
let mut retry_chunk = chunk_result.chunk;
|
||||
retry_chunk.retry_count += 1;
|
||||
retry_chunk.last_peer = Some(chunk_result.peer_addr);
|
||||
failed_chunks.push(retry_chunk);
|
||||
} else {
|
||||
last_err = Some(eyre::eyre!(
|
||||
"Max retries exceeded for chunk: {}",
|
||||
chunk_result.chunk.relative_path
|
||||
));
|
||||
match chunk_result.result {
|
||||
Ok(()) => {
|
||||
let _ = tx_notify_ui.send(PeerEvent::DownloadGameFileChunkFinished {
|
||||
id: game_id.to_string(),
|
||||
peer_addr: chunk_result.peer_addr,
|
||||
relative_path: chunk_result.chunk.relative_path,
|
||||
offset: chunk_result.chunk.offset,
|
||||
length: chunk_result.chunk.length,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!(
|
||||
"Failed to download chunk from {}: {e}",
|
||||
chunk_result.peer_addr
|
||||
);
|
||||
if chunk_result.chunk.retry_count < MAX_RETRY_COUNT {
|
||||
let mut retry_chunk = chunk_result.chunk;
|
||||
retry_chunk.retry_count += 1;
|
||||
retry_chunk.last_peer = Some(chunk_result.peer_addr);
|
||||
failed_chunks.push(retry_chunk);
|
||||
} else {
|
||||
last_err = Some(eyre::eyre!(
|
||||
"Max retries exceeded for chunk: {}",
|
||||
chunk_result.chunk.relative_path
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,9 +185,20 @@ pub async fn download_game_files(
|
||||
eyre::bail!("download cancelled for game {game_id}");
|
||||
}
|
||||
|
||||
if let Err(e) = chunk_result.result {
|
||||
log::error!("Retry failed for chunk: {e}");
|
||||
last_err = Some(e);
|
||||
match chunk_result.result {
|
||||
Ok(()) => {
|
||||
let _ = tx_notify_ui.send(PeerEvent::DownloadGameFileChunkFinished {
|
||||
id: game_id.to_string(),
|
||||
peer_addr: chunk_result.peer_addr,
|
||||
relative_path: chunk_result.chunk.relative_path,
|
||||
offset: chunk_result.chunk.offset,
|
||||
length: chunk_result.chunk.length,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Retry failed for chunk: {e}");
|
||||
last_err = Some(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user