Я ненавижу руками создавать бойлерплейты. Любые. Нет, LLM-ки тут тоже не помогут: им надо писать промпты (а потом ещё проверять, что оно там нагенерировало). Мне всегда хотелось, чтобы остов приложения задавался конфигурацией, а я бы только добавлял бизнес-логику. Буквально, в уже сгенерированные для неё места.

Именно в такой парадигме написана моя библиотека finitomata, в которой конфигурация конечных автоматов задаётся текстовым представлением (PlantUML/Mermaid), а бизнес-логика просто распихивается по колбэкам переходов. Но мне этого оказалось мало, и я решил обернуть в такие же абстракции хранение и подписку на изменения.

Так родилась библиотека (пока не опубликована, доступна только в исходниках) persistomata.

Persitomata :: Flow
Persitomata :: Flow

Я последовательно шёл к этой реализации, поэтому сначала были созданы Rambla для «публикации» в сторонние источники (текст на хабре) и Antenna для умного пабсаба (текст на хабре). Еще у меня завалялась библиотека Telemetría (текст на хабре), которая, вообще-то изначально писалась для упрощения работы с телеметрией, но потом обзавелась пользовательскими плагинами и теперь прекрасно подходит в качестве просто реализации аспектов для эликсира.

Картина с высоты орлиного полёта выглядит так (см. КДПВ):

  • все отслеживаемые сущности являются конечными автоматами (это не страшно, в вырожденном случае он может содержать один переход в то же самое состояние с разными пейлоадами, что эмулирует «просто набор функций»);

  • все переходы между состояниями обёрнуты в аспекты, отсылающие асинхронные сообщения в эфир; на эти сообщения можно подписаться из бизнес-логики (спасибо библиотеке antenna — очень гранулярно, если нужно), и на некоторые — подписано ядро persistomata;

  • внутренние подписки публикуют полученные данные в настроенные «каналы» (спасибо rambla, каналы можно настроить какие угодно — от логов и пресловутой телеметрии, до базы данных) — по умолчанию это Clickhouse.

Таким образом мы просто шлём сообщения нашим конечным автоматам, инициируя переходы, которые отсылают сообщения во внешний эфир и пишут event log в clickhouse.

Из коробки предоставляется (пока одна) mix task, которая сгенерирует саму стейт-машину, тест для неё, и миграции для кликхауза. Миграций будет три, потому что помимо собственно ивентлога, мне потребуется нормальная таблица, которая реализована как materialized view на последних виденных состояниях «объектов».

Если помимо кликхауза — хочется прикрутить Postgres — добавьте свой listener средствами Antenna и пишите оттуда в базу. Нужен обмен горячими данными с братским микросервисом — добавьте RabbitMQ в конфигурацию Rambla. И так далее.

Оно по умолчанию прозрачно работает в кластере (горизонтальное масштабирование из коробки), легко дружится с Phoenix (в качестве примера я скоро допишу на этом движке хаброподобный форум, без модераторов и кармы — это чистый вайбкодинг, кстати, там только архитектура требует работы разработчика, со всем остальном справляются генераторы) и требует буквально нулевые ресурсы на взлёте. На моём ноуте (в контейнере с 8G RAM) бенчмарки показывают 80% загрузки на примерно 1000/50000 запросах в секунду (цифры write/read).

Поскольку я сейчас занят реализацией примера использования, очень интересны вопросы, комментарии и предложения. Всё-таки «хабрафорум» — это востребованный пример, но не совсем то, ради чего я затевался. Я метил преимущественно в микросервисы.

Удачного вайбкодинга!

