use chrono::{Utc, DateTime}; use serde::{Serialize, Deserialize}; #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Clone)] pub struct Pending { update_id: u64, meta: M, enqueued_at: DateTime, } impl Pending { pub fn new(meta: M, update_id: u64) -> Self { Self { enqueued_at: Utc::now(), meta, update_id, } } pub fn processing(self) -> Processing { Processing { from: self, started_processing_at: Utc::now(), } } pub fn abort(self) -> Aborted { Aborted { from: self, aborted_at: Utc::now(), } } pub fn meta(&self) -> &M { &self.meta } pub fn id(&self) -> u64 { self.update_id } } #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Clone)] pub struct Processed { success: N, processed_at: DateTime, #[serde(flatten)] from: Processing, } impl Processed { pub fn id(&self) -> u64 { self.from.id() } } #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Clone)] pub struct Processing { #[serde(flatten)] from: Pending, started_processing_at: DateTime, } impl Processing { pub fn id(&self) -> u64 { self.from.id() } pub fn meta(&self) -> &M { self.from.meta() } pub fn process(self, meta: N) -> Processed { Processed { success: meta, from: self, processed_at: Utc::now(), } } pub fn fail(self, error: E) -> Failed { Failed { from: self, error, failed_at: Utc::now(), } } } #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Clone)] pub struct Aborted { #[serde(flatten)] from: Pending, aborted_at: DateTime, } impl Aborted { pub fn id(&self) -> u64 { self.from.id() } } #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Clone)] pub struct Failed { #[serde(flatten)] from: Processing, error: E, failed_at: DateTime, } impl Failed { pub fn id(&self) -> u64 { self.from.id() } } #[derive(Debug, PartialEq, Eq, Hash, Serialize)] #[serde(tag = "status")] pub enum UpdateStatus { Processing(Processing), Pending(Pending), Processed(Processed), Aborted(Aborted), Failed(Failed), } impl UpdateStatus { pub fn id(&self) -> u64 { match self { UpdateStatus::Processing(u) => u.id(), UpdateStatus::Pending(u) => u.id(), UpdateStatus::Processed(u) => u.id(), UpdateStatus::Aborted(u) => u.id(), UpdateStatus::Failed(u) => u.id(), } } } impl From> for UpdateStatus { fn from(other: Pending) -> Self { Self::Pending(other) } } impl From> for UpdateStatus { fn from(other: Aborted) -> Self { Self::Aborted(other) } } impl From> for UpdateStatus { fn from(other: Processed) -> Self { Self::Processed(other) } } impl From> for UpdateStatus { fn from(other: Processing) -> Self { Self::Processing(other) } } impl From> for UpdateStatus { fn from(other: Failed) -> Self { Self::Failed(other) } }