1use std::collections::BTreeMap;
2
3use chrono::Utc;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct OperationContext {
8 pub trace_id: Option<String>,
9 pub request_id: Option<String>,
10}
11
12impl OperationContext {
13 pub fn new(trace_id: Option<String>, request_id: Option<String>) -> Self {
14 Self {
15 trace_id,
16 request_id,
17 }
18 }
19}
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22pub struct OperationEnvelope<T> {
23 pub operation: String,
24 pub op_version: String,
25 pub trace_id: Option<String>,
26 pub request_id: Option<String>,
27 pub data: T,
28}
29
30impl<T> OperationEnvelope<T> {
31 pub fn new(operation: &str, op_version: &str, context: &OperationContext, data: T) -> Self {
32 Self {
33 operation: operation.to_string(),
34 op_version: op_version.to_string(),
35 trace_id: context.trace_id.clone(),
36 request_id: context.request_id.clone(),
37 data,
38 }
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
43#[serde(rename_all = "snake_case")]
44pub enum OperationErrorType {
45 Input,
46 Validation,
47 Capacity,
48 Backend,
49 Internal,
50 Contract,
51 Cancelled,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
55#[serde(rename_all = "snake_case")]
56pub enum OperationErrorSeverity {
57 Warning,
58 Error,
59 Fatal,
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
63pub struct OperationErrorEnvelope {
64 pub error_code: String,
65 pub error_type: OperationErrorType,
66 pub message: String,
67 pub operation: String,
68 pub op_version: String,
69 pub retryable: bool,
70 pub severity: OperationErrorSeverity,
71 pub context: BTreeMap<String, String>,
72 pub trace_id: Option<String>,
73 pub request_id: Option<String>,
74 pub timestamp: String,
75}
76
77pub struct OperationErrorSpec<'a> {
78 pub error_code: &'a str,
79 pub error_type: OperationErrorType,
80 pub retryable: bool,
81 pub severity: OperationErrorSeverity,
82}
83
84pub fn operation_error(
85 operation: &str,
86 op_version: &str,
87 context: &OperationContext,
88 spec: OperationErrorSpec<'_>,
89 message: impl Into<String>,
90 error_context: BTreeMap<String, String>,
91) -> OperationErrorEnvelope {
92 OperationErrorEnvelope {
93 error_code: spec.error_code.to_string(),
94 error_type: spec.error_type,
95 message: message.into(),
96 operation: operation.to_string(),
97 op_version: op_version.to_string(),
98 retryable: spec.retryable,
99 severity: spec.severity,
100 context: error_context,
101 trace_id: context.trace_id.clone(),
102 request_id: context.request_id.clone(),
103 timestamp: Utc::now().to_rfc3339(),
104 }
105}