1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::{time::Duration, time::Instant};
use crate::driver::{
AbortSignal, DefaultAbortSignal, DefaultDriver, Driver, TelemetryEvent, TreeStats,
};
use crate::error::Error;
use crate::merge::{MergedRoot, Merger};
use crate::tree::Tree;
pub trait Store {
type Ok;
type Error: From<Error>;
fn fetch_local_tree(&self) -> Result<Tree, Self::Error>;
fn fetch_remote_tree(&self) -> Result<Tree, Self::Error>;
fn apply<'t>(&mut self, root: MergedRoot<'t>) -> Result<Self::Ok, Self::Error>;
fn merge(&mut self) -> Result<Self::Ok, Self::Error> {
self.merge_with_driver(&DefaultDriver, &DefaultAbortSignal)
}
fn merge_with_driver(
&mut self,
driver: &impl Driver,
signal: &impl AbortSignal,
) -> Result<Self::Ok, Self::Error> {
signal.err_if_aborted()?;
debug!(driver, "Building local tree");
let (local_tree, time) = with_timing(|| self.fetch_local_tree())?;
driver.record_telemetry_event(TelemetryEvent::FetchLocalTree(TreeStats {
items: local_tree.size(),
problems: local_tree.problems().counts(),
time,
}));
trace!(driver, "Built local tree from mirror\n{}", local_tree);
signal.err_if_aborted()?;
debug!(driver, "Building remote tree");
let (remote_tree, time) = with_timing(|| self.fetch_remote_tree())?;
driver.record_telemetry_event(TelemetryEvent::FetchRemoteTree(TreeStats {
items: remote_tree.size(),
problems: remote_tree.problems().counts(),
time,
}));
trace!(driver, "Built remote tree from mirror\n{}", remote_tree);
signal.err_if_aborted()?;
debug!(driver, "Building merged tree");
let merger = Merger::with_driver(driver, signal, &local_tree, &remote_tree);
let (merged_root, time) = with_timing(|| merger.merge())?;
driver.record_telemetry_event(TelemetryEvent::Merge(time, *merged_root.counts()));
trace!(
driver,
"Built new merged tree\n{}\nDelete Locally: [{}]\nDelete Remotely: [{}]",
merged_root.node().to_ascii_string(),
merged_root
.local_deletions()
.map(|d| d.guid.as_str())
.collect::<Vec<_>>()
.join(", "),
merged_root
.remote_deletions()
.map(|d| d.guid.as_str())
.collect::<Vec<_>>()
.join(", ")
);
signal.err_if_aborted()?;
debug!(driver, "Applying merged tree");
let (result, time) = with_timing(|| self.apply(merged_root))?;
driver.record_telemetry_event(TelemetryEvent::Apply(time));
Ok(result)
}
}
fn with_timing<T, E>(run: impl FnOnce() -> Result<T, E>) -> Result<(T, Duration), E> {
let now = Instant::now();
run().map(|value| (value, now.elapsed()))
}