7.9 KiB
Context
The repository already has shared networking building blocks for client and server roles. NetworkIntegrationFactory.CreateClientRuntime(...) and SharedNetworkRuntime provide a concrete client bootstrap path, while NetworkIntegrationFactory.CreateServerHost(...) only returns a ServerNetworkHost object with lower-level lifecycle methods such as StartAsync(), Stop(), UpdateLifecycle(), and message draining. That leaves TODO step 6 unfinished because there is still no single integration entry point that represents "boot a real server runtime with configuration, startup, and ownership semantics".
Constraints for this design:
- Shared networking code under
Assets/Scripts/Network/must remain free ofUnityEnginedependencies. - The existing client single-session path must remain unchanged.
- Server hosting must continue to rely on
MultiSessionManager,ServerNetworkHost, and the current transport abstractions instead of introducing a second lifecycle model. - The result should be testable from edit-mode tests without needing a Unity scene or manual wiring.
Goals / Non-Goals
Goals:
- Introduce a concrete server runtime entry point that can be invoked by a host process with minimal wiring.
- Centralize server startup configuration validation, transport construction, startup sequencing, and shutdown ownership in one place.
- Preserve the current
ServerNetworkHostas the session/lifecycle owner for connected peers. - Define a stable integration surface that can later be used by Unity adapters, console hosts, or dedicated-server launchers.
- Add regression coverage for startup success, startup failure, and shutdown cleanup behavior.
Non-Goals:
- Redesign
ServerNetworkHost,MultiSessionManager, or transport interfaces. - Change client runtime behavior or the single-session entry path.
- Introduce authentication, gameplay loop, or headless process packaging concerns beyond the networking startup contract.
- Add Unity-specific MonoBehaviour startup code inside shared networking assemblies.
Decisions
Decision: Add a dedicated server runtime entry type above CreateServerHost
The change will define a higher-level entry type, centered on a server bootstrap configuration object plus a startup/integration facade, instead of asking callers to directly compose transports and manually coordinate ServerNetworkHost lifecycle calls.
Rationale:
CreateServerHost(...)is still a factory for components, not an integration entry point with ownership semantics.- A dedicated entry type makes startup failure handling, disposal/stop behavior, and future host adapters explicit.
- It mirrors the repository's existing preference for focused types and keeps
ServerNetworkHostfocused on per-peer session orchestration.
Alternatives considered:
- Expand
ServerNetworkHostto absorb bootstrap concerns: rejected because it mixes runtime assembly and per-session lifecycle responsibilities. - Leave only
NetworkIntegrationFactory.CreateServerHost(...)and document manual wiring: rejected because TODO step 6 specifically calls for a real startup/integration entry point.
Decision: Keep the entry point in shared networking code and expose host-specific integration separately
The entry point contract will live under Assets/Scripts/Network/ so it can be reused by any host. Unity or other environment-specific launchers may wrap it elsewhere, but they will call into the shared entry contract rather than duplicating bootstrap logic.
Rationale:
- The startup contract is not inherently Unity-specific.
- Tests can validate the shared contract directly.
- This preserves the repository rule against introducing
UnityEngineinto shared networking code.
Alternatives considered:
- Put the entry point only in a Unity-facing adapter: rejected because it would make dedicated-server and CLI-style integration harder and would not strengthen the shared network contract.
Decision: Model startup as configuration + runtime handle
The design will use an immutable or validation-friendly configuration object for server ports, optional sync port, dispatcher, reconnect policy, time provider, and transport factory overrides. Starting the entry point produces or owns a runtime handle that exposes the underlying ServerNetworkHost, startup state, and a single stop/dispose path.
Rationale:
- Separating configuration from runtime ownership makes validation and tests straightforward.
- A runtime handle can guard against double-start, partial-start, and stop-before-start errors.
- This is the minimum structure needed to support a "real server startup" contract without over-designing deployment concerns.
Alternatives considered:
- Static
StartServer(...)helper returning onlyServerNetworkHost: rejected because ownership and shutdown semantics remain implicit. - A fully generic dependency injection container entry flow: rejected as unnecessary for the current repository scope.
Decision: Make startup and shutdown sequencing explicit and failure-safe
The entry point will be responsible for invoking reliable transport startup first, then sync transport startup if configured, and ensuring partial failures stop any already-started resources. Shutdown will be idempotent and will cascade into ServerNetworkHost.Stop() so session cleanup remains owned by existing lifecycle code.
Rationale:
- Startup sequencing already exists in lower-level runtime types; the integration entry point must make it observable and enforceable.
- Failure-safe cleanup prevents leaked transports and stale multi-session state during host bootstrap failures.
- Idempotent stop behavior is important for integration with external host lifecycles.
Alternatives considered:
- Let callers implement their own try/finally around startup: rejected because it recreates the missing integration contract in every host.
Risks / Trade-offs
- [Risk] A new runtime wrapper could duplicate behavior already present in
ServerNetworkHostorNetworkIntegrationFactory. → Mitigation: keep the wrapper narrowly focused on config validation, ownership, and lifecycle sequencing while delegating per-peer behavior to existing types. - [Risk] Naming the new entry type poorly could create confusion between factory, host, and runtime responsibilities. → Mitigation: pick a name that clearly indicates bootstrap/integration ownership rather than per-session management.
- [Risk] Delta specs may over-constrain future dedicated-server hosting scenarios. → Mitigation: define minimal contractual guarantees around startup, shutdown, and lifecycle ownership, while leaving environment-specific hosting adapters out of scope.
- [Risk] Tests may only cover happy-path startup. → Mitigation: require regression cases for startup failure rollback and repeated shutdown calls.
Migration Plan
- Add the new entry-point/configuration types and wire them to existing
NetworkIntegrationFactoryandServerNetworkHostinfrastructure. - Add or update edit-mode tests to cover startup sequencing, failure rollback, and shutdown cleanup semantics.
- Update any TODO/documented integration references to use the new entry point as the recommended server bootstrap path.
- Keep existing
CreateServerHost(...)available unless implementation evidence shows it should be downgraded or internally delegated.
Rollback strategy: remove the new entry point and revert callers to direct CreateServerHost(...) usage. Because the change is additive, rollback should not require transport or protocol migration.
Open Questions
- Should the runtime handle implement
IDisposable/IAsyncDisposable, or is an explicitStop()/StopAsync()contract sufficient for current usage? - Should the shared entry point expose a long-running integration loop hook, or only startup/stop plus access to
ServerNetworkHostfor callers that own their own loops? - Is there an existing external host adapter in this repository that should be updated immediately once the shared entry point exists, or does the initial change stop at shared bootstrap plus tests?