use std::collections::BTreeMap;
use chrono::Utc;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OperationContext {
pub trace_id: Option<String>,
pub request_id: Option<String>,
}
impl OperationContext {
pub fn new(trace_id: Option<String>, request_id: Option<String>) -> Self {
Self {
trace_id,
request_id,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OperationEnvelope<T> {
pub operation: String,
pub op_version: String,
pub trace_id: Option<String>,
pub request_id: Option<String>,
pub data: T,
}
impl<T> OperationEnvelope<T> {
pub fn new(operation: &str, op_version: &str, context: &OperationContext, data: T) -> Self {
Self {
operation: operation.to_string(),
op_version: op_version.to_string(),
trace_id: context.trace_id.clone(),
request_id: context.request_id.clone(),
data,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OperationErrorType {
Input,
Validation,
Capacity,
Backend,
Internal,
Contract,
Cancelled,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OperationErrorSeverity {
Warning,
Error,
Fatal,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OperationErrorEnvelope {
pub error_code: String,
pub error_type: OperationErrorType,
pub message: String,
pub operation: String,
pub op_version: String,
pub retryable: bool,
pub severity: OperationErrorSeverity,
pub context: BTreeMap<String, String>,
pub trace_id: Option<String>,
pub request_id: Option<String>,
pub timestamp: String,
}
pub struct OperationErrorSpec<'a> {
pub error_code: &'a str,
pub error_type: OperationErrorType,
pub retryable: bool,
pub severity: OperationErrorSeverity,
}
pub fn operation_error(
operation: &str,
op_version: &str,
context: &OperationContext,
spec: OperationErrorSpec<'_>,
message: impl Into<String>,
error_context: BTreeMap<String, String>,
) -> OperationErrorEnvelope {
OperationErrorEnvelope {
error_code: spec.error_code.to_string(),
error_type: spec.error_type,
message: message.into(),
operation: operation.to_string(),
op_version: op_version.to_string(),
retryable: spec.retryable,
severity: spec.severity,
context: error_context,
trace_id: context.trace_id.clone(),
request_id: context.request_id.clone(),
timestamp: Utc::now().to_rfc3339(),
}
}