раздел 46
Effect: Тихая Академия
Курс для миддла на TypeScript, который пишет на async/await каждый день. Ты скорописец из городской конторы Анкмора: твой код уронил сигнальную башню, а в журнале пусто. Тихая Академия учит обратному городской магии: сначала записать заклинание целиком, потом произносить. Начинаешь с теории типов TypeScript и функционального программирования с нуля, собираешь свой маленький эффект-рантайм и только потом открываешь Effect: типизированные ошибки, сервисы и слои, ресурсы, файберы, расписания, Schema, стримы, HTTP, трассы и кластер. По дороге разбираешься, почему Семафорная Магистраль теряет сообщения и кто прячет её ошибки. Задачи и проверка типов идут прямо в браузере.
Не получилось изменить список. Попробуй ещё раз.
Раздел открыт для всех. Войди, чтобы отмечать пройденные уроки, вести заметки и решать задачи в редакторе. войти
Мастерская: Шифр Магистрали
Мастерская: Котёл Матушки
Мастерская: Свой Гекс
Мастерская: Башня на Effect
- Квитанцииэтап не сдан
- Кадр целикомэтап не сдан
- Обработчик с именемэтап не сдан
- Ошибки делаэтап не сдан
- То, чего быть не можетэтап не сдан
- Итог словамиэтап не сдан
- Книга башенэтап не сдан
- Ответ по тегуэтап не сдан
- Дублиэтап не сдан
- Старый проводэтап не сдан
- Заказ: ночь целикомэтап не сдан
- Провод из контекстаэтап не сдан
- Слой как фабрикаэтап не сдан
- Один журнал на всехэтап не сдан
- Своя сменаэтап не сдан
- Позывной и печатьэтап не сдан
- Имя сменыэтап не сдан
- Дублёрыэтап не сдан
- Заказ: башня из слоёвэтап не сдан
- Что открыл, то закройэтап не сдан
- Линия в слоеэтап не сдан
- Не посерединеэтап не сдан
- Край и сигналэтап не сдан
- Линии к соседямэтап не сдан
- Заказ: башня не течётэтап не сдан
Мастерская: Протокол Магистрали
Мастерская: Почтамт
Мастерская: Линия башен
Уроки раздела
Скорописец: зачем всё это
Библиотека: типы, чтобы читать Effect
Изделие «Шифр Магистрали», крейт shifr
Головология: ФП с нуля
Изделие «Котёл Матушки», крейт kotel
- Действия, вычисления, данные
- Чистые функции
- Неизменяемость
- Функции как значения
- Композиция, pipe и flow
- Каррирование и двойные функции
- Алгебраические типы
- Option: коробка, которая может быть пустой
- Result: дорога в два пути
- Первая ошибка или все сразу
- Назвать узор: функтор и монада
- Генераторы: рецепт без лестницы
- Босс: котёл Матушки
Свой Гекс: рантайм эффектов своими руками
Изделие «Свой Гекс», крейт geks
Первые чары: ядро Effect
Изделие «Башня на Effect», крейт bashnya
Сундук: сервисы и слои
Изделие «Башня на Effect», крейт bashnya
Смерть приходит вовремя: ресурсы и прерывание
Изделие «Башня на Effect», крейт bashnya
Муравейник: файберы и координация
Изделие «Башня на Effect», крейт bashnya
Часы на башне: расписания и время
Изделие «Башня на Effect», крейт bashnya
Печати: Schema
Изделие «Протокол Магистрали», крейт magistral
Магистраль: Stream
Изделие «Протокол Магистрали», крейт magistral
Почтамт: платформа
Изделие «Почтамт», крейт pochtamt
Свет в окнах: наблюдаемость
Изделие «Почтамт», крейт pochtamt
Витрина: Effect во фронтенде
Башни без хозяина: распределённое
Изделие «Линия башен», крейт liniya
Голем: модели и инструменты
Мастерство: тесты, архитектура, переход
Изделие «Линия башен», крейт liniya
Понятия курса
Понятия разобраны внутри уроков. Нажми на понятие, чтобы открыть урок, где оно объясняется.
Скорописец: зачем всё это
- Башня, которая молчитФункция башни на async/await падает молча, а журнал пуст. Что такое эффект на пальцах, чем он отличается от вызова функции, и как устроен курс: от типов и ФП к своему рантайму и Effect.урок 1 · Башня, которая молчитопираются: урок 2
- Как читать «Ук»Ошибки TypeScript: hover, длинные ошибки снизу вверх, strict, exactOptionalPropertyTypes и noUncheckedIndexedAccess. Первый перевод с Ук.урок 4 · Как читать «Ук»опираются: урок 5
- Описание против исполненияPromise уже летит, когда его создали, а функция без вызова ждёт. Рецепт, а не обед: ленивое описание можно повторить, отменить и проверить. Мифы про Effect: размер, скорость, «это RxJS».урок 3 · Описание против исполненияопираются: урок 4
- Слепота к несчастливому путиcatch (e: unknown), нет отмены, таймаутов и повторов, скрытые зависимости, нет трассы. Каждое требование надёжности на голом async/await стоит строк, и код растёт быстрее пользы.урок 2 · Слепота к несчастливому путиопираются: урок 3
Библиотека: типы, чтобы читать Effect
- ДженерикиДженерик как функция над типами: параметры, ограничения, вывод из аргументов, const-параметры типа. Каналы шифра, которые помнят тип сообщений.урок 8 · Дженерикиопираются: урок 9
- Номинальность и брендыБренды на unique symbol, private и protected члены делают класс номинальным, коллизия _tag. Номера башен и сообщений, которые не подделать.урок 14 · Номинальность и брендыопираются: урок 15
- Размеченные объединенияСообщения по полю _tag, разбор switch до never, absurd и проверка полноты компилятором.урок 7 · Размеченные объединенияопираются: урок 8
- Сужениеtypeof, in, instanceof, предикаты is и asserts: как из unknown с провода получить кадр, которому можно верить.урок 6 · Сужениеопираются: урок 7
- Типы как множестваЛитералы, объединение и пересечение, unknown как всё, never как пустое множество, присваиваемость как вложенность. Таблица кодов ставней для шифра башни.урок 5 · Типы как множестваопираются: урок 6
- Чтение сигнатурПерегрузки, Array.map, Promise.then, перегрузки pipe и NoInfer: как прочитать чужую сигнатуру и предсказать выведенный тип.урок 9 · Чтение сигнатуропираются: урок 10
- Шаблонные литеральные типыКоды башен `T-${number}` и маршруты в типах, infer внутри шаблона и умеренный разбор строк.урок 12 · Шаблонные литеральные типыопираются: урок 13
- keyof и отображённые типыkeyof, индексный доступ, отображённые типы, модификаторы и переименование ключей через as. Таблица обработчиков сообщений.урок 10 · keyof и отображённые типыопираются: урок 11
- Босс: протокол семафораПротокол башни целиком: провод, конверты, разбор с типизированными ошибками и неподделываемые номера, проверенные тестами на типы.урок 16 · Босс: протокол семафораопираются: урок 17
- ВариантностьКто отдаёт, тот ковариантен, кто берёт, контравариантен. Почему ошибки двух задач складываются в объединение и почему never подходит куда угодно; аннотации in и out.урок 13 · Вариантностьопираются: урок 14
- Тесты на типыexpectTypeOf, @ts-expect-error, тест «это не должно собираться» и свои Equal и Expect.урок 15 · Тесты на типыопираются: урок 16
- Условные типы и inferУсловные типы, infer и распределение по объединению: достать A и E из своей ленивой задачи Task<A, E>. Читаем, а не сочиняем головоломки.урок 11 · Условные типы и inferопираются: урок 12
Головология: ФП с нуля
- Алгебраические типыПроизведение и сумма, сколько значений у типа и почему невозможные состояния лучше сделать непредставимыми.урок 23 · Алгебраические типыопираются: урок 24
- Действия, вычисления, данныеДействие зависит от того, когда и сколько раз его вызвали, вычисление нет, данные это просто факты. Раскрашиваем код Ринцвальда и вынимаем из действий вычисления журнала башни.урок 17 · Действия, вычисления, данныеопираются: урок 18
- Композиция, pipe и flowКомпозиция функций, pipe передаёт значение по конвейеру, flow собирает конвейер в функцию. Перегрузки, которые держат типы на каждом шаге.урок 21 · Композиция, pipe и flowопираются: урок 22
- Неизменяемостьreadonly, as const, обновление копией и структурное разделение: новое значение вместо правки старого, и что из старого переходит в новое без копирования.урок 19 · Неизменяемостьопираются: урок 20
- Первая ошибка или все сразуКороткое замыкание против накопления: all останавливается на первой ошибке, validateAll собирает все. Разбор журнала со всеми ошибками и номерами строк.урок 26 · Первая ошибка или все сразуопираются: урок 27
- Функции как значенияФункции высшего порядка и замыкания: условия собираются из маленьких функций, замыкание помнит то, что ему дали при создании.урок 20 · Функции как значенияопираются: урок 21
- Чистые функцииЧистота и ссылочная прозрачность: время и случайность приходят аргументами, вычисление проверяется без моков, а локальная мутация, которую не видно снаружи, чистоте не мешает.урок 18 · Чистые функцииопираются: урок 19
- Option: коробка, которая может быть пустойOption против null и undefined: some, none, fromNullable, map, flatMap, getOrElse и match. Пустую коробку не открывают.урок 24 · Option: коробка, которая может быть пустойопираются: урок 25
- Result: дорога в два путиResult как железная дорога: map, flatMap, mapError, tap и match. Ошибка видна в типе, а ошибки шагов складываются в объединение.урок 25 · Result: дорога в два путиопираются: урок 26
- Босс: котёл МатушкиМини-библиотека целиком: разбор кадров Магистрали без единого throw, все ошибки ночи сразу и подтверждения кадров, которых башня не отправляла.урок 29 · Босс: котёл Матушкиопираются: урок 30
- Генераторы: рецепт без лестницыПротокол итератора, yield и yield*, do-нотация для своего Option на генераторах. Мост к Effect.gen.урок 28 · Генераторы: рецепт без лестницыопираются: урок 29
- Каррирование и двойные функцииКаррирование, data-first и data-last, Function.dual: почему в Effect работают и Option.map(box, f), и pipe(box, Option.map(f)).урок 22 · Каррирование и двойные функцииопираются: урок 23
- Назвать узор: функтор и монадаФунктор это честный map, монада это flatMap без коробки в коробке. Законы как тесты на свойства с fast-check.урок 27 · Назвать узор: функтор и монадаопираются: урок 28
Свой Гекс: рантайм эффектов своими руками
- Ошибка в типеIO<A, E>: свиток кончается Exit, а не исключением. Ожидаемая ошибка Fail против дефекта Die, catch и mapError, ошибки шагов складываются в объединение.урок 31 · Ошибка в типеопираются: урок 32
- Свиток на потом: свой IOДействие как значение: IO<A> хранит, что сделать, и делает это только при запуске. succeed, sync, map, flatMap и runSync на замыканиях.урок 30 · Свиток на потом: свой IOопираются: урок 31
- Сундук: окружение RIO<A, E, R>: свиток просит сервисы из Сундука по именам. service, provideService вычитает имя из R, запуск возможен только с пустым R. Почему R складывается объединением.урок 32 · Сундук: окружение Rопираются: урок 33
- Босс: Гекс, который умеет остановитьсяПрерывание и финализаторы в своём рантайме: runFork, interrupt, ensuring, acquireUseRelease. Таблица соответствий своего Гекса и настоящего Effect.урок 35 · Босс: Гекс, который умеет остановитьсяопираются: урок 36
- Свиток на генератореСвиток сам отдаётся в yield*, как в Effect 4; gen выводит ошибки и нужды всех шагов. Чем это отличается от адаптера Option.open.урок 34 · Свиток на генератореопираются: урок 35
- Цикл ГексаСвиток деревом инструкций и цикл со стеком продолжений: сто тысяч flatMap без переполнения, асинхронность через callback, runPromise.урок 33 · Цикл Гексаопираются: урок 34
Первые чары: ядро Effect
- ДефектыДефекты: die, orDie, catchDefect. Где граница между ожидаемой ошибкой и дефектом и почему дефекта нет в типе.урок 40 · Дефектыопираются: урок 41
- Квитанция Effect<A, E, R>Effect<A, E, R> как квитанция: что получу, как упадёт, что нужно. succeed, sync, try, tryPromise, fail; runSync, runPromise и Exit.урок 36 · Квитанция Effect<A, E, R>опираются: урок 37
- Мост наружуМост к промисам и колбэкам: tryPromise, Effect.callback; runPromise только на краю программы.урок 45 · Мост наружуопираются: урок 46
- Ожидаемые ошибкиData.TaggedError и Schema.TaggedError, catch, catchTag с массивом тегов, mapError; коллизия _tag и как от неё защититься.урок 39 · Ожидаемые ошибкиопираются: урок 40
- Data и EqualData, Equal и Hash: равенство по значению, Data.Class и TaggedEnum, HashSet; ловушка с изменяемыми ключами.урок 44 · Data и Equalопираются: урок 45
- Effect.fn: функции с именемEffect.fn("Module.name") для переиспользуемых функций, fnUntraced, Effect.fn.Return и комбинаторы дополнительными аргументами.урок 38 · Effect.fn: функции с именемопираются: урок 39
- Effect.gen и pipeEffect.gen и pipe это один и тот же flatMap; async/await против gen/yield*, return yield*, andThen, map и tap.урок 37 · Effect.gen и pipeопираются: урок 38
- Match: полное сопоставлениеMatch: полное сопоставление, Match.tag, Match.tags и Match.literals из 4.1; забытый вариант не соберётся.урок 43 · Match: полное сопоставлениеопираются: урок 44
- Option и Result внутри EffectOption и Result больше не эффекты: Effect.fromOption, fromResult, Effect.result и Effect.option.урок 42 · Option и Result внутри Effectопираются: урок 43
- Босс: обработчик кадров башниОбработчик кадров башни на Effect: каждая ошибка в типе или в отчёте, ни одной проглоченной. Улика catch {} в коде Магистрали.урок 46 · Босс: обработчик кадров башниопираются: урок 47
- Cause и ExitCause в v4 плоский, с массивом reasons; Exit, Cause.pretty. Ловушка: если в причине есть дефект, catchTag пропускает и типизированную ошибку.урок 41 · Cause и Exitопираются: урок 42
Сундук: сервисы и слои
- Граф слоёвСлой, которому нужен другой слой: Layer.provide, provideMerge, mergeAll. Провод и смена пишут в один журнал; Layer.satisfiesServicesType<never>() ловит забытую зависимость на типах.урок 49 · Граф слоёвопираются: урок 50
- Конфигурация и RedactedConfig.String, Config.Redacted, orElse и withDefault; ConfigProvider.fromUnknown в тестах; сервис-строка из конфигурации и ошибка ConfigError в слое.урок 51 · Конфигурация и Redactedопираются: урок 52
- Сервисы: что нужно, без того, где взятьContext.Service<Self, Shape>()("bashnya/Wire"), yield* в Effect.gen, Wire.of и Wire["Service"]. Зависимость уезжает из аргументов в R, а первый способ её дать это Effect.provideService.урок 47 · Сервисыопираются: урок 48
- Слой как фабрикаLayer.succeed для готового значения, Layer.effect для сервиса со своим состоянием, Effect.provide. Соглашение layer, layerTest, layerConfig статическими полями класса сервиса.урок 48 · Слой как фабрикаопираются: урок 49
- Ссылки со значением по умолчаниюContext.Reference вместо FiberRef из v3: значение по умолчанию, поэтому в R ссылки нет. References.CurrentLogLevel и подмена на кусок программы через provideService.урок 52 · Ссылки со значением по умолчаниюопираются: урок 53
- Босс: башня из слоёвБашня собирается из слоёв в проде и в тесте, R пуст у обеих сборок. Позывной и ключ из конфигурации, ленивая книга, журнал один на смену.урок 54 · Босс: башня из слоёвопираются: урок 55
- Сколько раз построен слойEffect 4 переиспользует слой, построенный внешним provide, а соседние provide строят свой. Слой в обработчике каждого кадра, { local: true } и Layer.fresh.урок 50 · Сколько раз построен слойопираются: урок 51
- Тестовые слои и дублёрыLayer.mock, it.effect и layer(...) из @effect/vitest, TestClock; ленивый слой на Deferred, который готов сразу и ждёт данные только при первом вопросе.урок 53 · Тестовые слои и дублёрыопираются: урок 54
Смерть приходит вовремя: ресурсы и прерывание
- Ресурс в слоеLayer.effect в Effect 4 сам даёт область: ресурс, взятый при сборке слоя, закрывается, когда слой разбирают, и узнаёт исход программы. Layer.scoped из v3 больше нет.урок 56 · Ресурс в слоеопираются: урок 57
- Scope и финализаторыEffect.acquireRelease: взятие и возврат рядом, возврат знает Exit. Область Scope копит финализаторы и закрывает их в обратном порядке; Effect.scoped убирает Scope из R; addFinalizer.урок 55 · Scope и финализаторыопираются: урок 56
- Босс: башня не течётНочь от сигнала до кода выхода: хорошая, с провалом открытия и с выдернутым шнуром. После каждой склад пуст, ресурсы закрыты в обратном порядке с верным исходом.урок 60 · Босс: башня не течётопираются: урок 61
- Край программы: runMain и ManagedRuntimeКод выхода 0, 1 и 130; свой runMain из Runtime.makeRunMain, сигнал как прерывание главного файбера. ManagedRuntime собирает слой один раз для чужого сервера и закрывает по dispose.урок 58 · Край программы: runMain и ManagedRuntimeопираются: урок 59
- Общие ресурсы: RcMap, RcRef и PoolСчётчик ссылок и время простоя: RcMap по ключу, RcRef для одного ресурса, Pool для нескольких одинаковых. Линия к соседу открывается при первой отправке и закрывается после простоя.урок 59 · Общие ресурсы: RcMap, RcRef и Poolопираются: урок 60
- ПрерываниеПрерывание не ошибка и не дефект: Effect.catch его не ловит. uninterruptible откладывает прерывание до конца куска; onInterrupt и ensuring добавляют действие на выходе.урок 57 · Прерываниеопираются: урок 58
Муравейник: файберы и координация
- Гонки и времяraceAll отдаёт первый успех и прерывает остальных; timeout и timeoutOption; firstSuccessOf пробует запасных по очереди. Почему Promise.race не останавливает проигравших.урок 64 · Гонки и времяопираются: урок 65
- Много сразу: all, forEach, validate, partitionconcurrency и предел одновременности, результаты в порядке элементов, discard. validate собирает все ошибки, partition делит удачи и ошибки.урок 63 · Много сразу: all, forEach, validate, partitionопираются: урок 64
- Общее состояние: RefПотерянное обновление между чтением и записью; Ref.update и Ref.modify одним шагом; SynchronizedRef для обновления с эффектом; SubscriptionRef с потоком изменений.урок 65 · Общее состояние: Refопираются: урок 66
- СемафорПредел на узкое место, а не на того, кто шлёт: Semaphore и withPermits с возвратом при любом исходе. RateLimiter как предел за время, нестабильный в 4.1.урок 67 · Семафоропираются: урок 68
- ФайберыФайбер это исполняемая квитанция: forkChild, Fiber.join, Fiber.await, Fiber.interrupt. Пульс башни в фоне, дерево файберов и прерывание вниз по дереву.урок 61 · Файберыопираются: урок 62
- Босс: сто соседей сразуНочь, где кадры обрабатываются вперемешку и не больше предела сразу, а отчёт тот же, что по одному кадру: дубли через Seen одним шагом, судьбы собираются в порядке строк.урок 71 · Босс: сто соседей сразуопираются: урок 72
- Ждать сигнала: Deferred и LatchОдноразовая ячейка Deferred и своя гонка на ней; ворота Latch, которые можно открыть и закрыть; свой мьютекс из Ref и Deferred и его дыра с прерыванием.урок 66 · Ждать сигнала: Deferred и Latchопираются: урок 67
- Как устроены файберыОдин поток и планировщик; уступка при ожидании, по yieldNow и по бюджету 2048 шагов; почему Effect.sync не прервать; keep-alive у runMain; Worker для долгих расчётов.урок 70 · Как устроены файберыопираются: урок 71
- Очереди: Queue и PubSubПроизводитель и потребитель; ограниченная очередь и противодавление, dropping и sliding; PubSub отдаёт каждое сообщение каждому подписчику. Почему unbounded опасна для входящих.урок 68 · Очереди: Queue и PubSubопираются: урок 69
- Структурная конкурентностьРебёнок forkChild живёт не дольше родителя. Исключения явные: forkScoped к области из контекста, forkIn к названной области, forkDetach ни к кому.урок 62 · Структурная конкурентностьопираются: урок 63
- Транзакции: TxRef и Effect.txНесколько ячеек одним шагом: TxRef, Effect.tx и txRetry, который ждёт перемены прочитанного. Оптимистичная конкурентность и почему внутри транзакции нет дел с миром.урок 69 · Транзакции: TxRef и Effect.txопираются: урок 70
Часы на башне: расписания и время
- По чьим часам: Clock и TestClockВремя это сервис: Clock, Duration, DateTime. Почему Date.now и setTimeout в башне запрещены; TestClock из effect/testing: adjust, setTime, сутки за миллисекунды.урок 74 · По чьим часам: Clock и TestClockопираются: урок 75
- Повторы: retry и repeatretry повторяет провал, repeat успех; while, until, times и schedule. Повторять только то, что может пройти; min, max и concat; Effect.schedule и cron с часовым поясом.урок 73 · Повторы: retry и repeatопираются: урок 74
- РасписаниеРасписание это значение: recurs, spaced, fixed, exponential, jittered, upTo, while. Чем spaced отличается от fixed, зачем джиттер и почему повтор без паузы это молоток.урок 72 · Расписаниеопираются: урок 73
- Босс: башня, которая чинит себя самаПредел на попытку, повторы обрывов и молчания с джиттером, общий срок строки, отчёт без ошибок в типе. Ночь проверяется на TestClock за миллисекунды.урок 75 · Босс: башня, которая чинит себя самаопираются: урок 76
Печати: Schema
- Бланк договора: Struct, Union, LiteralsStruct, Union, Literals, Tuple, Record; optionalKey против optional и exactOptionalPropertyTypes; typeof Schema.Type.урок 77 · Бланк договора: Struct, Union, Literalsопираются: урок 78
- Классы схемSchema.Class с поведением, TaggedClass, TaggedError, mapFields для производных схем.урок 80 · Классы схемопираются: урок 81
- Один договор, много копийИз схемы выводятся JSON Schema, Equivalence и генератор для свойств; закодировал и разобрал, вышло то же. Схема как договор с моделью.урок 83 · Один договор, много копийопираются: урок 84
- Почему отказ: SchemaIssueДерево SchemaIssue, все ошибки сразу через errors: all, путь и сообщение для людей вместо invalid input.урок 81 · Почему отказ: SchemaIssueопираются: урок 82
- Проверки и брендыcheck с готовыми фильтрами, refine, brand: значение, которое нельзя подделать строкой. Где ставить проверку, чтобы её нельзя было обойти.урок 78 · Проверки и брендыопираются: урок 79
- Разбирай, а не проверяйСхема это тип, разбор и запись сразу. decodeUnknownEffect и SchemaError вместо JSON.parse и as; проверенное значение несёт проверку в типе. Чем Schema отличается от Zod.урок 76 · Разбирай, а не проверяйопираются: урок 77
- Босс: две версии протоколаКадры Магистрали v1 и v2 разбираются одной схемой, v1 мигрирует при разборе, наружу только v2; отказы словами.урок 84 · Босс: две версии протоколаопираются: урок 85
- Две стороны схемыEncoded на проводе, Type в программе: decodeTo, SchemaTransformation, fromJsonString. Ловушка Schema.Date против строки в JSON.урок 79 · Две стороны схемыопираются: урок 80
- Рекурсия и проверки с миромsuspend для схем, которые ссылаются на себя; проверка, которой нужен сервис, прямо в разборе и в R.урок 82 · Рекурсия и проверки с миромопираются: урок 83
Магистраль: Stream
- Мёртвые письма: Sink и ChannelОчередь мёртвых писем вместо выброшенного мусора; Sink как значение, куда течёт поток; Channel под капотом; горячий поток на SubscriptionRef.урок 88 · Мёртвые письмаопираются: урок 89
- Поток вместо массиваStream как тянущий поток и рецепт: callback и fromEventListener для источников, которые толкают сами, fromEffectRepeat для тех, кого тянут; map, filter, mapEffect, run*.урок 85 · Поток вместо массиваопираются: урок 86
- ПротиводавлениеТянущий поток не берёт лишнего; толкающему нужен буфер и решение, что терять: suspend, dropping, sliding. Stream.buffer между шагами.урок 86 · Противодавлениеопираются: урок 87
- Босс: ретрансляторНочь Магистрали потоком: дубли узнаются по ключу, свои кадры доставлены, чужие уходят пачками с повтором, мусор и неотправленное в мёртвых письмах.урок 89 · Босс: ретрансляторопираются: урок 90
- Много линийmerge, mapEffect с concurrency и порядком, grouped и groupedWithin, throttle по кускам, broadcast и broadcastN.урок 87 · Много линийопираются: урок 88
Почтамт: платформа
- Окошки на бумаге: HttpApiHttpApi как договор: группы и эндпоинты на Schema, параметры пути и запроса, тело, статусы ответов, ошибки со статусом и HttpApiError.Problem (4.1); OpenAPI выводится из договора.урок 91 · Окошки на бумаге: HttpApiопираются: урок 92
- Платформа: файлы, пути, хранилище, процессыFileSystem, Path, KeyValueStore и ChildProcess как сервисы; слои платформ Node, Bun и браузера; тестовые слои layerNoop и layerMemory.урок 95 · Подвал Почтамта: платформаопираются: урок 96
- Почтамт из терминала: effect/cliCommand, Argument и Flag на Schema, подкоманды, справка из описания, запуск runWith с тестовыми слоями.урок 96 · Почтамт из терминала: effect/cliопираются: урок 97
- Провод к чужой книге: HttpClientHttpClient как сервис: запрос, ответ по схеме, прослойки mapRequest и filterStatusOk, retryTransient для временных бед; провод в тестах подменяется слоем.урок 90 · Провод к чужой книге: HttpClientопираются: урок 91
- Служебная линия: RPCRpc.make и RpcGroup, обработчики toLayer, потоковый вызов, RpcTest в памяти; когда RPC, когда HTTP.урок 93 · Служебная линия: RPCопираются: урок 94
- Босс: ПочтамтВесь Почтамт одним слоем: окошки на HttpApi, книги на SQL, книга башен по HTTP, архив мёртвых писем на FileSystem; проверка через HttpApiTest на PGlite.урок 97 · Босс: Почтамтопираются: урок 98
- Книги Почтамта: SQLSqlClient и шаблон sql, параметры вместо склейки, SqlSchema на ответах, транзакции withTransaction, миграции Migrator; драйвер это слой, в браузере PGlite.урок 94 · Книги Почтамта: SQLопираются: урок 95
- Окошки открыты: сервер, клиент, тест в памятиHttpApiBuilder.group и layer, обработчики берут сервисы при сборке слоя, производный клиент HttpApiClient, OpenAPI и Scalar, HttpApiTest и toWebHandler без сети.урок 92 · Окошки открыты: сервер, клиент, тест в памятиопираются: урок 93
Свет в окнах: наблюдаемость
- Журнал для того, кто придёт ночьюEffect.log по уровням, пометки annotateLogs, свой логгер слоем через Logger.make и Logger.layer, минимальный уровень; журнал книги башен.урок 98 · Журнал для того, кто придёт ночьюопираются: урок 99
- История одного письма: трассыСпаны withSpan и Effect.fn, атрибуты и annotateCurrentSpan, дерево родителей, трассировщик в памяти для тестов; экспорт OTLP словами.урок 99 · История одного письма: трассыопираются: урок 100
- Сколько: метрикиMetric.counter, Metric.timer и гистограммы, метки withAttributes, чтение Metric.value; почему номер письма не метка.урок 100 · Сколько: метрикиопираются: урок 101
- Босс: честный ПочтамтКнига башен, которой верят только проверенное: пачки, кэш, срок ответа, журнал, трасса и счётчики; недозвон это 503 с причиной, а не «нет такой башни».урок 102 · Босс: честный Почтамтопираются: урок 103
- Сорок башен, четыре тысячи вопросовЗадача N+1: Request и RequestResolver собирают вопросы одного такта в пачку, Cache со сроком по исходу, почему провал не кэшируют.урок 101 · Сорок башен, четыре тысячи вопросовопираются: урок 102
Витрина: Effect во фронтенде
- Окно в лавку: атомы в React@effect/atom-react: RegistryProvider, useAtomValue и useAtom, компонент читает атом, форма на Schema, AtomHttpApi к окошкам Почтамта.урок 104 · Окно в лавку: атомы в Reactопираются: урок 105
- Табличка, которая не врёт: атомыeffect/reactivity: Atom.make и производные атомы, Atom.runtime(layer) к сервисам, AsyncResult как честное «ещё спрашиваю», Atom.family и реестр.урок 103 · Табличка, которая не врёт: атомыопираются: урок 104
- Улица: Effect в браузереСобытия браузера как потоки с отпиской, геолокация и мягкая деградация при отказе, хранилище браузера с запасным путём, модули @effect/platform-browser.урок 105 · Улица: Effect в браузереопираются: урок 106
Башни без хозяина: распределённое
- Одно письмо за раз: акторыСвой актор на Queue и Deferred: состояние, почтовый ящик, одно сообщение за раз; ask и tell; почему блокировки не спасают.урок 107 · Одно письмо за раз: акторыопираются: урок 108
- Очередь, которая помнитPersistedQueue: задания переживают перезапуск, номер попытки, повторы по расписанию, предел попыток, свой id против дублей, задержка; хранилище слоем (память, SQL, Redis).урок 106 · Очередь, которая помнитопираются: урок 107
- Хотя бы раз: гарантии доставкиЗадача двух генералов, at-least-once с квитанцией и повтором, входящие без дублей, «обработано это ответ», сохранённые сообщения кластера.урок 109 · Хотя бы раз: гарантии доставкиопираются: урок 110
- Босс: линия без хозяинаОкошко, outbox, очередь, путь письма на workflow и башни-сущности кластера вместе: Магистраль рушится, линия держит город.урок 112 · Босс: линия без хозяинаопираются: урок 113
- Ключ и outbox: двойная записьКлюч идемпотентности, двойная запись и почему ни один порядок не безопасен, transactional outbox в одной транзакции SQL, повтор вместо потери.урок 110 · Ключ и outbox: двойная записьопираются: урок 111
- Кольцо башен: шарды и сущностиХеш-кольцо с виртуальными узлами против деления по модулю, Entity на Rpc, шарды и TestRunner.layer, где живёт сущность.урок 108 · Кольцо башен: шарды и сущностиопираются: урок 109
- Путь письма: workflowWorkflow и Activity: шаг выполняется один раз и запоминает итог, idempotencyKey, DurableClock и DurableDeferred, движок в памяти для тестов.урок 111 · Путь письма: workflowопираются: урок 112
Голем: модели и инструменты
- Окошко для всех: свой MCP-серверMcpServer: инструменты из Toolkit, ресурсы и промпты, транспорт stdio и HTTP, провал инструмента ответом, проверка в памяти через McpTest.урок 115 · Окошко для всех: свой MCP-серверопираются: урок 116
- Свиток в голове: модель как недоверенный сервисeffect/ai: LanguageModel и промпт, generateText и generateObject со схемой ответа, провайдер слоем, болванка модели в тестах, ключ через Config.Redacted.урок 113 · Свиток в голове: модель как недоверенный сервисопираются: урок 114
- Руки голема: инструменты и цикл агентаTool и Toolkit с обработчиками слоем, Chat и его история, цикл агента с пределом ходов, запасная модель через ExecutionPlan.урок 114 · Руки голема: инструменты и цикл агентаопираются: урок 115
Мастерство: тесты, архитектура, переход
- Записка Гилта: код v3 и инструментыТаблица переименований v3 → v4, ServiceMap и модули unstable из бет, @effect/tsgo, language service и правила линтера.урок 119 · Записка Гилта: код v3 и инструментыопираются: урок 120
- Журнал без правил: архитектура и свои типыСлайсы и границы сервисов, машина состояний на Data.TaggedEnum и Result, свой тип данных на Equal, Hash и Pipeable в HashSet и HashMap.урок 117 · Журнал без правил: архитектура и свои типыопираются: урок 118
- Кто это проверил: тесты на Effect@effect/vitest: it.effect и it.live, TestClock и виртуальное время, тестовые слои, свойства на it.effect.prop из схем, мутанты как проверка самих тестов.урок 116 · Кто это проверил: тесты на Effectопираются: урок 117
- Старая книга: постепенный переход на EffectПаттерн use над Promise-клиентом, пагинация и события потоком, ManagedRuntime на границе со старым кодом, перевод маршрутов Hono по одному.урок 118 · Старая книга: постепенный переход на Effectопираются: урок 119
- Экзамен: город на одном сервереФинальный босс: Почтамт, Магистраль, старые башни и линия на одной базе, outbox в общей транзакции, кадры с провода через те же проверки, что окошко; репетиция в браузере, экзамен в GitHub CI на PostgreSQL.урок 120 · Финальный босс: город на одном сервере