substrate_api_client/api/rpc_api/
runtime_update.rs1use crate::{api::Error, rpc::Subscribe, rpc_api::EventSubscriptionFor, Result};
14use alloc::sync::Arc;
15use codec::{Decode, Encode};
16use core::sync::atomic::{AtomicBool, Ordering};
17use serde::de::DeserializeOwned;
18
19pub struct RuntimeUpdateDetector<Hash, Client>
21where
22 Hash: DeserializeOwned + Copy + Decode,
23 Client: Subscribe,
24{
25 subscription: EventSubscriptionFor<Client, Hash>,
26 external_cancellation: Option<Arc<AtomicBool>>,
27}
28
29impl<Hash, Client> RuntimeUpdateDetector<Hash, Client>
30where
31 Hash: DeserializeOwned + Copy + Encode + Decode,
32 Client: Subscribe,
33{
34 pub fn new(subscription: EventSubscriptionFor<Client, Hash>) -> Self {
35 Self { subscription, external_cancellation: None }
36 }
37
38 pub fn new_with_cancellation(
41 subscription: EventSubscriptionFor<Client, Hash>,
42 cancellation: Arc<AtomicBool>,
43 ) -> Self {
44 Self { subscription, external_cancellation: Some(cancellation) }
45 }
46
47 #[maybe_async::maybe_async(?Send)]
50 pub async fn detect_runtime_update(&mut self) -> Result<bool> {
51 'outer: loop {
52 if let Some(canceled) = &self.external_cancellation {
53 if canceled.load(Ordering::SeqCst) {
54 return Ok(false)
55 }
56 }
57 let event_records = self
58 .subscription
59 .next_events_from_metadata()
60 .await
61 .ok_or(Error::Other("Error receiving events".into()))??;
62 let event_iter = event_records.iter();
63 for event in event_iter {
64 if event?.is_code_update() {
65 break 'outer
66 }
67 }
68 }
69 Ok(true)
70 }
71}