Skip to main content

sessions

Typed specification

Generated by the pinned ess generate --kind docs from ess. Structural validation establishes consistency; behaviour, storage and cross-record predicates remain implementation obligations.

Proposed supervising session lifecycle; timed enforcement remains a binding obligation.

connectors.sessions is one of connectors's bounded contexts. Back to the index.

Types​

Binding​

connectors.sessions.Binding is a record of four fields:

  • instance_ref — String
  • connection_ref — String
  • admitted_revision — String
  • authority_ref — String

CleanupDecision​

connectors.sessions.CleanupDecision is one of released and unaccounted.

DataLease​

connectors.sessions.DataLease is a record of three fields:

  • issued_at — Timestamp
  • effective_expiry — Timestamp
  • sequence — Integer

GateDecision​

connectors.sessions.GateDecision is one of allow, expired, revoked and unverified.

PeerShutdown​

connectors.sessions.PeerShutdown is one of confirmed and unconfirmed.

Placement​

connectors.sessions.Placement is one of local, direct and relay.

Profile​

connectors.sessions.Profile is one of outbound and inbound_offer.

SessionId​

connectors.sessions.SessionId wraps String and is not interchangeable with one: the whole value of naming it separately is the crossings the model then refuses.

TerminalActor​

connectors.sessions.TerminalActor is one of adapter, application and host.

TerminalFact​

connectors.sessions.TerminalFact is a record of three fields:

  • reason — connectors.sessions.TerminalReason
  • by — connectors.sessions.TerminalActor
  • accepted_at — Timestamp

TerminalReason​

connectors.sessions.TerminalReason is one of remote_hangup, local_close, cancelled, rejected, expired, revoked, lease_expired, media_overload, media_incompatible, transport_lost and error.

Entities​

An entity is what this context is about: something with an identity that outlives any one request, a shape, and a lifecycle. The lifecycle is exhaustive — a move that is not drawn below is a move this specification does not permit, and that is the only way it says so. Every move is labelled with the command that takes it, because a move nothing can trigger is refused rather than drawn.

Session​

connectors.sessions.Session.

An instance is identified by session_id, a connectors.sessions.SessionId. The name is part of the model and not a convention: a view projects the identity under that name, so a projection inventing its own would disagree with the view.

It holds:

  • binding — connectors.sessions.Binding
  • profile — connectors.sessions.Profile
  • placement — connectors.sessions.Placement
  • streams — List<String>
  • data_lease — Optional<connectors.sessions.DataLease>, which may be absent
  • terminal — Optional<connectors.sessions.TerminalFact>, which may be absent

It declares no relation to another entity, and no other entity names it.

No invariant is declared, so nothing here constrains an instance at rest.

Its state is a connectors.sessions.Session.State, one of Closed, Closing, Establishing, Lost, Offered and Ready. That enum is synthesised from the lifecycle rather than declared beside it, so the states a view's filter compares and the states drawn below cannot disagree.

An instance is created in Offered. Closed and Lost are terminal, so an instance may rest there forever. That is declared rather than inferred from having no way out: an entity that cannot leave a state is either finished or stuck, and only its author knows which.

Each move is taken by a declared command outcome, and a move nothing takes is refused as missing_causation rather than left as a state change nobody can trigger:

  • accept — taken by connectors.sessions.AcceptOffer on its accepted outcome
  • ready — taken by connectors.sessions.EstablishReady on its ready outcome
  • permit_data — taken by connectors.sessions.PermitData on its permitted outcome
  • renew — taken by connectors.sessions.RenewDataLease on its renewed outcome
  • deny_ready — taken by connectors.sessions.EstablishReady on its authority-terminated outcome
  • deny_data — taken by connectors.sessions.PermitData on its authority-terminated outcome
  • deny_renewal — taken by connectors.sessions.RenewDataLease on its authority-terminated outcome
  • begin_close — taken by connectors.sessions.BeginClose on its closing outcome
  • close — taken by connectors.sessions.FinishTeardown on its closed outcome
  • cleanup_lost — taken by connectors.sessions.FinishTeardown on its lost outcome
  • continuity_lost — taken by connectors.sessions.LoseContinuity on its lost outcome

An instance is brought into existence by connectors.sessions.OfferSession on its offered outcome.

Illegal transitions are illegal by absence: no rule forbids them, there is simply no arrow, because a rule would be a second place for the same truth to live. A diagram cannot show an absence, so the pairs it does not connect are listed here, derived from the same transitions — anything named below is a move this specification does not permit.

  • Closed may not become Closing
  • Closed may not become Establishing
  • Closed may not become Lost
  • Closed may not become Offered
  • Closed may not become Ready
  • Closing may not become Establishing
  • Closing may not become Offered
  • Closing may not become Ready
  • Establishing may not become Closed
  • Establishing may not become Offered
  • Lost may not become Closed
  • Lost may not become Closing
  • Lost may not become Establishing
  • Lost may not become Offered
  • Lost may not become Ready
  • Offered may not become Closed
  • Offered may not become Ready
  • Ready may not become Closed
  • Ready may not become Establishing
  • Ready may not become Offered

