Раздел 46 · Effect: Тихая Академия

Финальный босс: город на одном сервере

senior~170 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Мантия профессора всё ещё висит на манекене в кабинете Аркканцлера, там же, где ты увидел её в уроке 116. Все части города ты уже собирал, только по отдельности. Башня разбирает кадры и не прячет ошибок (урок 75). Магистраль читает кадры двух версий по Schema (урок 89). Почтамт держит окошки, книги на SQL и честно говорит о себе (урок 102). Линия без хозяина доставляет письмо без потерь и без дублей, что бы ни перезапустили по дороге (урок 112).

Теперь у них одна база и один сервер. Письмо, принятое в окошке, и строка outbox ложатся одной транзакцией. Кадр с провода проходит те же проверки, что письмо из окошка. Насос переносит outbox в очередь линии, а путь письма живёт в движке workflow. Нового в уроке нет: всё это ты уже умеешь, теперь собери вместе.

Что нужно городу

Код Почтамта, Магистрали и башни лежит рядом как есть, править его нельзя: src/pochtamt/, src/magistral/, src/bashnya/. Модули линии из этапов 1-7 твои. Новый модуль один, src/city.ts.

  • Одна база. Миграции Почтамта и outbox линии в одном наборе, второй прогон ничего не делает.
  • Письмо и outbox одной транзакцией. Окошко пишет письмо в книгу Почтамта и строку outbox вместе: половины записи не бывает.
  • Граница города. Строка с провода: JSON это кадр Магистрали любой версии, остальное кадр старой башни. Текст становится письмом после той же проверки адреса, что в окошке; служебный кадр письмом не становится; мусор это LineRejected с причинами.
  • Насос. Outbox в очередь линии, у письма статус sent, воркер запускает пути. Второй проход по пустому outbox отдаёт ноль.
  • Город целиком. Окошки и линия одним слоем. Базу, книгу башен, шардинг и движок workflow город получает снаружи: на репетиции PGlite и всё в памяти, на экзамене PostgreSQL и настоящий кластер.

Точные сигнатуры и тексты лежат в описании этапа.

Чек-лист перед сдачей

  1. Тесты всех прошлых этапов зелёные.
  2. В базе таблицы journal, letters и outbox, второй migrateCity отдаёт [].
  3. Письмо через окошко ложится в книгу, журнал и outbox; письмо на T-404 это UnknownAddress, и строк не прибавилось.
  4. Кадр старой башни, кадр Магистрали v2 и кадр v1 становятся письмами от первой башни пути к последней.
  5. Пинг и квитанция дают Option.none(), мусор это LineRejected.
  6. dispatch отправляет все письма из outbox и второй раз ноль; у отправленных писем в окошке статус sent, башни приняли свои письма.

Репетиция

Репетиция бесплатная и идёт в браузере: тесты города и всех этапов, которые потом пойдут и на экзамене, но база в памяти. PostgreSQL и сервер живым процессом проверяет только экзамен.

Экзамен

Экзамен тем же кодом, но по-настоящему, и проверяет его GitHub CI.

  1. Создай репозиторий из шаблона bondiano/most-liniya-template и перенеси туда src/ репетиции.
  2. Допиши src/main.ts: сервер города на PostgreSQL, кластер из одного раннера с сообщениями в той же базе, насос раз в секунду, трассы в коллектор OTLP и запуск через NodeRuntime.runMain.
  3. Привяжи репозиторий в настройках, в строке «Линия башен».

Каждый пуш гоняет скрытые проверки на PostgreSQL 17: тесты всех этапов, город на настоящей базе и твой сервер живым процессом, который должен принять письмо, отправить его, отдать трассы и спокойно остановиться по SIGTERM. Засчитывается проверка с премиумом. Подробности в описании этапа.

Нестабильно. Город стоит на effect/cluster, effect/workflow, effect/persistence, effect/http-api и effect/observability: в 4.1 всё это помечено @stability unstable. Урок и грейдер написаны на 4.1.0.

Подумай до кода

  • Где теряется письмо. Пройди путь одного письма от окошка до башни адресата и найди каждое место, где падение процесса раньше теряло бы письмо или удваивало его. Какой этап закрывает каждое из них?
  • Что меняется на экзамене. Город получает SqlClient, шардинг и движок снаружи. Сколько строк src/city.ts поменяется, когда PGlite станет PostgreSQL, а TestRunner кластером в базе?

Практика

Глубже в архиве

Что такое сигналы процесса и почему SIGTERM просит завершиться по-хорошему, а SIGKILL нет, разобрано в уроке о Linux и администрировании раздела про инфраструктуру.

Итог

Пока ты переносил книги на PostgreSQL, Пондер разбирал старые кадры из архива Почтамта, чтобы проверить миграцию.

Имя он читает про себя и вслух не произносит. Сообщение, которое никогда не теряется, это и есть надёжная система. Спрятанная ошибка не исчезает, она идёт по линии дальше; честный тип ошибки, транзакция с outbox и трасса наружу не дают ей спрятаться.

Ранг за этот заказ: профессор тихих чар.

Дальше

Вечером Патриций выходит на площадь перед Почтамтом. Письма идут, витрина Чонси светится свежими отметками, в окошке голем Дорфл отвечает горожанину и просит проверить его ответ.

Больше он ничего не спрашивает. Рыдкулл снимает мантию с манекена и отдаёт её тебе.

Поздно вечером ты поднимаешься на башню Академии на краю города, ту самую, что молчала в уроке 01. За столом сидит новый студент-скорописец. Его скоропись упала молча, в журнале пусто, и он не понимает почему. Ты садишься рядом и пишешь ему первое заклинание.