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
//! Infrastructure errors.
//!
//! These are failures of the runtime itself: storage, configuration,
//! serialization. What happened to an effect, including "unknown", is an
//! [`EffectOutcome`](crate::EffectOutcome), never a `RuntimeError`.
use crate::id::{EffectId, IdentityError};
use crate::kind::EffectKind;
use crate::store::StoreError;
/// Why the runtime could not process an effect.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum RuntimeError {
/// The effect name or logical key was invalid.
#[error("invalid effect identity: {0}")]
Identity(#[from] IdentityError),
/// The key was used before with a different input. Returning the earlier
/// effect's result would answer a question nobody asked.
#[error("effect {id} was recorded with a different input")]
InputMismatch {
/// The existing effect.
id: EffectId,
},
/// The key was used before with a different [`EffectKind`].
#[error("effect {id} was recorded as {stored:?}, not {requested:?}")]
KindMismatch {
/// The existing effect.
id: EffectId,
/// The kind on record.
stored: EffectKind,
/// The kind of this call.
requested: EffectKind,
},
/// The input could not be serialized.
#[error("could not serialize the effect input: {0}")]
Input(#[source] serde_json::Error),
/// A committed effect's stored output does not deserialize into the
/// requested type, e.g. because the type changed since it was recorded.
#[error(
"effect {id} committed, but its stored output does not match the requested type: {source}"
)]
Output {
/// The committed effect.
id: EffectId,
/// The deserialization error.
#[source]
source: serde_json::Error,
},
/// The runtime's risk policy requires something the effect lacks, so
/// it was refused before anything was recorded.
#[error("effect `{key}` violates the risk policy: it requires {requirement}")]
PolicyViolation {
/// The effect's `name:key`.
key: String,
/// What the policy requires, e.g. `verification`.
requirement: &'static str,
},
/// No effect has this name and key.
#[error("no effect `{key}` exists")]
NoSuchEffect {
/// The effect's `name:key`.
key: String,
},
/// The handler is registered without `.compensable()`, so its effects
/// cannot be compensated.
#[error("the handler for effect `{name}` is not registered as compensable")]
NotCompensable {
/// The effect name.
name: &'static str,
},
/// No handler of the submitted type is registered under its name.
#[error("no handler registered for effect `{name}`")]
NotRegistered {
/// The effect name.
name: &'static str,
},
/// A stored input no longer deserializes into the handler's input type,
/// e.g. because the type changed since the effect was recorded.
#[error("effect {id}'s stored input does not match its handler's input type: {source}")]
StoredInput {
/// The effect.
id: EffectId,
/// The deserialization error.
#[source]
source: serde_json::Error,
},
/// The store failed. If this happens after the action ran, the effect
/// stays in doubt and recovery will treat its outcome as unknown.
#[error(transparent)]
Store(#[from] StoreError),
/// The runtime's own task failed (a bug in `agent-effects`).
#[error("effect task failed: {0}")]
Internal(String),
}