Add code to handle a race condition around first_preprocess

This commit is contained in:
Luke Parker 2023-08-26 21:09:57 -04:00
parent c245bcdc9b
commit 9adefa4c2c
No known key found for this signature in database
2 changed files with 18 additions and 4 deletions

View file

@ -92,7 +92,7 @@ impl<'a, D: Db> MainDb<'a, D> {
} }
txn.put(key, preprocess); txn.put(key, preprocess);
} }
pub fn first_preprocess<G: Get>(getter: &G, id: [u8; 32]) -> Vec<u8> { pub fn first_preprocess<G: Get>(getter: &G, id: [u8; 32]) -> Option<Vec<u8>> {
getter.get(Self::first_preprocess_key(id)).expect("asked for first preprocess we never saved") getter.get(Self::first_preprocess_key(id))
} }
} }

View file

@ -694,6 +694,20 @@ pub async fn run<D: Db, Pro: Processors, P: P2p>(
let key = key.clone(); let key = key.clone();
let tributaries = tributaries.clone(); let tributaries = tributaries.clone();
async move { async move {
// SubstrateBlockAck is fired before Preprocess, creating a race between Tributary ack
// of the SubstrateBlock and the sending of all Preprocesses
// A similar race condition exists when multiple Batches are present in a block
// This waits until the necessary preprocess is available
let get_preprocess = |raw_db, id| async move {
loop {
let Some(preprocess) = MainDb::<D>::first_preprocess(raw_db, id) else {
sleep(Duration::from_millis(100)).await;
continue;
};
return preprocess;
}
};
let (ids, txs) = match id_type { let (ids, txs) = match id_type {
RecognizedIdType::Block => { RecognizedIdType::Block => {
let block = id; let block = id;
@ -704,7 +718,7 @@ pub async fn run<D: Db, Pro: Processors, P: P2p>(
txs.push(Transaction::BatchPreprocess(SignData { txs.push(Transaction::BatchPreprocess(SignData {
plan: *id, plan: *id,
attempt: 0, attempt: 0,
data: MainDb::<D>::first_preprocess(&raw_db, *id), data: get_preprocess(&raw_db, *id).await,
signed: Transaction::empty_signed(), signed: Transaction::empty_signed(),
})); }));
} }
@ -716,7 +730,7 @@ pub async fn run<D: Db, Pro: Processors, P: P2p>(
vec![Transaction::SignPreprocess(SignData { vec![Transaction::SignPreprocess(SignData {
plan: id, plan: id,
attempt: 0, attempt: 0,
data: MainDb::<D>::first_preprocess(&raw_db, id), data: get_preprocess(&raw_db, id).await,
signed: Transaction::empty_signed(), signed: Transaction::empty_signed(),
})], })],
), ),