1
1
use graph:: data:: subgraph:: schema:: SubgraphError ;
2
- use graph:: prelude:: { thiserror, Error , StoreError } ;
2
+ use graph:: env:: ENV_VARS ;
3
+ use graph:: prelude:: { anyhow, thiserror, Error , StoreError } ;
3
4
4
5
pub trait DeterministicError : std:: fmt:: Debug + std:: fmt:: Display + Send + Sync + ' static { }
5
6
6
7
impl DeterministicError for SubgraphError { }
7
8
9
+ impl DeterministicError for StoreError { }
10
+
11
+ impl DeterministicError for anyhow:: Error { }
12
+
8
13
/// An error happened during processing and we need to classify errors into
9
14
/// deterministic and non-deterministic errors. This struct holds the result
10
15
/// of that classification
@@ -26,7 +31,34 @@ impl ProcessingError {
26
31
pub fn is_deterministic ( & self ) -> bool {
27
32
matches ! ( self , ProcessingError :: Deterministic ( _) )
28
33
}
34
+
35
+ pub fn detail ( self , ctx : & str ) -> ProcessingError {
36
+ match self {
37
+ ProcessingError :: Unknown ( e) => {
38
+ let x = e. context ( ctx. to_string ( ) ) ;
39
+ ProcessingError :: Unknown ( x)
40
+ }
41
+ ProcessingError :: Deterministic ( e) => {
42
+ ProcessingError :: Deterministic ( Box :: new ( anyhow ! ( "{e}" ) . context ( ctx. to_string ( ) ) ) )
43
+ }
44
+ ProcessingError :: Canceled => ProcessingError :: Canceled ,
45
+ }
46
+ }
29
47
}
48
+
49
+ /// Similar to `anyhow::Context`, but for `Result<T, ProcessingError>`. We
50
+ /// call the method `detail` to avoid ambiguity with anyhow's `context`
51
+ /// method
52
+ pub trait DetailHelper < T , E > {
53
+ fn detail ( self : Self , ctx : & str ) -> Result < T , ProcessingError > ;
54
+ }
55
+
56
+ impl < T > DetailHelper < T , ProcessingError > for Result < T , ProcessingError > {
57
+ fn detail ( self , ctx : & str ) -> Result < T , ProcessingError > {
58
+ self . map_err ( |e| e. detail ( ctx) )
59
+ }
60
+ }
61
+
30
62
/// Implement this for errors that are always non-deterministic.
31
63
pub ( crate ) trait NonDeterministicErrorHelper < T , E > {
32
64
fn non_deterministic ( self : Self ) -> Result < T , ProcessingError > ;
@@ -43,3 +75,26 @@ impl<T> NonDeterministicErrorHelper<T, StoreError> for Result<T, StoreError> {
43
75
self . map_err ( |e| ProcessingError :: Unknown ( Error :: from ( e) ) )
44
76
}
45
77
}
78
+
79
+ /// Implement this for errors where it depends on the details whether they
80
+ /// are deterministic or not.
81
+ pub ( crate ) trait ClassifyErrorHelper < T , E > {
82
+ fn classify ( self : Self ) -> Result < T , ProcessingError > ;
83
+ }
84
+
85
+ impl < T > ClassifyErrorHelper < T , StoreError > for Result < T , StoreError > {
86
+ fn classify ( self ) -> Result < T , ProcessingError > {
87
+ self . map_err ( |e| {
88
+ if ENV_VARS . mappings . store_errors_are_nondeterministic {
89
+ // Old behavior, just in case the new behavior causes issues
90
+ ProcessingError :: Unknown ( Error :: from ( e) )
91
+ } else {
92
+ if e. is_deterministic ( ) {
93
+ ProcessingError :: Deterministic ( Box :: new ( e) )
94
+ } else {
95
+ ProcessingError :: Unknown ( Error :: from ( e) )
96
+ }
97
+ }
98
+ } )
99
+ }
100
+ }
0 commit comments