test/chat-cachekey-reuse-contract.test.js
Rama master · réplica de lectura del repositorio original.
import { describe, it, beforeEach, afterEach } from 'node:test';
import { readFileSync } from 'node:fs';
import assert from 'node:assert/strict';
import { cacheKey, cacheGet, cacheSet, cacheClear, cacheStats } from '../src/cache.js';
// WHY THIS EXISTS
//
// The inner chat path now reuses `context.__originalCkey` instead of recomputing
// `cacheKey(body, callerKey)` (measured 1.09 ms @400 messages, 2.96 ms @4 MB image —
// and it was computed twice per request). The reuse is gated on `!__fallbackAttempt`
// because the auto-fallback path REWRITES body.model before re-entering: that is the
// H-3 design where the lookup must use the fallback model while the write goes into the
// original slot.
//
// Measured 2026-09-13: deleting that guard left 110 cache/fallback tests green. The
// reason is structural — `cacheSet` only accepts keys the CALLER passes, so no existing
// test can observe "which key did the inner path use". These assertions pin the
// contract at the only level that can see it, by reproducing exactly what the inner
// path does with each combination.
const ORIGINAL = { model: 'glm-5.1', messages: [{ role: 'user', content: 'hi' }] };
const FALLBACK = { model: 'glm-5.2', messages: [{ role: 'user', content: 'hi' }] };
const CALLER = 'team:alice:client:abc';
describe('chat cache key reuse contract (perf change 2026-09-13)', () => {
beforeEach(() => {
process.env.RESPONSE_CACHE_ENABLED = '1';
process.env.WINDSURFAPI_RESPONSE_CACHE = '1';
cacheClear();
});
afterEach(() => { cacheClear(); });
it('the outer key is computed from the ORIGINAL body, before any fallback rewrite', () => {
const originalCkey = cacheKey(ORIGINAL, CALLER);
assert.notEqual(originalCkey, cacheKey(FALLBACK, CALLER), 'the two models must not collide');
});
it('non-fallback: reusing the outer key is identical to recomputing (the optimisation is sound)', () => {
const outer = cacheKey(ORIGINAL, CALLER);
const recomputed = cacheKey(ORIGINAL, CALLER);
assert.equal(outer, recomputed, 'same body + same callerKey must be a stable key');
});
it('fallback attempt: the inner path must NOT reuse the outer key', () => {
// Reproduce the inner path for both branches and show they address different slots.
const outer = cacheKey(ORIGINAL, CALLER); // written by handleChatCompletions:2778
const innerReused = outer; // what the buggy guard does
const innerFresh = cacheKey(FALLBACK, CALLER); // what !__fallbackAttempt must yield
assert.notEqual(innerReused, innerFresh, 'the guard is load-bearing: these are different cache slots');
// And prove the difference is observable through the cache itself: an entry stored
// under the fresh (fallback) key must be invisible to a lookup under the reused one.
cacheSet(innerFresh, { text: 'fallback answer', ts: Date.now() });
assert.equal(cacheGet(innerReused), null, 'a fallback-model entry must not be served as the original model');
assert.ok(cacheGet(innerFresh), 'and the fallback key itself does resolve');
});
it('the cache must be on for the assertion above to mean anything', () => {
const stats = cacheStats();
assert.equal(stats.enabled, true, `cache disabled (${JSON.stringify(stats)}) — cacheGet is always null and the test would be vacuous`);
});
// STRUCTURAL, and deliberately so. The assertions above pin the KEY derivation, which
// is all a cache-level test can see; they cannot see whether chat.js actually consults
// `__fallbackAttempt` before reusing. Measured: deleting that conjunct from chat.js
// leaves every behavioural cache test green (110 tests), because `cacheSet` only ever
// receives keys its caller passes. "Which key did the inner path choose" is not
// observable through the cache API, so the guard is pinned at source level and the
// comment above it explains what it protects. This is the rubric's sanctioned case:
// a proposition about code shape that behaviour cannot express.
it('chat.js gates the reuse on !__fallbackAttempt, and says why', () => {
const src = readFileSync(new URL('../src/handlers/chat.js', import.meta.url), 'utf8');
assert.match(
src,
/reuseOriginalCkey[\s\S]{0,600}?__fallbackAttempt/,
'the inner ckey reuse must stay gated on __fallbackAttempt',
);
assert.match(
src,
/reuseOriginalCkey\s*=\s*typeof context\.__originalCkey === 'string'/,
'and it must require a non-empty outer key rather than reusing undefined',
);
});
});