5.0 KiB
Рантайм школы: поток и ECS
Договорённость, которую код фазы 2 уже выполняет: каждая школа — свой работник, свой Arch
World, свой файл. Инвариант в AGENTS.md совпадает с этим текстом.
Экран и defs: near-term.md, defs.md.
Куда класть код: projects.md.
Работник (поток, очередь, сейв-файл) живёт в Server. То, что он тикает — School в
Simulation. Каталог, с которым школа создана — Content, замороженный у работника.
Что уже почти есть
У каждой School уже свой Arch World. Это оставляем и делаем жёстким правилом: мир не
разделяется между школами и не отдаётся чужому потоку. Arch не потокобезопасен.
Целевая модель — в этом срезе
Каждая школа — актор: свой поток (TaskCreationOptions.LongRunning / выделенный поток, не
пул тиков), свой World, свои часы, свой замороженный каталог def, свой файл на диске.
Над ними — тонкий супервизор (вместо сегодняшнего общего цикла):
- создать / удалить школу, знать лимит;
- держать ящики:
id →очередь команд этой школы; - собирать снимки для
GET /api/schools(работник публикует неизменяемое состояние, как сейчас цикл публикуетSchoolsState); - маршрутизировать сокет:
OpenSchool/SetRunning/ кадры часов — только в ящик той школы; - при старте процесса поднять школы с диска, при остановке — дождаться записи работников.
Супервизор не вызывает World, не тикает часы, не читает defs инстанса. Работник не
трогает чужой мир и не ходит в ASP.NET. Файл школы пишет работник (create/delete через
команду супервизору, снимок часов — редкий, shutdown — обязательный).
Тик по-прежнему фиксированный (SimulationOptions.FixedDeltaTime), у каждого работника свой
таймер. Школы не синхронизируют календарь друг с другом — так и задумано.
Пока школ максимум шесть, шесть потоков — нормально. Не ставить тик симуляции на ThreadPool:
под нагрузкой его заберут запросы и часы начнут плыть.
Зачем ломать текущий цикл
Один поток на все школы дешевле и проще (нет гонок между мирами). Отдельный поток нужен, когда школы перестанут быть «только часы»: моды, карта, ECS. Тогда одна тяжёлая школа не должна останавливать остальные, и набор модов у школы A не должен быть глобальным синглтоном процесса.
Каталог def на школу, не на процесс: при создании выбирают моды, работник грузит папки и больше их не перечитывает. Иначе правка JSON на диске внезапно меняет уже идущую школу.
Как это стыкуется с сокетом и меню
Как сейчас по смыслу, другое только «кто трогает School»:
- входящее с HTTP/WS → команда в ящик школы (или супервизору, если это create/delete);
- меню читает опубликованный снимок, без блокировки работника;
- исходящие кадры часов — из работника в outbox соединения, не наоборот.
Инвариант вместо «только поток цикла трогает registry» становится: только работник школы
трогает её School / World / каталог; супервизор трогает только таблицу ящиков.
Пока не делаем
- Потоки на системы внутри одной школы (job system как у RimWorld).
- Миграция живой школы на другой набор модов.
- Запись сейва на каждом тике.