Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(uploader): fix for mismatched ordering of instructions #1858

Merged
merged 1 commit into from
Jun 8, 2024
Merged
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
24 changes: 22 additions & 2 deletions sn_client/src/uploader/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,22 +824,42 @@ impl InnerUploader {
let mut cost_map = BTreeMap::new();
let mut current_batch = vec![];

let mut got_a_previous_force_payment = false;
while let Some(payment) = make_payment_receiver.recv().await {
let make_payments = if let Some((item, quote)) = payment {
let xorname = item.xorname();
trace!("Inserted {xorname:?} into cost_map");

current_batch.push((xorname, quote.clone()));
let _ = cost_map.insert(xorname, (quote.1, quote.2, quote.0.to_bytes()));
cost_map.len() >= batch_size
cost_map.len() >= batch_size || got_a_previous_force_payment
} else {
// using None to indicate as all paid.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better update the comment to be :

When the received `payment` is `None`, it notifies no more payment to be made.
There shall be a round of `forced payment` to pay the remaining payments in the cost_map (less than batch_size)
With normal order, there shall be no more payment come in afterwards,
however it could be break due to async channel send.
Hence have to catering such `out-of-order` situation.

let make_payments = !cost_map.is_empty();
trace!("Got a forced forced round of make payment. make_payments: {make_payments:?}");
trace!("Got a forced forced round of make payment.");
// Note: There can be a mismatch of ordering between the main loop and the make payment loop because
// the instructions are sent via a task(channel.send().await). And there is no guarantee for the
// order to come in the same order as they were sent.
//
// We cannot just disobey the instruction inside the child loop, as the mainloop would be expecting
// a result back for a particular instruction.
if !make_payments {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use if cost_map.is_empty() { will be more readable ?

got_a_previous_force_payment = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better rename the var to be cost_map_was_emptied

warn!(
"We were told to force make payment, but cost_map is empty, so we can't do that just yet. Waiting for a task to insert a quote into cost_map"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the msg actually shall be:

We were told cost_map is empty, i.e. no more payment to be maid

)
}

make_payments
};

if make_payments {
// reset force_make_payment
if got_a_previous_force_payment {
info!("A task inserted a quote into cost_map, so we can now make a forced round of payment!");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better change the comment msg to be:

New quote inserted into cost_map, after it was emptied, we shall make a forced round of payment

got_a_previous_force_payment = false;
}

let result = match wallet_client.pay_for_records(&cost_map, verify_store).await
{
Ok((storage_cost, royalty_fees)) => {
Expand Down
Loading