Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions ant-core/src/data/client/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,13 @@ pub struct PaidChunk {
pub struct WaveResult {
/// Successfully stored chunk addresses.
pub stored: Vec<XorName>,
/// Chunks that failed to store after all retries.
/// Chunks that failed to store after all retries (address + error text).
pub failed: Vec<(XorName, String)>,
/// The paid [`PaidChunk`]s for the entries in `failed`, retained so a
/// caller can re-drive storage against the *same* on-chain payment without
/// re-quoting or re-paying. Parallel to `failed` (same order). Empty when
/// `failed` is empty.
pub failed_chunks: Vec<PaidChunk>,
/// Sum of store-RPC attempts across all chunks in this wave (>= stored.len() + failed.len()).
pub chunk_attempts_total: usize,
/// Per-chunk wall-clock (ms) from first attempt to successful store. Only populated for stored chunks.
Expand Down Expand Up @@ -854,6 +859,7 @@ impl Client {
let result = WaveResult {
stored,
failed: Vec::new(),
failed_chunks: Vec::new(),
chunk_attempts_total,
store_durations_ms,
retries_per_chunk,
Expand All @@ -863,13 +869,19 @@ impl Client {
}

if attempt == MAX_RETRIES {
let failed = failed_this_round
.into_iter()
.map(|(c, e)| (c.address, e))
.collect();
// Keep the paid chunks (not just their addresses) so a
// post-payment store failure stays retryable without paying
// again — the proofs live in each `PaidChunk`.
let mut failed = Vec::with_capacity(failed_this_round.len());
let mut failed_chunks = Vec::with_capacity(failed_this_round.len());
for (chunk, err) in failed_this_round {
failed.push((chunk.address, err));
failed_chunks.push(chunk);
}
let result = WaveResult {
stored,
failed,
failed_chunks,
chunk_attempts_total,
store_durations_ms,
retries_per_chunk,
Expand All @@ -890,6 +902,7 @@ impl Client {
let result = WaveResult {
stored,
failed: Vec::new(),
failed_chunks: Vec::new(),
chunk_attempts_total,
store_durations_ms,
retries_per_chunk,
Expand Down
6 changes: 6 additions & 0 deletions ant-core/src/data/client/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ impl Client {
chunk_count,
)
.await?;
// `merkle_upload_chunks` no longer re-raises `outcome.fatal`, so the
// whole-file data path re-raises it here to keep its all-or-nothing
// contract (a non-quorum error aborts the upload).
if let Some(e) = outcome.fatal {
return Err(e);
}
// Unlike `FileUploadResult`, `DataUploadResult` cannot express a
// partial store, and the returned `data_map` is unusable unless
// every chunk landed (download fails on any missing chunk). So a
Expand Down
Loading
Loading