/
kochkatech
/
CorpGame
Обзор
Документация
Войти
/
kochkatech
/
CorpGame
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
1
CI/CD
Аналитика
dev
backend/src/common/keyed-mutex.ts
40 строк
2 KB
kochkareal
feat(devops): свод к одному процессу Node на SQLite, портативная сборка без Docker; аудит безопасности
06 авг 2026, 15:06
06 авг 2026, 15:06
3266bcd
Код
Авторство
О чём код?
/** * Последовательный доступ к ключу внутри процесса: два `acquire` одного ключа не * пересекаются во времени, разные ключи независимы и идут параллельно. * * Игра работает одним процессом (см. README), поэтому распределённая блокировка не нужна — * достаточно очереди в памяти. Раньше её роль играл `SELECT ... FOR UPDATE` в Postgres. * * Реализация — цепочка промисов на ключ: каждый новый захват ждёт «хвост» очереди и сам * становится новым хвостом. Когда очередь опустела, запись удаляется, чтобы Map не рос * за время игры. */ export class KeyedMutex { private readonly tails = new Map<string, Promise<void>>(); /** Резолвится, когда ключ свободен. Возвращает функцию освобождения — вызывать в finally. */ acquire(key: string): Promise<() => void> { const previous = this.tails.get(key) ?? Promise.resolve(); let finish!: () => void; const current = new Promise<void>((resolve) => { finish = resolve; }); // Новый хвост резолвится, когда отработала и очередь до нас, и мы сами. const tail = previous.then(() => current); this.tails.set(key, tail); return previous.then(() => () => { // Хвост убираем, только если после нас никто не встал в очередь: иначе затрём // чужую цепочку и два держателя окажутся в критической секции одновременно. if (this.tails.get(key) === tail) this.tails.delete(key); finish(); }); } /** Сколько ключей сейчас занято — для тестов и диагностики. */ get size(): number { return this.tails.size; } }