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
use hdk::prelude::*;
enum Latest {
Found(Record),
Continue(ActionHash),
NoRecord,
}
pub struct LatestRecord {
pub original_record_hash: ActionHash,
pub record: Record,
pub link: Link,
}
pub fn get_latest_records(
target: Vec<Link>,
option: GetOptions,
) -> ExternResult<Vec<LatestRecord>> {
// Get the original
let initial_details = super::get_details(target, option.clone())?;
initial_details
.into_iter()
.map(|details| {
let mut latest_details = check_updates(details.0)?;
// Follow any updates until there are none
// and choose the update with the latest timestamp
loop {
match latest_details {
// Found an entry with no more updates
Latest::Found(record) => {
return Ok(LatestRecord {
original_record_hash: details.2,
record,
link: details.1,
})
}
// Found an update so follow it
Latest::Continue(action_hash) => {
latest_details = _helper_get_latest_record(action_hash, option.clone())?
}
// There was no original so return the default
Latest::NoRecord => {
return Err(wasm_error!(WasmErrorInner::Guest(
"Unable to find record in dht".to_string()
)))
}
}
}
})
.collect()
}
fn _helper_get_latest_record(target: ActionHash, option: GetOptions) -> ExternResult<Latest> {
let details = get_details(target, option.clone())?;
match details {
Some(details) => check_updates(details),
None => Ok(Latest::NoRecord),
}
}
// Get the actual profile entry
fn check_updates(details: Details) -> ExternResult<Latest> {
match details {
Details::Record(RecordDetails {
record,
updates,
deletes,
..
}) => {
// No updates, we are done
if deletes.len() > 0 {
Ok(Latest::NoRecord)
} else if updates.is_empty() {
Ok(Latest::Found(record))
} else {
// Get the latest update via timestamp
let latest_record = updates
.into_iter()
.fold(
None,
|latest: Option<SignedActionHashed>, update| match latest {
Some(latest) => {
if update.action().timestamp() > latest.action().timestamp() {
Some(update)
} else {
Some(latest)
}
}
None => Some(update),
},
)
.expect("Updates are not empty");
Ok(Latest::Continue(latest_record.action_address().clone()))
}
}
_ => Ok(Latest::NoRecord),
}
}