Заведи каркас пакета и утилитный слой MCP-сервера
package.json, tsconfig, eslint, генерация типов из OpenAPI-спеки, модули config/redact/errors/money/sanitize/cache с тестами и обезличенные фикстуры живых ответов API openrusrouter.ru. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
29 files changed
+11350
No files matched your search
@@ -0,0 +1,42 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createTtlCache } from "../src/cache.js";
|
||||
|
||||
test("значение живёт ttl и потом перезагружается", async () => {
|
||||
let t = 1_000;
|
||||
let calls = 0;
|
||||
const get = createTtlCache(100, async () => ++calls, () => t);
|
||||
assert.equal(await get(), 1);
|
||||
t += 99;
|
||||
assert.equal(await get(), 1);
|
||||
t += 1;
|
||||
assert.equal(await get(), 2);
|
||||
assert.equal(calls, 2);
|
||||
});
|
||||
|
||||
test("single-flight: один loader на N параллельных get()", async () => {
|
||||
let calls = 0;
|
||||
let release!: (v: string) => void;
|
||||
const get = createTtlCache(1_000, () => {
|
||||
calls++;
|
||||
return new Promise<string>((r) => {
|
||||
release = r;
|
||||
});
|
||||
});
|
||||
const all = Promise.all(Array.from({ length: 10 }, () => get()));
|
||||
release("ok");
|
||||
assert.deepEqual(await all, Array(10).fill("ok"));
|
||||
assert.equal(calls, 1);
|
||||
});
|
||||
|
||||
test("ошибка не кэшируется", async () => {
|
||||
let calls = 0;
|
||||
const get = createTtlCache(1_000, async () => {
|
||||
calls++;
|
||||
if (calls === 1) throw new Error("fail");
|
||||
return "ok";
|
||||
});
|
||||
await assert.rejects(get(), /fail/);
|
||||
assert.equal(await get(), "ok");
|
||||
assert.equal(calls, 2);
|
||||
});
|
||||
Reference in new issue
Block a user