urma_node/service/
worker.rs1use super::Service;
7use crate::{
8 engine_sync::CatchUp, recorded::RecordedError, recorded::record, retrieval::RecordSource,
9};
10use std::{sync::atomic::Ordering, time::Duration};
11
12impl Service {
13 pub const CATCH_UP_BLOCKS: u64 = 256;
15 pub const CATCH_UP_TIME: Duration = Duration::from_secs(5);
17 const PAUSE_STEPS: u32 = 20;
18 const PAUSE_STEP: Duration = Duration::from_millis(100);
19
20 fn stopped(&self) -> bool {
21 self.stop.load(Ordering::Acquire)
22 }
23
24 fn pause(&self) {
26 for _ in 0..Self::PAUSE_STEPS {
27 if self.stopped() {
28 return;
29 }
30 std::thread::sleep(Self::PAUSE_STEP);
31 }
32 }
33
34 pub(super) fn sync_loop(&self) {
35 while !self.stopped() {
36 if !self.sync_round() {
37 self.pause();
38 }
39 }
40 }
41
42 pub(super) fn maintenance_loop(&self) {
43 while !self.stopped() {
44 self.maintenance_round();
45 self.pause();
46 }
47 }
48
49 fn sync_round(&self) -> bool {
52 let catch_up = match self.engine.synchronize_headers_until(&self.stop) {
53 Ok(_) => {
54 self.engine
55 .scan_catch_up(&self.stop, Self::CATCH_UP_BLOCKS, Self::CATCH_UP_TIME)
56 }
57 Err(error) => CatchUp {
58 scanned: 0,
59 outcome: Err(error),
60 },
61 };
62 let result = catch_up.outcome.and_then(|status| {
63 if !self.stopped() {
64 self.engine.resolve_cached_dependency()?;
65 }
66 Ok(status)
67 });
68 record(&self.sync_error, &result);
69 catch_up.scanned > 0
70 }
71
72 fn maintenance_round(&self) {
73 self.discover_peers();
76 self.sync_next_inventory();
77 self.acquire_next_dependency();
78 if !self.stopped() {
81 let result = self.engine.maintain_next_names(&self.stop);
82 record(&self.names_error, &result);
83 }
84 if !self.stopped() {
85 self.retain_next_object();
86 }
87 if !self.stopped() {
89 let result = self.engine.maintain_cache(self.cache_bytes, &self.stop);
90 if let Ok(mut status) = self.cache_status.lock() {
91 match result {
92 Ok(receipt) => {
93 status.receipt = Some(receipt);
94 status.error = None;
95 }
96 Err(cause) => {
97 status.error = Some(RecordedError::now(cause));
98 }
99 }
100 }
101 }
102 }
103
104 fn retain_next_object(&self) {
107 let Some((scratch, slice)) = &self.retention else {
108 return;
109 };
110 let owned = self.record_sources();
111 let sources: Vec<&dyn RecordSource> = owned
112 .iter()
113 .map(|source| -> &dyn RecordSource { source.as_ref() })
114 .collect();
115 let result = self
116 .engine
117 .retain_next_object(&sources, *slice, scratch, &self.stop);
118 record(&self.retention_error, &result);
119 }
120
121 fn acquire_next_dependency(&self) {
122 let Some(sources) = &self.commit_sources else {
123 return;
124 };
125 if self.stopped() {
126 return;
127 }
128 let result = self.engine.resolve_next_dependency(sources, &self.stop);
129 if self.stopped() {
130 return;
131 }
132 record(&self.dependency_error, &result);
133 }
134}