阶段 5
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-27
|
||||
@@ -0,0 +1,60 @@
|
||||
## Context
|
||||
|
||||
The project already shares transport, envelope parsing, and message dispatch between Unity client and non-Unity server hosts. Stage 4 established that transport callbacks do not execute gameplay handlers inline, but session lifecycle behavior is still fragmented: transport establishment, login success, heartbeat timeout, disconnect, and reconnect intent are not modeled as separate states, and heartbeat logic is still entangled with business flow. Stage 5 needs a single host-agnostic lifecycle layer before later QoS and sync work build on unstable assumptions.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Introduce an explicit shared connection state model that distinguishes transport connection, authentication/login progress, steady-state session health, timeout, and reconnect intent.
|
||||
- Centralize heartbeat timing, timeout detection, and reconnect scheduling into a shared session manager instead of distributing them across handlers and host code.
|
||||
- Keep heartbeat infrastructure-focused: liveness detection, RTT measurement, and time sync only.
|
||||
- Allow Unity client and non-Unity server hosts to observe the same lifecycle events while keeping host-specific reactions outside the shared core.
|
||||
|
||||
**Non-Goals:**
|
||||
- Reworking message QoS or transport reliability semantics.
|
||||
- Changing the envelope protocol or replacing KCP.
|
||||
- Designing gameplay-specific reconnect UX, character resync, or rollback rules.
|
||||
- Adding final production telemetry; detailed metrics belong to a later stage.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Use an explicit shared connection state enum and session manager
|
||||
A dedicated `SessionManager` backed by a `ConnectionState` model keeps lifecycle transitions in one place and makes transport-connected, login-pending, logged-in, timed-out, reconnecting, and login-failed states observable. This is better than inferring state from scattered booleans in handlers because later features such as reconnect backoff and QoS splitting need a stable state machine boundary.
|
||||
|
||||
Alternative considered: keep lifecycle flags in `NetworkManager` and server host adapters. Rejected because it would fork client/server behavior again right after the shared-network-foundation refactor.
|
||||
|
||||
### Treat heartbeat as infrastructure signals, not business state ownership
|
||||
Heartbeat messages feed the session manager with liveness timestamps, RTT samples, and time-sync data, but they do not themselves declare login success or trigger reconnect policy. This keeps message handlers narrow and prevents hidden coupling where missing a heartbeat implicitly mutates business session state in unrelated code.
|
||||
|
||||
Alternative considered: let heartbeat handlers directly disconnect or reconnect. Rejected because it recreates the current layering problem and makes timeout policy hard to test.
|
||||
|
||||
### Make shared runtime own lifecycle orchestration, hosts own reactions
|
||||
`SharedNetworkRuntime` should compose transport, message routing, and session lifecycle so both client and server use the same lifecycle rules. Unity `NetworkManager` and `ServerNetworkHost` consume lifecycle events and decide what to do next, such as UI updates, reconnect attempts, or server-side cleanup.
|
||||
|
||||
Alternative considered: introduce separate client/server session managers. Rejected because stage five explicitly aims to share the network底层 contract and keep host differences at the adapter layer.
|
||||
|
||||
### Represent reconnect as a scheduler policy, not an immediate side effect
|
||||
Reconnect should be modeled as a transition into a reconnect-pending or reconnecting state with policy-owned timing, instead of directly restarting transport from inside a timeout callback. That makes backoff, disable/enable behavior, and tests deterministic.
|
||||
|
||||
Alternative considered: reconnect immediately inside timeout detection. Rejected because it couples timer evaluation to transport startup side effects and makes repeated failures difficult to reason about.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Introducing a state machine can expose ambiguities in existing login/heartbeat handlers. -> Mitigation: define explicit transition sources and add tests for login success, login failure, heartbeat timeout, disconnect, and reconnect scheduling.
|
||||
- [Risk] Shared lifecycle ownership can blur the boundary between transport events and business authentication events. -> Mitigation: keep transport state inputs and login result inputs as separate session-manager APIs.
|
||||
- [Risk] Reconnect policy may require host-specific decisions later. -> Mitigation: keep policy configuration injectable and host reactions event-driven rather than hardcoding Unity-only behavior.
|
||||
- [Risk] Existing code may already assume that "connected" means "logged in". -> Mitigation: update host-facing APIs and TODO/documentation so callers consume explicit lifecycle states instead of legacy booleans.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add shared lifecycle types (`ConnectionState`, session event model, heartbeat policy/session manager) without removing existing login/heartbeat flows yet.
|
||||
2. Route transport-connect, login-result, heartbeat-received, and timeout inputs through the new session manager.
|
||||
3. Update Unity client and server host adapters to observe lifecycle state changes from the shared runtime.
|
||||
4. Remove or simplify duplicated timeout/reconnect logic from message handlers and host code.
|
||||
5. Add edit mode tests that lock state transitions before beginning Stage 6 QoS work.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Whether the server host needs the exact same reconnect scheduling primitives as the client, or only the same state vocabulary.
|
||||
- Whether login failure should transition to `Disconnected` immediately after reporting failure, or remain in a stable `LoginFailed` state until the host decides the next action.
|
||||
- How much time-sync state should live in the session manager versus a separate clock-sync helper once Stage 6 begins.
|
||||
@@ -0,0 +1,24 @@
|
||||
## Why
|
||||
|
||||
Current networking distinguishes transport delivery from Unity threading, but it still does not distinguish transport connectivity, login success, heartbeat timeout, and reconnect flow as first-class session states. Stage 5 is needed now so client and server can share one coherent lifecycle model before QoS and sync optimization build on top of ambiguous state handling.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a shared session lifecycle module that models disconnected, transport-connected, login-pending, logged-in, timeout, reconnecting, and login-failed states explicitly.
|
||||
- Add a heartbeat policy that is limited to liveness checks, RTT measurement, and time synchronization, without owning login or reconnect decisions directly.
|
||||
- Move timeout detection, disconnect transitions, and reconnect scheduling into a shared session manager instead of leaving them in message handlers or host-specific business code.
|
||||
- Expose lifecycle state changes and session events so Unity client host and non-Unity server host can react without forking the underlying network core.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `network-session-lifecycle`: Shared connection, login, heartbeat, timeout, and reconnect state management for client and server hosts.
|
||||
|
||||
### Modified Capabilities
|
||||
- `shared-network-foundation`: The shared runtime now includes host-agnostic session lifecycle management in addition to transport and message routing.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected code: `SharedNetworkRuntime`, `MessageManager`, `NetworkManager`, `ServerNetworkHost`, login/heartbeat handlers, and new session manager/state types.
|
||||
- Affected behavior: login success no longer implies transport connect, heartbeat becomes a narrow infrastructure concern, and reconnect logic moves out of ad hoc business paths.
|
||||
- Affected tests: edit mode tests need coverage for lifecycle transitions, timeout handling, login failure, and reconnect scheduling across shared client/server runtime paths.
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
## ADDED 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 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
|
||||
- **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 session into the logged-in state
|
||||
- **THEN** hosts can react to that state change without conflating it with transport establishment
|
||||
|
||||
### Requirement: Heartbeat is limited to liveness, RTT, and time sync
|
||||
The shared session lifecycle SHALL treat heartbeat traffic as infrastructure input for liveness detection, round-trip-time measurement, and clock synchronization only. Heartbeat processing MUST NOT itself own login success, login failure, or reconnect policy decisions.
|
||||
|
||||
#### Scenario: Heartbeat updates liveness and RTT only
|
||||
- **WHEN** a heartbeat response is received for an active session
|
||||
- **THEN** the session manager updates last-seen or timeout bookkeeping and RTT or clock-sync data
|
||||
- **THEN** it does not mark the session logged in solely because the heartbeat succeeded
|
||||
|
||||
#### Scenario: Missing heartbeat triggers timeout state
|
||||
- **WHEN** the configured heartbeat timeout elapses without a required heartbeat or other liveness signal
|
||||
- **THEN** the session lifecycle transitions the session into a timed-out state
|
||||
- **THEN** reconnect handling is delegated to the lifecycle reconnect policy rather than hidden inside the heartbeat handler itself
|
||||
|
||||
### Requirement: Timeout and reconnect are session-manager responsibilities
|
||||
The shared networking core SHALL manage timeout detection, disconnect transitions, and reconnect scheduling through a session-manager component rather than implementing those decisions inside business message handlers.
|
||||
|
||||
#### 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
|
||||
- **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
|
||||
- **THEN** hosts can handle that failure separately from a transport disconnect or heartbeat timeout
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
## ADDED 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 same shared runtime with a session manager that consumes transport events, login results, and heartbeat signals without depending on Unity-specific runtime types.
|
||||
|
||||
#### Scenario: Client host composes runtime with lifecycle manager
|
||||
- **WHEN** the Unity client constructs its shared networking runtime
|
||||
- **THEN** that runtime includes shared session lifecycle management 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 observes the same lifecycle vocabulary
|
||||
- **WHEN** a non-Unity server host composes the shared networking runtime
|
||||
- **THEN** it uses the same lifecycle state model and session-manager abstractions as the client-side shared runtime
|
||||
- **THEN** server-specific cleanup or admission behavior stays in the server host adapter rather than forking the shared core contract
|
||||
@@ -0,0 +1,19 @@
|
||||
## 1. Shared Lifecycle Model
|
||||
|
||||
- [x] 1.1 Add shared lifecycle types for connection state, session events, and heartbeat/reconnect policy configuration.
|
||||
- [x] 1.2 Implement a host-agnostic session manager that consumes transport-connected, login-result, heartbeat, timeout, and disconnect inputs.
|
||||
|
||||
## 2. Runtime Integration
|
||||
|
||||
- [x] 2.1 Extend `SharedNetworkRuntime` to compose the session manager alongside transport and message routing.
|
||||
- [x] 2.2 Update `NetworkManager` and `ServerNetworkHost` to observe explicit lifecycle state changes instead of inferring session health from ad hoc flags.
|
||||
|
||||
## 3. Heartbeat And Login Flow Cleanup
|
||||
|
||||
- [x] 3.1 Refactor login and heartbeat handlers so heartbeat only updates liveness, RTT, and time-sync state.
|
||||
- [x] 3.2 Remove timeout and reconnect decisions from business handlers and route them through session-manager policy APIs.
|
||||
|
||||
## 4. Verification And Documentation
|
||||
|
||||
- [x] 4.1 Add edit mode tests for transport-connected vs logged-in distinction, login failure, heartbeat timeout, and reconnect scheduling.
|
||||
- [x] 4.2 Update `CodeX-TODO.md` and related network docs to reflect the new lifecycle layering and stage-five completion criteria.
|
||||
Reference in New Issue
Block a user