[2026] rollout support, to be short lived I suppose

This commit is contained in:
Devin Zuczek
2026-10-19 22:54:18 -04:00
parent a3291bc9ce
commit 05d7fe4c32
13 changed files with 462 additions and 56 deletions
+9
View File
@@ -83,6 +83,15 @@ export type Env = SharedHonoEnv & {
* means rollout callers use the live pool. See `tachyonPoolFor` in match.app.ts.
*/
TACHYON_HOST_PORT_ROLLOUT?: string
/**
* The builds under staged rollout, overriding `ROLLOUT_GAME_VERSIONS` in @repo/domain:
* a comma-separated list of builds, or `off` for none. Set for every worker from the
* root `.env` (`RECFLARE_ROLLOUT_GAME_VERSIONS`), so this agrees with the gate `auth`
* applies by construction. Read through `rolloutGameBuilds`; decides who is served the
* rollout Tachyon pool above. Ending the rollout (`off`) moves those callers to the
* live pool.
*/
ROLLOUT_GAME_VERSIONS?: string
/**
* The Photon region every session is pinned to — both the region named in the connection
* info and the one stamped on every room instance, which must agree. Optional; unlike the
+4 -3
View File
@@ -49,6 +49,7 @@ import {
recordStat,
refreshInstanceFullness,
Role,
rolloutGameBuilds,
RoomInstanceType,
roomRoles,
setPresence,
@@ -253,7 +254,7 @@ const ROLLOUT_TACHYON_SERVER_ID_PREFIX = 'rollout-'
interface TachyonCaller {
/** The account's `isSandbox` flag. */
isSandbox: boolean
/** Running a build under staged rollout (`ROLLOUT_GAME_VERSIONS`, off the token's `rn.ver`). */
/** Running a build under staged rollout (`rolloutGameBuilds`, off the token's `rn.ver`). */
isRollout: boolean
}
@@ -3216,7 +3217,7 @@ const app = new Hono<App>()
'…). Both are empty when the pool is unset or the caller is in no instance. A',
'sandbox account is picked out of the `TACHYON_HOST_PORT_SANDBOX` pool instead, the',
'same way, with ids `dev-1`, `dev-2`, …; a caller whose token’s `rn.ver` is a build',
'under staged rollout (`ROLLOUT_GAME_VERSIONS`, currently `20260323`) out of',
'under staged rollout (`ROLLOUT_GAME_VERSIONS`, by default `20260323`) out of',
'`TACHYON_HOST_PORT_ROLLOUT`, with ids `rollout-1`, `rollout-2`, …. Sandbox wins when',
'both apply, and either special pool left unset falls back to the live one.',
'`experiments` carries the client’s networking flags.',
@@ -3264,7 +3265,7 @@ const app = new Hono<App>()
const tachyon = tachyonServerFor(
tachyonPoolFor(c.env, {
isSandbox: account?.isSandbox === true,
isRollout: isRolloutGameVersion(await callerVersion(c)),
isRollout: isRolloutGameVersion(await callerVersion(c), rolloutGameBuilds(c.env)),
}),
roomInstanceId
)
@@ -1814,6 +1814,7 @@ describe('auth-gated endpoints', () => {
const original = env.TACHYON_HOST_PORT
const originalSandbox = env.TACHYON_HOST_PORT_SANDBOX
const originalRollout = env.TACHYON_HOST_PORT_ROLLOUT
const originalRolloutVersions = env.ROLLOUT_GAME_VERSIONS
try {
env.TACHYON_HOST_PORT = '198.51.100.12:7777'
env.TACHYON_HOST_PORT_SANDBOX = '203.0.113.30:7777, 203.0.113.30:7778'
@@ -1905,6 +1906,30 @@ describe('auth-gated endpoints', () => {
})
}
// WHICH builds are under rollout is the ROLLOUT_GAME_VERSIONS var, the same one
// `auth` gates on. `off` ends the rollout and its callers join the live pool; naming
// another build moves the pool to that build's players instead.
const movedRollout = await createRoomInstance(env.DB, {
ownerAccountId: 976,
roomId: 2,
photonRoomId: 'tachyon-rollout-moved',
maxCapacity: 12,
})
env.ROLLOUT_GAME_VERSIONS = 'off'
expect(await rolloutVoiceFor('976', '20260323.14', movedRollout.roomInstanceId)).toEqual({
voiceConnectionInfo: '198.51.100.12:7777',
voiceServerId: 'tachyon-1',
})
env.ROLLOUT_GAME_VERSIONS = '20250718'
expect(await rolloutVoiceFor('976', '20250718.01', movedRollout.roomInstanceId)).toEqual(
rolloutPool[movedRollout.roomInstanceId % rolloutPool.length]
)
expect(await rolloutVoiceFor('976', '20260323.14', movedRollout.roomInstanceId)).toEqual({
voiceConnectionInfo: '198.51.100.12:7777',
voiceServerId: 'tachyon-1',
})
env.ROLLOUT_GAME_VERSIONS = originalRolloutVersions
// With no rollout pool configured, a rollout build falls back to the live one, not
// the sandbox one.
env.TACHYON_HOST_PORT_ROLLOUT = undefined
@@ -1935,6 +1960,7 @@ describe('auth-gated endpoints', () => {
env.TACHYON_HOST_PORT = original
env.TACHYON_HOST_PORT_SANDBOX = originalSandbox
env.TACHYON_HOST_PORT_ROLLOUT = originalRollout
env.ROLLOUT_GAME_VERSIONS = originalRolloutVersions
}
})