refactor: 重构获取anonymous token以及xeapikey的获取

This commit is contained in:
Takanashi Hoshino
2026-09-13 11:13:56 +08:00
parent a8c781fd64
commit c478367c6c
11 changed files with 656 additions and 78 deletions
+235
View File
@@ -0,0 +1,235 @@
const assert = require('assert')
describe('util/runtimeState', () => {
let runtimeState
beforeEach(() => {
// 每个用例从干净状态开始,并清掉可能影响 seed 的环境变量
delete process.env.NETEASE_ANONYMOUS_TOKEN
delete process.env.NETEASE_XEAPI_PUBLIC_KEY
delete require.cache[require.resolve('./runtimeState')]
runtimeState = require('./runtimeState')
})
afterEach(() => {
delete process.env.NETEASE_ANONYMOUS_TOKEN
delete process.env.NETEASE_XEAPI_PUBLIC_KEY
})
describe('anonymous token', () => {
it('set/get 往返', () => {
runtimeState.setAnonymousToken('TOKEN_A')
assert.strictEqual(runtimeState.getAnonymousToken(), 'TOKEN_A')
})
it('set 忽略空值,不覆盖已有 token', () => {
runtimeState.setAnonymousToken('TOKEN_A')
runtimeState.setAnonymousToken('')
runtimeState.setAnonymousToken(null)
assert.strictEqual(runtimeState.getAnonymousToken(), 'TOKEN_A')
})
it('优先从环境变量读取种子(需显式 loadSeed)', () => {
process.env.NETEASE_ANONYMOUS_TOKEN = 'ENV_TOKEN'
assert.strictEqual(runtimeState.getAnonymousToken(), '')
runtimeState.loadSeed()
assert.strictEqual(runtimeState.getAnonymousToken(), 'ENV_TOKEN')
})
it('缺失时 ensureAnonymousToken 调用 refresh 并写入', async () => {
let calls = 0
const token = await runtimeState.ensureAnonymousToken(async () => {
calls++
return 'FRESH_TOKEN'
})
assert.strictEqual(token, 'FRESH_TOKEN')
assert.strictEqual(runtimeState.getAnonymousToken(), 'FRESH_TOKEN')
assert.strictEqual(calls, 1)
})
it('已有 token 时 ensureAnonymousToken 不再调用 refresh', async () => {
runtimeState.setAnonymousToken('CACHED')
let calls = 0
const token = await runtimeState.ensureAnonymousToken(async () => {
calls++
return 'FRESH'
})
assert.strictEqual(token, 'CACHED')
assert.strictEqual(calls, 0)
})
it('并发调用共享同一个刷新任务(去重)', async () => {
let calls = 0
const slowRefresh = () =>
new Promise((resolve) =>
setTimeout(() => {
calls++
resolve('SHARED_TOKEN')
}, 20),
)
const results = await Promise.all([
runtimeState.ensureAnonymousToken(slowRefresh),
runtimeState.ensureAnonymousToken(slowRefresh),
runtimeState.ensureAnonymousToken(slowRefresh),
])
assert.deepStrictEqual(results, [
'SHARED_TOKEN',
'SHARED_TOKEN',
'SHARED_TOKEN',
])
assert.strictEqual(calls, 1)
})
it('refresh 失败后任务被清理,可再次重试', async () => {
await assert.rejects(
runtimeState.ensureAnonymousToken(async () => {
throw new Error('boom')
}),
)
assert.strictEqual(runtimeState.isAnonymousTokenRefreshing(), false)
const token = await runtimeState.ensureAnonymousToken(
async () => 'RETRY_OK',
)
assert.strictEqual(token, 'RETRY_OK')
})
it('刷新期间 isAnonymousTokenRefreshing 为 true', async () => {
let sawRefreshing = false
await runtimeState.ensureAnonymousToken(async () => {
sawRefreshing = runtimeState.isAnonymousTokenRefreshing()
return 'X'
})
assert.strictEqual(sawRefreshing, true)
assert.strictEqual(runtimeState.isAnonymousTokenRefreshing(), false)
})
})
describe('xeapi public key', () => {
it('set/get 往返', () => {
runtimeState.setXeapiPublicKey({ publicKey: 'PK', version: 'v1' })
assert.deepStrictEqual(runtimeState.getXeapiPublicKey(), {
publicKey: 'PK',
version: 'v1',
})
})
it('优先从环境变量读取 JSON 种子(需显式 loadSeed)', () => {
process.env.NETEASE_XEAPI_PUBLIC_KEY = JSON.stringify({
publicKey: 'ENV_PK',
version: 'env-v',
})
assert.strictEqual(runtimeState.getXeapiPublicKey(), null)
runtimeState.loadSeed()
assert.deepStrictEqual(runtimeState.getXeapiPublicKey(), {
publicKey: 'ENV_PK',
version: 'env-v',
})
})
it('环境变量中的非法 JSON 被忽略', () => {
process.env.NETEASE_XEAPI_PUBLIC_KEY = 'not-json'
runtimeState.loadSeed()
assert.strictEqual(runtimeState.getXeapiPublicKey(), null)
})
it('mergeXeapiPublicKey 保留旧 sk(服务端未下发时)', () => {
runtimeState.setXeapiPublicKey({ publicKey: 'PK1', sk: 'SK1' })
const merged = runtimeState.mergeXeapiPublicKey({ publicKey: 'PK2' })
assert.strictEqual(merged.sk, 'SK1')
assert.strictEqual(merged.publicKey, 'PK2')
})
it('mergeXeapiPublicKey 优先使用新 sk', () => {
runtimeState.setXeapiPublicKey({ publicKey: 'PK1', sk: 'SK1' })
const merged = runtimeState.mergeXeapiPublicKey({
publicKey: 'PK2',
sk: 'SK2',
})
assert.strictEqual(merged.sk, 'SK2')
})
it('缺失时 ensureXeapiPublicKey 调用 refresh 并合并写入', async () => {
let calls = 0
const result = await runtimeState.ensureXeapiPublicKey(async () => {
calls++
return { publicKey: 'FRESH_PK', version: 'v2' }
})
assert.strictEqual(calls, 1)
assert.deepStrictEqual(result, { publicKey: 'FRESH_PK', version: 'v2' })
assert.deepStrictEqual(runtimeState.getXeapiPublicKey(), {
publicKey: 'FRESH_PK',
version: 'v2',
})
})
it('已有 key 且未 force 时不刷新', async () => {
runtimeState.setXeapiPublicKey({ publicKey: 'CACHED' })
let calls = 0
const result = await runtimeState.ensureXeapiPublicKey(async () => {
calls++
return { publicKey: 'FRESH' }
})
assert.strictEqual(calls, 0)
assert.strictEqual(result.publicKey, 'CACHED')
})
it('force 时即使已有 key 也刷新', async () => {
runtimeState.setXeapiPublicKey({ publicKey: 'CACHED', sk: 'OLD_SK' })
let calls = 0
const result = await runtimeState.ensureXeapiPublicKey(
async () => {
calls++
return { publicKey: 'FRESH' }
},
{ force: true },
)
assert.strictEqual(calls, 1)
assert.strictEqual(result.publicKey, 'FRESH')
// 旧 sk 被保留
assert.strictEqual(result.sk, 'OLD_SK')
})
it('并发 ensureXeapiPublicKey 共享同一刷新任务', async () => {
let calls = 0
const slowRefresh = () =>
new Promise((resolve) =>
setTimeout(() => {
calls++
resolve({ publicKey: 'SHARED_PK' })
}, 20),
)
const results = await Promise.all([
runtimeState.ensureXeapiPublicKey(slowRefresh),
runtimeState.ensureXeapiPublicKey(slowRefresh),
])
assert.strictEqual(calls, 1)
assert.strictEqual(results[0].publicKey, 'SHARED_PK')
assert.strictEqual(results[1].publicKey, 'SHARED_PK')
})
it('刷新期间 isXeapiPublicKeyRefreshing 为 true', async () => {
let sawRefreshing = false
await runtimeState.ensureXeapiPublicKey(async () => {
sawRefreshing = runtimeState.isXeapiPublicKeyRefreshing()
return { publicKey: 'X' }
})
assert.strictEqual(sawRefreshing, true)
assert.strictEqual(runtimeState.isXeapiPublicKeyRefreshing(), false)
})
})
describe('reset', () => {
it('清空 token 与 publicKey', () => {
runtimeState.setAnonymousToken('TOKEN')
runtimeState.setXeapiPublicKey({ publicKey: 'PK' })
runtimeState.reset()
assert.strictEqual(runtimeState.getAnonymousToken(), '')
assert.strictEqual(runtimeState.getXeapiPublicKey(), null)
})
})
})