Files
2026-05-27 23:29:53 +01:00

3.5 KiB

game-server — performance spec delta (Wave B-5b)

ADDED Requirements

Requirement: ObjectPool typed reuse

ObjectPool<T> SHALL recycle typed objects between a configurable factory, reset, and optional dispose to dampen GC pressure, and SHALL enforce a configurable maxSize cap by raising typed errors when callers misuse the pool.

Scenario: pre-allocation populates the pool

  • GIVEN an ObjectPool configured with initialSize: 2 and preAllocate: true
  • WHEN the pool is constructed
  • THEN getStats().available reports 2

Scenario: acquire returns a recycled object

  • GIVEN a pool with two pre-allocated objects
  • WHEN the caller invokes acquire()
  • THEN the returned object came from the pool
  • AND getStats().totalReused reports 1

Scenario: cap rejection

  • GIVEN a pool with maxSize: 1 and one object outstanding
  • WHEN the caller invokes acquire() again
  • THEN the call throws GameServerError(GAME_SERVER.POOL_EXHAUSTED)

Scenario: foreign-object release rejection

  • WHEN the caller releases an object not handed out by this pool
  • THEN release throws GameServerError(GAME_SERVER.RELEASE_FOREIGN_OBJECT)

Scenario: dispose lockout

  • GIVEN a disposed ObjectPool
  • WHEN the caller invokes acquire(), release(obj), or clear()
  • THEN each call throws GameServerError(GAME_SERVER.POOL_DISPOSED)

Requirement: SessionPool plain-data session recycling

SessionPool SHALL pool plain-data PooledSession records and expose a acquireSession(data) API that stamps the borrowed record with the caller-supplied identity and metadata before returning it.

Scenario: acquireSession stamps the record

  • WHEN the caller invokes acquireSession({ id: "match-42", type: "game", metadata: {...} })
  • THEN the returned PooledSession carries id === "match-42"
  • AND its children array is empty
  • AND its metadata.createdAt mirrors the caller's input

Scenario: releaseSession recycles the record

  • GIVEN a pool with initialSize: 1, maxSize: 5
  • WHEN the caller acquires, mutates, and releases a session
  • AND the caller immediately re-acquires
  • THEN the same underlying object is returned with a freshly empty children array

Requirement: NetworkTierAdapter capability-driven tier selection

NetworkTierAdapter SHALL accept a non-empty, validated tier list at construction time, track per-node capability assessments, and recommend an optimal tier per node based on its composite score.

Scenario: empty tier list rejection

  • WHEN the adapter is constructed with tiers: []
  • THEN the constructor throws GameServerError(GAME_SERVER.INVALID_TIER_CONFIG)

Scenario: score-based optimal tier

  • GIVEN an adapter with host, sub-host, player tiers
  • WHEN getOptimalTier({score: 92, ...}) is invoked
  • THEN the returned tier carries nodeType === "host"
  • AND getOptimalTier({score: 60, ...}) returns sub-host
  • AND getOptimalTier({score: 20, ...}) returns player

Scenario: load-balancing recommendation sort order

  • GIVEN three registered nodes with scores 90, 60, 20
  • WHEN getLoadBalancingRecommendations() is invoked
  • THEN the result is sorted by capability score descending
  • AND the first entry's recommendedLoad is floor(90 / 10) === 9

Scenario: unknown-tier rejection

  • WHEN getTierForNodeType("nope") is invoked
  • THEN the call throws GameServerError(GAME_SERVER.UNKNOWN_TIER)