Skip to content

Expired sessions should close the session #1049

Closed

Description

@arminsabouri

I am realizing the behavior for handling an expired session is different when replaying and normal state machine progressions.

if SystemTime::now() > self.context.expiry {
            return Err(InternalSessionError::Expired(self.context.expiry).into());
        }

In most cases we return an error instead of closing the session and pushing an error event.

Originally posted by @arminsabouri in #1036 (comment)

Activity

  1. added this to the payjoin-1.0 milestone on Sep 8, 2025
  2. self-assigned this
    on Sep 8, 2025
  3. DanGould commented on Sep 8, 2025

    @DanGould
    Member

    don't we want to throw an error and then have the error handler produce an event? Or is that separated where you think it should be unified?

  4. arminsabouri commented on Sep 8, 2025

    @arminsabouri
    ContributorAuthor

    don't we want to throw an error and then have the error handler produce an event? Or is that separated where you think it should be unified?

    yes this is essentially what I am thinking. Typestate should return a fatal state transition variant which closes the session and saves a session expired event.

  5. DanGould commented on Sep 8, 2025

    @DanGould
    Member

    I'm a bit unclear, seems like a "yes" answer to an either-or question. You think separated or unified error production + event production?

  6. arminsabouri commented on Sep 8, 2025

    @arminsabouri
    ContributorAuthor

    don't we want to throw an error

    I dont think we should be returning an Err. I want to be clear about that. Instead doing what I suggested above.

    Wdym by seperate or unified? Replaying will still check for expired session after a replaying all events. So in that sense its seperate

  7. arminsabouri commented on Sep 8, 2025

    @arminsabouri
    ContributorAuthor

    Related comment: #1036 (comment)

  8. benalleng commented on Sep 17, 2025

    @benalleng
    Collaborator

    Is this something we would like to use the SessionEvent::Closed from #1078 with expiration as the follow up reason?

  9. arminsabouri commented on Sep 18, 2025

    @arminsabouri
    ContributorAuthor

    Is this something we would like to use the SessionEvent::Closed from #1078 with expiration as the follow up reason?

    yes. I think a new Expired variant on SessionOutcome would make the most sense.

  10. nothingmuch commented on Sep 18, 2025

    @nothingmuch
    Contributor

    if we adhere to the principle that only primary information becomes an event, then knowing when the session's expiry (part of its context) is sufficient in principle, and no new information would imply no outcome event.

    however, this assumes the system clock is monotone... if the system clock rewinds after a session is considered expired, then it might be considered active again afterwards. i don't think that is a situation worth worrying about, especially since the completed_at column would be set when the the expiration condition is detected

    on the other hand if we do add an expired outcome event, then that's one more thing to keep in sync with the completed_at column, if it's ever not in sync than the session data would be in an inconsistent state (easy to repair such an inconsistency but that doesn't strongly adhere to the make-invallid-state-unrepresentable maxim)

    so i think my vote is that we don't need an Expired outcome, it's enough to just set completed at and reserve the SessionEvent::Closed event variants to record information that is otherwise missing (#1078 (comment)) but i'm not strongly against it if it makes the code more readable for example

  11. arminsabouri commented on Sep 22, 2025

    @arminsabouri
    ContributorAuthor

    Follow up on the above: State machine should generate the expired outcome (state transition object), the persister will close the session when processing this outcome.

  12. arminsabouri commented on Sep 22, 2025

    @arminsabouri
    ContributorAuthor

    This issue is blocked by #1060

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

apireceivereceiving payjoinsendsending payjoin

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions