Отказываемся от рутины Backend разработки
Опишу личную боль в написании backend:
Выгрузка данных в удобной для отображения форме для frontend, если у frontend'a
что-то добавилось вам так же придется менять выдачу ему этих данных.Под каждую страницу или функционал плодить Endpoint.
Для выборки данных нужно создавать/редактировать разграничения по правам, какая роль, какие данные может получать.
Какие решения могут помочь с этими проблемами?
Одним из возможных вариантов является переход на GraphQL. Это позволит решить три вышеуказанных проблемы. Однако вместе с этим может появиться новый нюанс - общеизвестная проблема N+1, которую часто связывают с использованием GraphQL.
Компания Hasura написала движок для GraphQL который решает данную проблему. И так же предоставляет GUI интерфейс для настройки прав, то есть какая роль может получать какие данные. И больше нет необходимости описывать таблицы кодом, можно просто создать таблицы в GUI интерфейсе или в базе данных и Hasura сразу сделает для них GraphQL оболочку.
![Настройка прав в Hasura Настройка прав в Hasura](https://habrastorage.org/getpro/habr/upload_files/971/e8d/8f5/971e8d8f50f9cd8e7156778ceac040d0.png)
Все бы хорошо, я бы и остановился бы на Hasura, но к сожалению она не предоставляет функционал для создания бизнес логики, а точнее она предлагает просто рядом с hasura развернуть нужный вам сервер, настроить на нем graphql и настроить hasura action который будет слать запрос в ваш сервер. Решение не плохое, но можно лучше.
Вот мы и пришли к Deep. У него полностью заимствуется вся технология по graphql из hasura, точнее он использует как движок саму hasura. Но так же реализовали систему handlers. Как она работает ? В базе данных есть товары. Вы вешаете handler именно на создание/изменение/удаление данных, можно их сравнить с триггерами в базе данных. К Handler вы привязываете Provider и Программный код.
Provider - Это Docker контейнер с экосистемой определенного языка, к примеру JavaScript или Python.
Программный код - Это функция которая написана на языке подключенного провайдера.
Провайдеры можно устанавливать в один клик из установщика Deep. И так же добавлять свои провайдеры на своем языке программирования.
Таким образом мы достигаем объединение любых языков программирования в одной программной среде, за малое количество времени.
Про провайдеры подробнее расскажу ниже.
От реляционных баз данных к связям
![Слева реляционная база данныхСправа база данных на связях Слева реляционная база данныхСправа база данных на связях](https://habrastorage.org/getpro/habr/upload_files/259/5ca/0d2/2595ca0d2489627fd1c0ada41bdd7a7b.png)
Справа база данных на связях
Если вы знакомы с графовыми базами данных они могут показаться похожими на связи в Deep. Но в отличии от графов в Deep нет различия между вершинами и ребрами, всё это представляется связями.
![Пример визуального отображения связей Пример визуального отображения связей](https://habrastorage.org/getpro/habr/upload_files/a9d/11c/b11/a9d11cb11f6a23f8d58a8aa5f4465ee5.png)
Такое решение было принято из-за трудности менять и адаптировать реляционную базу данных, так как с ростом проекта изменять что-то в существующей структуре все сложнее.
Если эта тема заинтересовала, то прошу прочтите эту статью и эту статью
Динамическая настройка прав
Deep также поработал и над настройкой прав, теперь права накладываются не на всю таблицу или колонку, а на выбранные пользователем связи.
Для начала все права теперь так же записываются в базу данных, что означает что их так же можно менять при помощи graphql на frontend и каждый может делать для них собственную визуализацию.
![Пример создания правил Пример создания правил](https://habrastorage.org/getpro/habr/upload_files/8b6/dfe/3ac/8b6dfe3ac1e576df5e9bc76e862c4ac0.png)
Как же работают 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](https://habrastorage.org/getpro/habr/upload_files/23a/2d3/18b/23a2d318b4ca5e50533ffd5a70dffc4d.png)
Теперь нужно выбрать связь на которую будем реагировать, я для этого создал новую связь type (1236) и связь syncTextFile (1240) в котором будет код программы.
![Пример новых связей Пример новых связей](https://habrastorage.org/getpro/habr/upload_files/c31/cbc/e8e/c31cbce8e0b56d810604ebbb20e29e43.png)
Открывает 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](https://habrastorage.org/getpro/habr/upload_files/483/a86/fc8/483a86fc87e997389de210ff78034ab0.png)
После настройки все продублируется в виде данных и их можно в любой момент менять при помощи кода. То есть Handler может настраивать другие Handler или даже самого себя и менять код самого себя.
![Пример настроек в виде связей Пример настроек в виде связей](https://habrastorage.org/getpro/habr/upload_files/fc9/6e0/62d/fc96e062de2433c44a64375b003038a0.png)
Если мы создадим связь с id = 1236, то есть экземпляр связи. То у нас выполниться Handler и в данных мы так же увидим результат выполнения.
![Результат выполнения Handler Результат выполнения Handler](https://habrastorage.org/getpro/habr/upload_files/51b/2dd/4af/51b2dd4af2f1999dcd752d59812286ac.png)
В Docker мы увидим что был поднят js-docker в котором уже изолированно выполняется код от операционной системы. То есть мне не пришлось устанавливать библиотеки и настраивать сервер, в docker уже это все собрано и я могу этим пользоваться.
![](https://habrastorage.org/getpro/habr/upload_files/388/2f2/27d/3882f227d66707566d2606c20d40111e.png)
Итоги
На данный момент я рассказал еще далеко не все про Deep и все его возможности.
Если вам стало интересно и хотите узнать больше, обязательно посетите discord сервер.
Сайт, где можно найти другие статьи.
И github, если интересно покопаться в самом коде.