Комментарии (17)


  1. Zulu0
    22.06.2025 09:00

    Удачного вайбкодинга!

    А ты умеешь в сарказм. Но статья прям хорша, спасибо


  1. mvv-rus
    22.06.2025 09:00

    Мне всегда хотелось, чтобы остов приложения задавался конфигурацией, а я бы только добавлял бизнес-логику. Буквально, в уже сгенерированные для неё места.

    Не кажется ли вам, что вы переоткрыли подход low-code (который ранее переоткрыл Rapid Application Development, который... - и так далее, вглубь истории)?

    А вообще, удачи в создании нового фреймворка, может быть - даже первого на ваших изотерических языках. А то фреймворки на JS у всех на слуху, а про ваши изотерические языки, как оно там с фреймворками, я, например, даже не слышал.

    А что до вайбкодинга, то для него него вам надо поднакописть кодовую базу. Будет база - будет вам и ваш любимый вайбкодинг, например, чтобы вайбкодить эти самые конфигурации. А потребность в вайбкодинге от смены парадигмы с императивной на декларативную никуда не денется. Потому что декларативный подход сложность, на самом деле, не убирает. Вон, судя по народной любви к ORM, на том же SQL народу программировать работу с БД ничуть не проще, чем с навигационным доступом к БД (типа, как в Clipper).


    1. cupraer Автор
      22.06.2025 09:00

      Не кажется ли вам, что вы переоткрыли подход low-code […]

      Нет. Из текста понятно, что ничего общего с low-code в этом решении нет.

      про ваши изотерические языки, как оно там с фреймворками, я, например, даже не слышал

      Нет там фреймворков, куда уж. Discord, Pepsico, J.P. Morgan, Mozilla, BBVA, да все буквально — прямо в машинных кодах херачат.

      А что такое «изотерические», кстати?

      фреймворки на JS у всех на слуху

      Вы путаете фреймворки и костыли.


      1. mvv-rus
        22.06.2025 09:00

        Из текста понятно, что ничего общего с low-code в этом решении нет.

        Из одного только текста - наверное. Но КДПВ смущает: это интефейс дизайнера или так, чисто для красоты?

        А что такое «изотерические», кстати?

        Опечатка.

        Вы путаете фреймворки и костыли.

        Нет. Фреймворк - это почти готовая программа, в которой достаточно в некоторые места подключить свой код, выполняющий полезную работу, не тратя силы на всяки церемонии, чтобы заставить программу работать в той среде, для которой она предназначена. Фреймворки JS (React с обвязкой, Vue, Angular и иже с ними) AFAIK вполне это реализуют.

        Вы, кстати, тоже делаете если не low-code, то, по крайней мере, фреймворк.


        1. cupraer Автор
          22.06.2025 09:00

          Дискуссия превращается в теософско-терминологическую, но я всё-таки вижу кардинальное отличие между тем, что делаю я, и целями, которых добились авторы JS-фреймворков.

          Я не заметаю нативную реализацию под ковер, наоборот: я её буквально выпячиваю. Действительно, имплементация моей стейт-машины не потребует писать код для проверки консистентности, имплементация моего подписчика — не заставит написать весь пабсаб, «вместе с бананом вы не получите джунгли». Но я не приношу никаких новых абстракций. Буквально вообще: у вас в руках все те же самые примитивы, которые были бы в голом эрланге, просто добрый человек за вас ⅞ уже реализовал (и проверил, что ошибок нет).

          Упомянутые библиотеки JS приносят такой же вагон новых примитивов, какой был в ванильном языке. Вы просто вместо Javascript Language используете для написания кода React Language. Который может быть даже лучше, чем ванилька, но это не важно. Это не фреймворк, это новый язык, со своими проблемами, тараканами и скелетами по шкафам.


          1. titulusdesiderio
            22.06.2025 09:00

            Если ваш проект на самом деле ничего не привносит - он бесполезен


            1. cupraer Автор
              22.06.2025 09:00

              Несомненно.

              Но если он привносит столько, сколько Реакт — он вреден.


          1. mvv-rus
            22.06.2025 09:00

            Это не фреймворк, это новый язык, со своими проблемами, тараканами и скелетами по шкафам.

            Новый язык, точнее, расширение существующего, приносит даже не фреймворк, а просто билиотека - обычно библиотека всё же добавляет свой набор примитивов.


            1. cupraer Автор
              22.06.2025 09:00

              Да, это, безусловно, более корректно, но, как всегда, дело в балансе.

              Если библиотека принесла функцию $, как сделала в своё время jQuery, или новые (недостаточно вспомненные старые) веб-компоненты, как сделал Polymer — всё в порядке, это действительно просто расширение функциональности. Код понятен, стандарт уважен.

              Но Реакт (и в меньшей степени Ангуляр) принес ведь не расширение языка. Если забыть линкануть jQuery — отвалится анимация и (в худшем случае) навигация. Если забыть линкануть Реакт — страница окажется абсолютно неработоспособной.


              1. dzmitry_sidarau
                22.06.2025 09:00

                Тут всё-таки стоит разделять серверный и клиентский рендеринг. Если при клиентском рендеринге без подключения Реакта кина не будет - это абсолютно нормальное поведение (так и было задумано).

                Мне в Реакте не хватает, что называется opinionated. Подходы меняются от версии к версии. Next.js - это вообще порождение Сатаны. Возможно, идея пререндера на сервере и гидратации html на клиенте изначально и была относительно неплоха. Но после того, как начали писать в, так называемых, серверных реакт компонентах SQL-запросы в базу, я перестал следить за развитием этого кхм... фреймворка.

                На Реакте можно писать сносный код, но это надо специально стараться. Никто не ударит по рукам, если нет. Тайпскрипт немного скрашивает жизнь, однако он тоже есть суррогат и не является панацеей. Sad but true.


  1. Dhwtj
    22.06.2025 09:00

    С возвращением!

    Переведу на раст и шарп, если дело стоящее и не очень длинное. А то задачи на работе скучные


    1. cupraer Автор
      22.06.2025 09:00

      Если потребуется какая-то помощь — пишите, с радостью помогу.


  1. Arm79
    22.06.2025 09:00

    Spring state machine? ))


    1. cupraer Автор
      22.06.2025 09:00

      Нет, конечно.

      Здесь всё асинхронно, оно живет в кластере прямо из коробки, окружаюший мир может отслеживать буквально всё, что происходит внутри, а еще пользователю моей библиотеки надо будет написать примерно в 100500 раз меньше бессмысленного бойлерплейта, в сравнении со спрингом.


  1. Doyal
    22.06.2025 09:00

    Спасибо за информацию, есть над чем подумать!
    Подскажите какую вашу библиотеку можно взять как основу для изучение толковых практик на elixir-е? Уровень не начальный, полусредний)


    1. cupraer Автор
      22.06.2025 09:00

      Я польщен, если можно так выразиться, но как «основу для изучение толковых практик» лучше брать не мои библиотеки (и не библиотеки Жозе, как ни странно :)) — а то, что пишет Войтек, вот хоть Req, например.

      Саша Юрич еще пишет очень elixirish код. Вот, например.

      Из моего кода — самый практичный — наверное — в antenna.


      1. dzmitry_sidarau
        22.06.2025 09:00

        Саша Юрич ещё книгу неплохую написал, где надо GenServer прям руками реализовать. Мне очень понравилось :)