# `Lightstreamer.Session`
[🔗](https://github.com/ktec/lightstreamer/blob/v0.1.0/lib/lightstreamer/session.ex#L1)

The connection and session lifecycle state machine.

One session owns one WebSocket via a `Lightstreamer.Transport` — a protocol
constraint (TLCP allows one stream connection per session), not a design
choice. The process is a thin router: it feeds inbound text through
`Lightstreamer.Protocol.Frame`, merges update deltas with
`Lightstreamer.Protocol.Update`, and forwards events to each subscription's
owner pid. No consumer logic ever runs here.

States: `:connecting → :ws_handshake → :creating | :binding → :streaming`,
plus `:backoff` between recovery attempts and `:failed` holding an initial
connection error until the `connect/2` caller collects it.

Lifecycle rules:

  * `LOOP` — the server asks for a rebind: new transport, `wsok` +
    `bind_session`. Silent, and per-item field state is **preserved**
    (the session survives).
  * Keepalive expiry / socket loss — try `bind_session` first (cheap, keeps
    the server-side session); if the bind is refused, fall back to a full
    `create_session`.
  * `END` / re-create — the session is dead: fresh `create_session`, all
    subscriptions re-issued with their original parameters and their
    per-item state **reset**, so stale merges cannot survive into the new
    snapshot (owners see `snapshot?: true` again).
  * Backoff between failed recovery attempts is exponential with jitter,
    capped. `CONERR` code 1 (bad credentials) is never retried —
    retrying bad credentials is how upstream accounts get locked.
  * `reconnect: :never` turns any of the above failures into notification
    and a stop.

Use through `Lightstreamer` — this module is not called directly.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
