Отказываемся от рутины Backend разработки

Опишу личную боль в написании backend:

  1. Выгрузка данных в удобной для отображения форме для frontend, если у frontend'a
    что-то добавилось вам так же придется менять выдачу ему этих данных.

  2. Под каждую страницу или функционал плодить Endpoint.

  3. Для выборки данных нужно создавать/редактировать разграничения по правам, какая роль, какие данные может получать.

Какие решения могут помочь с этими проблемами?

Одним из возможных вариантов является переход на GraphQL. Это позволит решить три вышеуказанных проблемы. Однако вместе с этим может появиться новый нюанс - общеизвестная проблема N+1, которую часто связывают с использованием GraphQL.

Компания Hasura написала движок для GraphQL который решает данную проблему. И так же предоставляет GUI интерфейс для настройки прав, то есть какая роль может получать какие данные. И больше нет необходимости описывать таблицы кодом, можно просто создать таблицы в GUI интерфейсе или в базе данных и Hasura сразу сделает для них GraphQL оболочку.

Настройка прав в Hasura
Настройка прав в Hasura

Все бы хорошо, я бы и остановился бы на Hasura, но к сожалению она не предоставляет функционал для создания бизнес логики, а точнее она предлагает просто рядом с hasura развернуть нужный вам сервер, настроить на нем graphql и настроить hasura action который будет слать запрос в ваш сервер. Решение не плохое, но можно лучше.

Вот мы и пришли к Deep. У него полностью заимствуется вся технология по graphql из hasura, точнее он использует как движок саму hasura. Но так же реализовали систему handlers. Как она работает ? В базе данных есть товары. Вы вешаете handler именно на создание/изменение/удаление данных, можно их сравнить с триггерами в базе данных. К Handler вы привязываете Provider и Программный код.

Provider - Это Docker контейнер с экосистемой определенного языка, к примеру JavaScript или Python.
Программный код - Это функция которая написана на языке подключенного провайдера.

Провайдеры можно устанавливать в один клик из установщика Deep. И так же добавлять свои провайдеры на своем языке программирования.
Таким образом мы достигаем объединение любых языков программирования в одной программной среде, за малое количество времени.
Про провайдеры подробнее расскажу ниже.

От реляционных баз данных к связям

Слева реляционная база данныхСправа база данных на связях
Слева реляционная база данных
Справа база данных на связях

Если вы знакомы с графовыми базами данных они могут показаться похожими на связи в Deep. Но в отличии от графов в Deep нет различия между вершинами и ребрами, всё это представляется связями.

Пример визуального отображения связей
Пример визуального отображения связей

Такое решение было принято из-за трудности менять и адаптировать реляционную базу данных, так как с ростом проекта изменять что-то в существующей структуре все сложнее.
Если эта тема заинтересовала, то прошу прочтите эту статью и эту статью

Динамическая настройка прав

Deep также поработал и над настройкой прав, теперь права накладываются не на всю таблицу или колонку, а на выбранные пользователем связи.

Для начала все права теперь так же записываются в базу данных, что означает что их так же можно менять при помощи graphql на frontend и каждый может делать для них собственную визуализацию.

Пример создания правил
Пример создания правил

Как же работают Rules ?
У них есть три связи RuleSubject, RuleObject, RuleAction
RuleSubject - Кому мы даем права
RuleObject - На ком выполняется операция
RuleAction - Тип операции

В примере мы рассматриваем операцию авторизации от пользователя (id = 373) в пользователя (id = 380), с названием admin.
Но при указании SelectorInclude, на пользователе 373 мы так же указали дерево joinTree, это область на которую будут так же распространяться права, кто может авторизоваться в связь admin. И связь joinTree указывает что могут авторизоваться те кто прикреплен при помощи join к 373 пользователю. Соответственно это пользователи 375 и 1048, они так же могут авторизоваться в пользователя admin.

Мы рассмотрели пример с авторизацией, но эта схема похожа и на других правилах. Вы так же можете создавать свои операции, к примеру AllowMove, AllowBuy и т.д. и указывать кто и над какими связями может выполнять эту операцию.

Создание Handlers

Возвращаемся к теме Handlers и как они создаются и работают.
Как установить handler с поддержкой вашего языка ? Сама оболочка с языком называется Provider и вам нужно в Packager искать Provider. Ниже пример я просто ввел название "Python" и мне первым выдался пакет "@konard/python-docker-isolation-provider" Нужно нажать "Install" и у нас появится поддержка Python.

Установка Python provider
Установка Python provider

Теперь нужно выбрать связь на которую будем реагировать, я для этого создал новую связь type (1236) и связь syncTextFile (1240) в котором будет код программы.

Пример новых связей
Пример новых связей

Открывает syncTextFile в Editor и видим два окна, слева окно для написания кода, справа для настройки handlers.
Слева вы можете писать код на любом языке, я же привел пример простой функции из JavaScript.
Справа у нас на выбор несколько Providers, один из который dockerSupportJs, так же есть наш установленный dockerSupportsPython. В провайдере мы можем создать Handler и в Handler выбрать тип реакции, такие как Insert, Update, Delete, Shedule, Port, Route
Insert - Реакция на создание связи
Update - Реакция на обновление связи
Delete - Реакция на удаление связи
Shedule - Код будет запускаться по таймеру
Port - Поднимает Docker образ на определенном порту
Route - Поднимает Web Server на определенном порту и указанием endpoint. При заходе на него будет выполняться код.

Создание Handler с HandleInsert
Создание Handler с HandleInsert

После настройки все продублируется в виде данных и их можно в любой момент менять при помощи кода. То есть Handler может настраивать другие Handler или даже самого себя и менять код самого себя.

Пример настроек в виде связей
Пример настроек в виде связей

Если мы создадим связь с id = 1236, то есть экземпляр связи. То у нас выполниться Handler и в данных мы так же увидим результат выполнения.

Результат выполнения Handler
Результат выполнения Handler

В Docker мы увидим что был поднят js-docker в котором уже изолированно выполняется код от операционной системы. То есть мне не пришлось устанавливать библиотеки и настраивать сервер, в docker уже это все собрано и я могу этим пользоваться.

Итоги

На данный момент я рассказал еще далеко не все про Deep и все его возможности.
Если вам стало интересно и хотите узнать больше, обязательно посетите discord сервер.

Сайт, где можно найти другие статьи.
И github, если интересно покопаться в самом коде.

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


  1. Konard
    27.08.2023 18:55
    +1

    Deep поддерживает написание обработчиков ещё и на PHP, Rust и Kotlin на данный момент.


  1. mikko_kukkanen
    27.08.2023 18:55

    На discord канале выкатывается "приглашение недействительно".


    1. Konard
      27.08.2023 18:55

      https://discord.gg/deep-foundation - эта ссылка не работает или другая?


  1. mikko_kukkanen
    27.08.2023 18:55

    Если дальше перейти, тоже ругается.


    1. Konard
      27.08.2023 18:55

      А если в приложении Discord открыть, как это будет выглядеть? У тебя есть аккаунт в Discord зарегистрированный?


      1. mikko_kukkanen
        27.08.2023 18:55


      1. mikko_kukkanen
        27.08.2023 18:55

        Аккаунта нет, конечно. Просто хотел покопаться.


        1. Konard
          27.08.2023 18:55

          Вероятно потребуется завести аккаунт, чтобы получить доступ на сервер Дискорда. В данный момент сервер не является публичным и доступен только по приглашению, из-за того что сервер пока не выполнил все условия Discord чтобы стать публичным с их точки зрения.