mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
47462793f7
Two residual silent `===` mismatches the #2700 Buffer-coercion sweep missed. The legacy single-pod sysRedis returns strings, but the HA/Sentinel sysRedis (preview now, prod after the upcoming cutover) returns BLOB_STRING replies as a Buffer. A Buffer is never strictly-equal to a string literal, so `value === '1'` silently evaluates false under Sentinel — no throw, just wrong behavior. Mirrors the canonical coercion from #2697/#2700. scanner-policies.service.ts (isRunCancelled): markRunCancelled sets the key to '1'. Pre-fix `v === '1'` compared a Buffer to the string → always false → run cancellation silently never detected in sentinel mode. Coerce to utf8 before the compare; try/catch fail-open behavior unchanged. image.service.ts (isImageScannerNewEnabled) — higher priority, it's destructive: a Buffer matched none of the four literals ('1'/'true'/'0'/'false') → fell through and DESTRUCTIVELY overwrote the operator's '1' with 'false', then returned false. The pure decision is extracted into image-scanner-flag.ts (parseScannerFlag → true/false/null) so the coercion + the seed-only-on-unset behavior is unit-testable without loading the ~7.9K-line image.service module (which drags in Prisma/env/auth at import and can't load under vitest). null == genuinely-unset → the only case the seed('false') still fires. Default-seeding behavior for the genuinely-null case is unchanged. Tests: scanner-policies.buffer.test.ts asserts Buffer('1')→true (the bug), string('1')→true (unchanged), Buffer('0')/null/other→false, thrown→false (fail-open). image-scanner-flag.buffer.test.ts asserts parseScannerFlag over Buffer/string/null/unknown inputs. Both confirmed non-vacuous (reverting a coercion turns the Buffer cases red). Pre-Sentinel-cutover hardening alongside #2697/#2700/#2710. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
/**
|
|
* Pure decision helper for the `image-scanner-new` sysRedis kill-switch.
|
|
*
|
|
* Lives in its own tiny module so the Buffer-coercion + seed-only-on-unset
|
|
* behavior is unit-testable without importing the ~7.9K-line image.service
|
|
* (which drags in Prisma/env/auth at load time and can't load under vitest).
|
|
*
|
|
* sysRedis.get is typed `string` but the HA/Sentinel client returns a Buffer
|
|
* for BLOB_STRING replies, matching none of the four literals → pre-fix
|
|
* `isImageScannerNewEnabled` fell through and DESTRUCTIVELY overwrote the
|
|
* operator's '1' with 'false' (then returned false). Coerce once before
|
|
* comparing. See PR #2697/#2700 for the canonical Buffer-vs-string regression.
|
|
*
|
|
* Returns:
|
|
* - `true` for '1' / 'true'
|
|
* - `false` for '0' / 'false'
|
|
* - `null` for a genuinely-unset/unknown key — the ONLY case in which the
|
|
* caller should default-seed 'false'.
|
|
*/
|
|
export function parseScannerFlag(raw: unknown): boolean | null {
|
|
const value = Buffer.isBuffer(raw) ? raw.toString('utf8') : raw;
|
|
if (value === '1' || value === 'true') return true;
|
|
if (value === '0' || value === 'false') return false;
|
|
return null;
|
|
}
|