server-core/network/presence
packages/server/src/network/presence
Purpose
Presence server internals.Public surface
AgentPresenceEntry
Interface
AgentEndpointResolver’s module JSDoc), so the entry tracks the
full set of live connections + the active leases keyed by which
connection holds them.
liveConns— every WS connection the agent is currently authenticated on.leasesByConn— per-connection breakdown of active leases (GRANTED or CLAIMED), keyed by connection. When a connection disconnects, its bucket is dropped wholesale so the leases bound to the dead conn don’t keep the agent inworkingforever.
leasesByConn MUST be present in
liveConns. A lease callback that arrives bound to a
recipientConnId not in liveConns is a fast-reconnect race ghost
and no-ops (audited as LeaseCallbackFromStaleConnection).
Status derivation: working if any live connection holds at least
one active lease; online if the entry exists but holds no active
leases anywhere; offline if the entry is absent. See
deriveEntryStatus.
The multi-connection shape is correctness-by-construction: a second
simultaneous connection ADDS to liveConns rather than clobbering
the agent’s lease set, so the original conn’s active leases stay
accounted-for.
“offline” is represented by entry absence; presence state NEVER
holds an entry whose liveConns is empty.
agentPresenceSubscribe
Variable
appPresenceSubscribe
Variable
DerivedPresenceStatus
TypeAlias
online— connected, no active lease.working— connected, ≥1 lease in GRANTED or CLAIMED.offline— WS closed (no entry in presence state).
deriveEntryStatus
Function
leasesByConn and returns working for any non-zero
count, else online.
LeaseTransitionObserver
Interface
LeaseRegistry calls at each transition
that crosses the lease’s “active for presence” boundary. “Active”
means GRANTED or CLAIMED — the two states that count toward
working.
This is the NARROW contract LeaseRegistry depends on. The registry
sees only these two methods, not the full PresenceService surface.
onLeaseActiveBeginfires onPENDING → GRANTEDonly.HOLD → PENDING → GRANTED(verdict re-try) eventually reaches GRANTED, at which point this fires; the intermediate HOLD never enters the active set.onLeaseActiveEndfires on the lease’s first exit from GRANTED-or-CLAIMED into a terminal state —CLAIMED → CONSUMED,GRANTED → EXPIRED(TTL),GRANTED → EXPIRED-on-disconnect. ACLAIMED → GRANTEDrollback is NOT an end event (still active). APENDING → DENIED | ABANDONED | HOLDtransition is NOT an end event (never entered the active set).
never — presence is best-effort and MUST
NOT propagate failure to the lease registry mutator.
recipientConnId parameter. Threads the lease’s
binding.recipientConnectionId so the service can check
recipientConnId ∈ entry.liveConns and drop fast-reconnect-race
ghost callbacks. The fast-reconnect race: agent A disconnects on
connId-1, the disconnect handler drops connId-1 from A’s
liveConns, A reconnects fast on connId-2, then the pending
leaseRegistry.abandon(connId-1) synchronously fires
onLeaseActiveEnd for each of A’s old leases. Without connId
threading, those callbacks would mutate against the surviving
connection; the check makes them no-op audits instead.
noopLeaseTransitionObserver
Variable
LeaseRegistry’s transitionObserver
when the registry is constructed without a presence service (e.g. in
lease-registry.test.ts unit tests that do not exercise presence).
The default discipline (Principle 4) is to have a value that does the
right thing rather than a null branch every call site has to
remember to guard.
PresenceAuditEvent
TypeAlias
-
LeaseEndAfterDisconnect—onLeaseActiveEndfires for an agent whose entry has already been dropped byonAgentDisconnect.closeSocketSessionrunsonAgentDisconnectBEFOREleaseRegistry.abandon(connId), and abandon synchronously firesonLeaseActiveEndfor every active lease bound to the connection. -
LeaseBeginAfterDisconnect—onLeaseActiveBeginfires betweenonAgentDisconnectandleaseRegistry.abandon, when a concurrentresolveLease(grant)on a different connection’s moderator verdict lands during the disconnect window. The entry-creation invariant (onlyonAgentConnectcreates entries) means the begin is correctly dropped without re-creating a ghost entry. -
LeaseCallbackFromStaleConnection— a lease callback fires with arecipientConnIdthat is NOT in the entry’s currentliveConnsset. The fast-reconnect race: agent A’sconnId-1disconnects (removed fromliveConns), A reconnects onconnId-2, and the pendingleaseRegistry.abandon(connId-1)firesonLeaseActiveEndfor A’s old leases carrying the now-staleconnId-1. The callback is a silent no-op (no state mutation, no emission).currentConnIdreports an arbitrary stable witness fromliveConns(the first, insertion-ordered) for diagnostics.
onLeaseActiveEnd for the same
lease id on an entry whose recipientConnId IS in liveConns) are
silent — no audit, no emission. The audit class is specifically for
the disconnect-window and fast-reconnect race cases.
Audit events are emitted via Effect.logDebug. They do NOT go
through Effect.die; the never E channel is preserved by
construction.
PresenceService
Class
LeaseRegistry
can drive lease transitions through it — the registry depends on the
narrow observer contract, not on this whole surface. The WS-lifecycle
hooks (onAgentConnect / onAgentDisconnect) feed connection
transitions, and network/presence/subscribe reads status via statusMany.
State. One in-memory status map, lost on restart. Agents repopulate
it on reconnect. Each entry carries liveConns (every WS conn the agent
is authed on) + leasesByConn (per-conn active-lease buckets).
Multi-connection shaped: a second simultaneous connect ADDS to
liveConns rather than clobbering it.
One Ref update per transition. Every observer/lifecycle method
computes its result inside one Ref operation so status updates remain
linearized across connect, disconnect, and lease callbacks.
Entry-creation invariant (load-bearing). Entries are created
EXCLUSIVELY in onAgentConnect (first connection). Subsequent
connects add to liveConns; the entry is never re-created while any
conn survives. A lease callback on an unknown agent NEVER allocates
an entry; instead it audits (PresenceAuditEvent) and no-ops.
Combined with the recipientConnId ∈ liveConns check, stale lease
callbacks across reconnect / partial-disconnect boundaries neither mutate
state nor re-create disconnected agents.
Lease observer flow:
PresenceServiceLive
Variable
PresenceServiceTag
Class
Files
handlers.tslayer.tspresence-types.tspresence.service.ts