-
Notifications
You must be signed in to change notification settings - Fork 79
Remove uninitialized session state #1014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,56 +3,34 @@ use std::time::SystemTime; | |
| use serde::{Deserialize, Serialize}; | ||
|
|
||
| use super::{ReceiveSession, SessionContext}; | ||
| use crate::error::{InternalReplayError, ReplayError}; | ||
| use crate::output_substitution::OutputSubstitution; | ||
| use crate::persist::SessionPersister; | ||
| use crate::receive::v2::{extract_err_req, InternalSessionError, SessionError}; | ||
| use crate::receive::{common, JsonReply, OriginalPayload, PsbtContext}; | ||
| use crate::{ImplementationError, IntoUrl, PjUri, Request}; | ||
|
|
||
| /// Errors that can occur when replaying a receiver event log | ||
| #[derive(Debug)] | ||
| pub struct ReplayError(InternalReplayError); | ||
|
|
||
| impl std::fmt::Display for ReplayError { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| use InternalReplayError::*; | ||
| match &self.0 { | ||
| InvalidStateAndEvent(state, event) => write!( | ||
| f, | ||
| "Invalid combination of state ({state:?}) and event ({event:?}) during replay", | ||
| ), | ||
| PersistenceFailure(e) => write!(f, "Persistence failure: {e}"), | ||
| } | ||
| } | ||
| } | ||
| impl std::error::Error for ReplayError {} | ||
|
|
||
| impl From<InternalReplayError> for ReplayError { | ||
| fn from(e: InternalReplayError) -> Self { ReplayError(e) } | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| pub(crate) enum InternalReplayError { | ||
| /// Invalid combination of state and event | ||
| InvalidStateAndEvent(Box<ReceiveSession>, Box<SessionEvent>), | ||
| /// Application storage error | ||
| PersistenceFailure(ImplementationError), | ||
| } | ||
|
|
||
| /// Replay a receiver event log to get the receiver in its current state [ReceiveSession] | ||
| /// and a session history [SessionHistory] | ||
| pub fn replay_event_log<P>(persister: &P) -> Result<(ReceiveSession, SessionHistory), ReplayError> | ||
| pub fn replay_event_log<P>( | ||
| persister: &P, | ||
| ) -> Result<(ReceiveSession, SessionHistory), ReplayError<ReceiveSession, SessionEvent>> | ||
| where | ||
| P: SessionPersister, | ||
| P::SessionEvent: Into<SessionEvent> + Clone, | ||
| P::SessionEvent: From<SessionEvent>, | ||
| { | ||
| let logs = persister | ||
| let mut logs = persister | ||
| .load() | ||
| .map_err(|e| InternalReplayError::PersistenceFailure(ImplementationError::new(e)))?; | ||
| let mut receiver = ReceiveSession::Uninitialized; | ||
| let mut history = SessionHistory::default(); | ||
|
|
||
| let mut history = SessionHistory::default(); | ||
| let first_event = logs.next().ok_or(InternalReplayError::NoEvents)?.into(); | ||
| history.events.push(first_event.clone()); | ||
| let mut receiver = match first_event { | ||
| SessionEvent::Created(context) => ReceiveSession::new(context), | ||
| _ => return Err(InternalReplayError::InvalidEvent(Box::new(first_event), None).into()), | ||
| }; | ||
|
Comment on lines
+27
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @nothingmuch that this should be encapsulated in a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could probably even be shared to de-duplicate code between the sender/receiver with some generic fn. Worth it if it's more beautiful and easier to maintain symmetry but not strictly neccessary
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree on both counts (there is potential for refactoring but also since it's all private it doesn't need to be in this PR) |
||
| for event in logs { | ||
| history.events.push(event.clone().into()); | ||
| receiver = receiver.process_event(event.into()).map_err(|e| { | ||
|
|
@@ -211,7 +189,7 @@ pub enum SessionEvent { | |
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use std::time::Duration; | ||
| use std::time::{Duration, SystemTime}; | ||
|
|
||
| use payjoin_test_utils::{BoxError, EXAMPLE_URL}; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mainly out of curiosity what compelled this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC there was a ambigious definition for fmt once I imported Debug.