-
-
Notifications
You must be signed in to change notification settings - Fork 119
/
validation.rs
120 lines (101 loc) · 3.32 KB
/
validation.rs
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
115
116
117
118
119
120
use std::{collections::BTreeMap, error::Error, thread};
use crate::{
objects::{BehindHandle, Object, ObjectSet},
storage::ObjectId,
validate::ValidationError,
};
use super::State;
/// Errors that occurred while validating the objects inserted into the stores
#[derive(Default)]
pub struct Validation {
/// All unhandled validation errors
pub errors: BTreeMap<ObjectId, ValidationError>,
}
impl Drop for Validation {
fn drop(&mut self) {
let num_errors = self.errors.len();
if num_errors > 0 {
println!(
"Dropping `Validation` with {num_errors} unhandled validation \
errors:"
);
for err in self.errors.values() {
println!("{}", err);
// Once `Report` is stable, we can replace this:
// https://doc.rust-lang.org/std/error/struct.Report.html
let mut source = err.source();
while let Some(err) = source {
println!("Caused by:\n\t{err}");
source = err.source();
}
}
if !thread::panicking() {
panic!();
}
}
}
}
impl State for Validation {
type Command = ValidationCommand;
type Event = ValidationEvent;
fn decide(&self, command: Self::Command, events: &mut Vec<Self::Event>) {
let mut errors = Vec::new();
match command {
ValidationCommand::ValidateObject { object } => {
object.validate(&mut errors);
for err in errors {
events.push(ValidationEvent::ValidationFailed {
object: object.clone(),
err,
});
}
}
ValidationCommand::OnlyValidate { objects } => {
events.push(ValidationEvent::ClearErrors);
for object in objects {
object.validate(&mut errors);
for err in errors.drain(..) {
events.push(ValidationEvent::ValidationFailed {
object: object.clone(),
err,
});
}
}
}
}
}
fn evolve(&mut self, event: &Self::Event) {
match event {
ValidationEvent::ValidationFailed { object, err } => {
self.errors.insert(object.id(), err.clone());
}
ValidationEvent::ClearErrors => self.errors.clear(),
}
}
}
/// The command accepted by the validation service
pub enum ValidationCommand {
/// Validate the provided object
ValidateObject {
/// The object to validate
object: Object<BehindHandle>,
},
/// Validate the provided objects, discard all other validation errors
OnlyValidate {
/// The objects to validate
objects: ObjectSet,
},
}
/// The event produced by the validation service
#[derive(Clone)]
pub enum ValidationEvent {
/// Validation of an object failed
ValidationFailed {
/// The object for which validation failed
object: Object<BehindHandle>,
/// The validation error
err: ValidationError,
},
/// All stored validation errors are being cleared
ClearErrors,
}