One view projects it: SessionStates.

Views​

A view is what the outside world is promised it can observe. Each one says which instances it contains and how soon it reflects a command that has already returned, because "you can read this" without "how soon" is the promise every flaky suite is built on.

SessionStates​

connectors.sessions.SessionStates.

It reads Session.

It contains every instance of that entity: no filter narrows it, which is a decision somebody made and not a line somebody omitted.

It exposes:

  • session_id — connectors.sessions.SessionId
  • state — connectors.sessions.Session.State
  • terminal — Optional<connectors.sessions.TerminalFact>, which may be absent

It declares no order, so the rows come back in whatever order the implementation has, and two reads may disagree.

Read-your-writes: it is current the moment the command that changed it returns. A caller that has just created an invoice and cannot see it in here has been told a lie about what it did.

A generated scenario asserts it once, immediately after the command: a view promising this and not keeping the promise has to fail the suite rather than be retried until it passes.

Commands​

AcceptOffer​

connectors.sessions.AcceptOffer.

It takes:

  • session_id — connectors.sessions.SessionId

It has two outcomes.

accepted — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Offered to Establishing, along the declared move accept. The instance is the one named by the input field session_id. It emits connectors.sessions.OfferAccepted. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed, Closing, Establishing, Lost and Ready, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

BeginClose​

connectors.sessions.BeginClose.

It takes:

  • session_id — connectors.sessions.SessionId
  • terminal — connectors.sessions.TerminalFact
  • cutoff_due_at — Timestamp
  • teardown_due_at — Timestamp

It has two outcomes.

closing — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Establishing, Offered and Ready to Closing, along the declared move begin_close. The instance is the one named by the input field session_id. It emits connectors.sessions.ClosingBegun. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed, Closing and Lost, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

EstablishReady​

connectors.sessions.EstablishReady.

It takes:

  • session_id — connectors.sessions.SessionId
  • decision — connectors.sessions.GateDecision
  • lease — connectors.sessions.DataLease

It has three outcomes.

ready — Taken when decision == allow holds of the input. It moves a connectors.sessions.Session from Establishing to Ready, along the declared move ready. The instance is the one named by the input field session_id. It emits connectors.sessions.SessionReady. A test reaches it by constructing an input that satisfies that condition.

authority-terminated — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Establishing to Closing, along the declared move deny_ready. The instance is the one named by the input field session_id. It emits connectors.sessions.DataAuthorityTerminated. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed, Closing, Lost, Offered and Ready, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

FinishTeardown​

connectors.sessions.FinishTeardown.

It takes:

  • session_id — connectors.sessions.SessionId
  • decision — connectors.sessions.CleanupDecision
  • peer_shutdown — connectors.sessions.PeerShutdown

It has three outcomes.

closed — Taken when decision == released holds of the input. It moves a connectors.sessions.Session from Closing to Closed, along the declared move close. The instance is the one named by the input field session_id. It emits connectors.sessions.LocalResourcesReleased. A test reaches it by constructing an input that satisfies that condition.

lost — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Closing to Lost, along the declared move cleanup_lost. The instance is the one named by the input field session_id. It emits connectors.sessions.LocalCleanupUnaccounted. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed, Establishing, Lost, Offered and Ready, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

LoseContinuity​

connectors.sessions.LoseContinuity.

It takes:

  • session_id — connectors.sessions.SessionId

It has two outcomes.

lost — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Closing, Establishing, Offered and Ready to Lost, along the declared move continuity_lost. The instance is the one named by the input field session_id. It emits connectors.sessions.ContinuityLost. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed and Lost, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

OfferSession​

connectors.sessions.OfferSession.

It takes:

  • binding — connectors.sessions.Binding
  • profile — connectors.sessions.Profile
  • placement — connectors.sessions.Placement
  • streams — List<String>

It has one outcome.

offered — The default branch, taken when no other outcome's condition matched. It creates a connectors.sessions.Session, which starts in Offered. The new instance's identity is published as session_id on connectors.sessions.SessionOffered. It emits connectors.sessions.SessionOffered. A test reaches it by constructing an input that satisfies no other outcome's condition.

PermitData​

connectors.sessions.PermitData.

It takes:

  • session_id — connectors.sessions.SessionId
  • decision — connectors.sessions.GateDecision
  • direction — String

It has three outcomes.

permitted — Taken when decision == allow holds of the input. It moves a connectors.sessions.Session from Ready to Ready, along the declared move permit_data. The instance is the one named by the input field session_id. It emits connectors.sessions.DataPermitted. A test reaches it by constructing an input that satisfies that condition.

authority-terminated — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Ready to Closing, along the declared move deny_data. The instance is the one named by the input field session_id. It emits connectors.sessions.DataAuthorityTerminated. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed, Closing, Establishing, Lost and Offered, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

RenewDataLease​

connectors.sessions.RenewDataLease.

