use crate::service::TxStatusMessage; use fuel_core_types::services::txpool::TransactionStatus; #[derive(Debug, Clone, PartialEq, Eq)] pub(super) enum State { Empty, Initial(TransactionStatus), EarlySuccess(TransactionStatus), Success(TransactionStatus, TransactionStatus), Failed, LateFailed(TransactionStatus), SenderClosed(TransactionStatus), Closed, } #[derive(Debug)] pub struct TxUpdateStream { state: State, } impl TxUpdateStream { pub fn new() -> Self { Self { state: State::Empty, } } #[cfg(test)] pub(super) fn with_state(state: State) -> Self { Self { state } } #[cfg(test)] pub(super) fn state(&self) -> &State { &self.state } pub fn add_msg(&mut self, msg: TxStatusMessage) { let state = std::mem::replace(&mut self.state, State::Empty); self.state = match state { State::Empty => match msg { TxStatusMessage::Status(TransactionStatus::Submitted { time }) => { State::Initial(TransactionStatus::Submitted { time }) } TxStatusMessage::Status(s) => State::EarlySuccess(s), TxStatusMessage::FailedStatus => State::Failed, }, State::Initial(s1) => { if let TxStatusMessage::Status(s2) = msg { State::Success(s1, s2) } else { State::LateFailed(s1) } } s => s, }; } pub fn add_failure(&mut self) { let state = std::mem::replace(&mut self.state, State::Empty); self.state = match state { State::Initial(s) => State::LateFailed(s), State::Empty => State::Failed, s => s, }; } pub fn close_recv(&mut self) { self.state = State::Closed; } pub fn try_next(&mut self) -> Option { let state = std::mem::replace(&mut self.state, State::Empty); match state { State::Initial(s) => Some(TxStatusMessage::Status(s)), State::Empty => None, State::EarlySuccess(s) | State::SenderClosed(s) => { self.state = State::Closed; Some(TxStatusMessage::Status(s)) } State::Failed => { self.state = State::Closed; Some(TxStatusMessage::FailedStatus) } State::LateFailed(s) => { self.state = State::Failed; Some(TxStatusMessage::Status(s)) } State::Success(s1, s2) => { self.state = State::SenderClosed(s2); Some(TxStatusMessage::Status(s1)) } State::Closed => { self.state = State::Closed; None } } } pub fn is_closed(&self) -> bool { matches!(self.state, State::Closed) } }