This commit is contained in:
SepComet
2026-03-27 13:27:14 +08:00
parent ff9ee1291f
commit e5851795c7
43 changed files with 1544 additions and 35 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-03-27
@@ -0,0 +1,59 @@
## Context
The current networking stack already shares transport, message routing, and session lifecycle vocabulary between client and server hosts. However, the shared runtime still owns exactly one `SessionManager`, which matches the client model but does not match a server that needs to track many remote peers concurrently while preserving the same login, timeout, heartbeat, and reconnect semantics.
The main constraint is backward compatibility for the client host. The Unity client should keep its simple single-session composition, while the server host gains an explicit multi-session orchestration layer instead of embedding per-peer lifecycle logic into handlers or transport internals.
## Goals / Non-Goals
**Goals:**
- Preserve `SessionManager` as the per-session finite state machine and lifecycle vocabulary owner.
- Introduce a shared multi-session orchestration layer that can create, look up, evaluate, and remove many session managers keyed by remote identity.
- Keep client composition simple by allowing the existing single-session runtime path to remain valid.
- Make server-facing APIs explicit about per-session lookup, enumeration, lifecycle events, and cleanup triggers.
**Non-Goals:**
- Redesign KCP transport session isolation or introduce a new wire protocol.
- Change the meaning of existing connection states or heartbeat semantics.
- Solve stage 6 QoS or synchronization policy work in the same change.
- Move gameplay admission, authority, or player-object ownership into the shared lifecycle layer.
## Decisions
### Keep `SessionManager` as a per-session state machine
`SessionManager` already models one connection lifecycle correctly. Replacing it with a collection-aware type would force client and server concerns into the same API surface. The change will keep `SessionManager` focused on a single session and add a higher-level multi-session coordinator for hosts that manage many peers.
Alternative considered: make `SessionManager` itself collection-aware.
Rejected because it would either expose server-only concepts to the client or create a type with dual responsibilities that is harder to test and reason about.
### Add a keyed multi-session coordinator above transport callbacks
The new orchestration layer should own a mapping from remote identity to per-session `SessionManager` instances. Transport delivery, login results, inbound activity, heartbeat updates, timeout evaluation, and reconnect bookkeeping should be routed through this keyed coordinator rather than being inferred in message handlers.
Alternative considered: keep session dictionaries inside `ServerNetworkHost` only.
Rejected because it would fork lifecycle orchestration away from the shared core and make server behavior harder to test without the host adapter.
### Preserve separate host adapters for client and server
The Unity client should continue composing a single-session runtime with its main-thread dispatcher. The server host should compose the shared transport and message layer with the new multi-session orchestration path, exposing per-session inspection and events without inheriting Unity-specific assumptions.
Alternative considered: replace `SharedNetworkRuntime` with one universal runtime abstraction.
Rejected because the client and server have materially different composition shapes; forcing one runtime abstraction would hide important ownership boundaries.
## Risks / Trade-offs
- [More lifecycle objects] → Mitigation: keep `SessionManager` unchanged and centralize multi-session behavior in one coordinator with focused tests.
- [Remote identity choice may leak transport details] → Mitigation: define a narrow session-key abstraction or standardize on the existing remote endpoint identity used by transport callbacks.
- [Server cleanup bugs can leave stale sessions behind] → Mitigation: require explicit disconnect/removal scenarios and evaluation tests for session expiry.
- [Client API drift during refactor] → Mitigation: keep the single-session runtime path as a first-class supported composition and verify it with regression tests.
## Migration Plan
1. Introduce the multi-session coordinator and per-session observation API in the shared network layer.
2. Rewire `ServerNetworkHost` to use the coordinator for per-peer lifecycle bookkeeping.
3. Leave the client host on the existing single-session runtime path, adding only compatibility glue if necessary.
4. Add tests that cover client single-session regressions and server multi-session behavior side by side.
## Open Questions
- Whether the server session key should be the transport remote endpoint directly or a narrower shared abstraction.
- Whether reconnect scheduling is meaningful for the server side, or should remain configurable per host/session policy.
- How much session enumeration should be exposed publicly versus kept internal with event-based observation.
@@ -0,0 +1,25 @@
## Why
The current shared networking foundation exposes a single `SessionManager` lifecycle per runtime, which is sufficient for a client connected to one server but not for a server handling multiple remote peers concurrently. Extending the lifecycle model now prevents the server host from forking transport, login, timeout, and reconnect logic away from the shared network core.
## What Changes
- Introduce shared multi-session lifecycle orchestration for hosts that manage more than one remote peer at a time.
- Preserve the current single-session client flow while adding a server-oriented session collection API keyed by remote identity.
- Define how transport events, login results, heartbeat liveness, timeout detection, and reconnect policy are applied per managed session instead of only per runtime.
- Clarify which responsibilities stay in the shared session orchestration layer versus host-specific admission, cleanup, and gameplay reactions.
## Capabilities
### New Capabilities
- `multi-session-lifecycle`: Shared orchestration and observation of multiple concurrent network sessions, especially for server hosts that manage many remote peers.
### Modified Capabilities
- `network-session-lifecycle`: The shared lifecycle vocabulary and heartbeat/reconnect rules must apply to each managed session, not only to a singleton runtime session.
- `shared-network-foundation`: The shared runtime foundation must support both client-style single-session composition and server-style multi-session composition without introducing a protocol or transport fork.
## Impact
- Affected code: `SharedNetworkRuntime`, `SessionManager`, `ServerNetworkHost`, transport-to-session wiring, and lifecycle-related tests.
- New APIs will likely introduce server-facing session lookup, enumeration, and per-session event observation.
- Client-side runtime composition should remain compatible, but session orchestration responsibilities will be split more explicitly between single-session and multi-session hosts.
@@ -0,0 +1,30 @@
## ADDED Requirements
### Requirement: Multi-session hosts manage per-peer lifecycle state
The shared networking core SHALL provide a multi-session lifecycle coordinator for hosts that manage multiple concurrent remote peers. The coordinator MUST maintain distinct per-session lifecycle state keyed by remote identity rather than collapsing all peers into one runtime-level state.
#### Scenario: Server tracks two peers independently
- **WHEN** a server host accepts transport activity from two different remote peers
- **THEN** the multi-session coordinator creates or resolves two distinct managed sessions
- **THEN** lifecycle changes for one peer do not overwrite or hide the state of the other peer
### Requirement: Multi-session hosts can observe and evaluate each managed session
The multi-session lifecycle coordinator SHALL expose per-session lookup or enumeration and MUST evaluate timeout, heartbeat, login, and reconnect rules for each managed session independently using the shared session lifecycle vocabulary.
#### Scenario: Timeout affects only one managed session
- **WHEN** one managed session stops receiving liveness updates while another session continues receiving heartbeat or message activity
- **THEN** the timed-out session transitions through timeout or reconnect states according to policy
- **THEN** the active session remains in its current healthy state
#### Scenario: Host can inspect current managed sessions
- **WHEN** server-side code needs to inspect the current connection state of connected peers
- **THEN** it can look up or enumerate managed sessions through the multi-session coordinator
- **THEN** each entry exposes the shared session lifecycle state for that specific peer
### Requirement: Session removal is explicit and does not corrupt remaining peers
The multi-session lifecycle coordinator SHALL support explicit removal or disconnection handling for one managed session without resetting unrelated sessions that remain active.
#### Scenario: Disconnect removes one session only
- **WHEN** one remote peer disconnects or is evicted by the host
- **THEN** the coordinator updates or removes that peer's managed session
- **THEN** other managed sessions remain queryable and keep their own lifecycle state
@@ -0,0 +1,27 @@
## MODIFIED Requirements
### Requirement: Session lifecycle distinguishes transport and login state
The shared networking core SHALL expose an explicit session lifecycle model that distinguishes transport connectivity from login/authentication success. Hosts MUST be able to observe at least disconnected, transport-connected, login-pending, logged-in, login-failed, timed-out, and reconnecting lifecycle states for each managed session without inferring them from unrelated message handlers.
#### Scenario: Transport connect does not imply login success
- **WHEN** the transport establishes a usable remote session but no login success message has been accepted yet
- **THEN** the shared lifecycle reports a transport-connected or login-pending state for that managed session
- **THEN** it does not report the session as logged in
#### Scenario: Login success advances lifecycle independently
- **WHEN** the client or server session manager receives a successful login/authentication result for an active transport session
- **THEN** the shared lifecycle transitions that managed session into the logged-in state
- **THEN** hosts can react to that state change without conflating it with transport establishment
### Requirement: Timeout and reconnect are session-manager responsibilities
The shared networking core SHALL manage timeout detection, disconnect transitions, and reconnect scheduling through session-manager components rather than implementing those decisions inside business message handlers. Hosts that manage multiple concurrent peers MUST apply these rules independently per managed session rather than collapsing timeout or reconnect state to the entire runtime.
#### Scenario: Timeout produces an observable reconnect transition
- **WHEN** a reconnect-capable host has a session that times out
- **THEN** the session manager emits a timeout-related lifecycle transition for that managed session
- **THEN** it can subsequently move the session into a reconnecting or reconnect-pending state according to configured policy
#### Scenario: Login failure is distinct from transport disconnect
- **WHEN** authentication or login fails while the transport session is still active
- **THEN** the shared lifecycle reports a login-failed state for that managed session
- **THEN** hosts can handle that failure separately from a transport disconnect or heartbeat timeout
@@ -0,0 +1,14 @@
## MODIFIED Requirements
### Requirement: Shared runtime owns host-agnostic session lifecycle orchestration
The shared network foundation SHALL include host-agnostic session lifecycle orchestration alongside transport startup and message routing. Client and server hosts MUST be able to compose the shared foundation with session orchestration that consumes transport events, login results, and heartbeat signals without depending on Unity-specific runtime types, while supporting both single-session client composition and multi-session server composition.
#### Scenario: Client host composes runtime with single-session lifecycle manager
- **WHEN** the Unity client constructs its shared networking runtime
- **THEN** that runtime includes shared session lifecycle management for its single remote session in addition to transport and message routing
- **THEN** Unity-specific code remains responsible only for reacting to lifecycle state changes and driving host behavior
#### Scenario: Server host composes shared foundation with multi-session orchestration
- **WHEN** a non-Unity server host constructs the runtime networking stack for multiple remote peers
- **THEN** it uses the shared transport and message-routing foundation together with shared multi-session lifecycle orchestration
- **THEN** server-specific cleanup, admission, and gameplay reactions stay in the server host adapter rather than forking the shared lifecycle contract
@@ -0,0 +1,23 @@
## 1. Shared Multi-Session Lifecycle Core
- [x] 1.1 Introduce a shared multi-session lifecycle coordinator that owns per-session `SessionManager` instances keyed by remote identity.
- [x] 1.2 Add APIs for per-session lookup, enumeration, lifecycle event observation, and explicit session removal without changing the existing session state vocabulary.
- [x] 1.3 Route transport activity, login results, heartbeat updates, timeout evaluation, and reconnect bookkeeping through the coordinator on a per-session basis.
## 2. Host Composition
- [x] 2.1 Rework `ServerNetworkHost` to use the shared multi-session coordinator instead of exposing only one runtime-level `SessionManager`.
- [x] 2.2 Preserve the current client-side single-session composition path so `NetworkManager` and `SharedNetworkRuntime` remain valid for one-server connectivity.
- [x] 2.3 Define how remote identity is mapped into session keys and ensure session cleanup does not disturb unrelated peers.
## 3. Verification
- [x] 3.1 Add edit-mode tests that verify two or more server-side sessions can progress through login, timeout, and disconnect independently.
- [x] 3.2 Add regression tests that confirm the client-side single-session lifecycle path still behaves as before.
- [x] 3.3 Build the edit-mode test project and run the network-related test suite to confirm no lifecycle regressions remain.
## 4. Documentation
- [x] 4.1 Update `CodeX-TODO.md` to reflect that stage 5 lifecycle support now covers server-side multi-session management.
- [x] 4.2 Document the new shared multi-session entry points and server-observable session states in change-related docs or code comments where needed.