It takes:

  • session_id — connectors.sessions.SessionId
  • decision — connectors.sessions.GateDecision
  • lease — connectors.sessions.DataLease

It has three outcomes.

renewed — Taken when decision == allow holds of the input. It moves a connectors.sessions.Session from Ready to Ready, along the declared move renew. The instance is the one named by the input field session_id. It emits connectors.sessions.DataLeaseRenewed. A test reaches it by constructing an input that satisfies that condition.

authority-terminated — The default branch, taken when no other outcome's condition matched. It moves a connectors.sessions.Session from Ready to Closing, along the declared move deny_renewal. The instance is the one named by the input field session_id. It emits connectors.sessions.DataAuthorityTerminated. A test reaches it by constructing an input that satisfies no other outcome's condition.

wrong-state — Taken when the subject is resting in a state none of this command's moves start from — a connectors.sessions.Session in Closed, Closing, Establishing, Lost and Offered, which is what is left of the lifecycle once this command's own moves are taken away. The document lists none of it. No entity in this specification changes. It reports connectors.sessions.StateConflict, carrying state. It emits nothing. A test reaches it by driving an instance into one of those states and then issuing the command, because no input selects this branch.

Events​

ClosingBegun​

connectors.sessions.ClosingBegun.

It carries:

  • session_id — connectors.sessions.SessionId
  • terminal — connectors.sessions.TerminalFact
  • cutoff_due_at — Timestamp
  • teardown_due_at — Timestamp

Emitted by connectors.sessions.BeginClose on its closing outcome.

Nothing in this system reacts to it.

ContinuityLost​

connectors.sessions.ContinuityLost.

It carries:

  • session_id — connectors.sessions.SessionId

Emitted by connectors.sessions.LoseContinuity on its lost outcome.

Nothing in this system reacts to it.

DataAuthorityTerminated​

connectors.sessions.DataAuthorityTerminated.

It carries:

  • session_id — connectors.sessions.SessionId
  • decision — connectors.sessions.GateDecision

Emitted by connectors.sessions.EstablishReady on its authority-terminated outcome.

Emitted by connectors.sessions.PermitData on its authority-terminated outcome.

Emitted by connectors.sessions.RenewDataLease on its authority-terminated outcome.

Nothing in this system reacts to it.

DataLeaseRenewed​

connectors.sessions.DataLeaseRenewed.

It carries:

  • session_id — connectors.sessions.SessionId
  • lease — connectors.sessions.DataLease

Emitted by connectors.sessions.RenewDataLease on its renewed outcome.

Nothing in this system reacts to it.

DataPermitted​

connectors.sessions.DataPermitted.

It carries:

  • session_id — connectors.sessions.SessionId
  • direction — String

Emitted by connectors.sessions.PermitData on its permitted outcome.

Nothing in this system reacts to it.

LocalCleanupUnaccounted​

connectors.sessions.LocalCleanupUnaccounted.

It carries:

  • session_id — connectors.sessions.SessionId

Emitted by connectors.sessions.FinishTeardown on its lost outcome.

Nothing in this system reacts to it.

LocalResourcesReleased​

connectors.sessions.LocalResourcesReleased.

It carries:

  • session_id — connectors.sessions.SessionId
  • peer_shutdown — connectors.sessions.PeerShutdown

Emitted by connectors.sessions.FinishTeardown on its closed outcome.

Nothing in this system reacts to it.

OfferAccepted​

connectors.sessions.OfferAccepted.

It carries:

  • session_id — connectors.sessions.SessionId

Emitted by connectors.sessions.AcceptOffer on its accepted outcome.

Nothing in this system reacts to it.

SessionOffered​

connectors.sessions.SessionOffered.

It carries:

  • session_id — connectors.sessions.SessionId

Emitted by connectors.sessions.OfferSession on its offered outcome.

Nothing in this system reacts to it.

SessionReady​

connectors.sessions.SessionReady.

It carries:

  • session_id — connectors.sessions.SessionId
  • lease — connectors.sessions.DataLease

Emitted by connectors.sessions.EstablishReady on its ready outcome.

Nothing in this system reacts to it.

Errors​

StateConflict​

It carries:

  • state — connectors.sessions.Session.State

Reported by connectors.sessions.AcceptOffer on its wrong-state outcome.

Reported by connectors.sessions.BeginClose on its wrong-state outcome.

Reported by connectors.sessions.EstablishReady on its wrong-state outcome.

Reported by connectors.sessions.FinishTeardown on its wrong-state outcome.

Reported by connectors.sessions.LoseContinuity on its wrong-state outcome.

Reported by connectors.sessions.PermitData on its wrong-state outcome.

Reported by connectors.sessions.RenewDataLease on its wrong-state outcome.


Generated from connectors v1 · model digest e1e1672d0af4753cb8f2da6c0b22a7f6ae8ce9f7abc168f86169babdf1325787 · contract digest slice-sha256/2:ec004793a058bf5edc9ff32d85018846bef1611d44fc1835481ed72a8dfe0b1a. Do not edit this file; change the specification and regenerate it with ess generate.