diff --git a/README.md b/README.md index d0274d1..7983a34 100644 --- a/README.md +++ b/README.md @@ -1086,6 +1086,7 @@ Created database 'company_restore' ## Lua-плагины Для расширения функциональных возможностей субд **без изменения её исходного кода**, в futriix была реализована система расширения функциональности через Lua-скрипты с изолированным окружением. Плагины имеют доступ к БД, транзакциям, триггерам, могут логировать события и взаимодействовать через событийную шину, а также они доступны в веб-интерфейсе. +А кроме того плагины могут использоваться для написания движков для субд, без изменения её исходного кода, на языке lua. ```sh # Просмотр информации о системе плагинов @@ -1288,8 +1289,140 @@ curl -X POST http://localhost:8080/api/plugin/call \ -d '{"plugin":"validation","function":"validate_collection","args":["employees"]}' ``` +**Плагины как инструмент написания движков для futriix** + +Для написания нового движка (LSM-дерева, key-value или time-series) необходимо два файла: файл с названием самого движка с расширением **.lua** +и файл **Манифест-плагина** с расширением **.json** + +**Манифест плагина-движка** — это JSON-файл, который сопровождает Lua-скрипт плагина и предоставляет системе метаданные о плагине. Манифест необходим для корректной загрузки, регистрации и управления плагинами, реализующими кастомные движки хранения данных. +Расположение и именование + +Манифест должен располагаться в той же директории, что и Lua-скрипт плагина (по умолчанию `/futriix/plugins`), и иметь идентичное имя файла с расширением **.json**. Например: + +```sh +plugins/ +├── timescale_engine.lua # Lua-скрипт движка +└── timescale_engine.json # Манифест движка +``` + +**Структура манифеста** + +```sh +{ + "name": "timescale_engine", + "version": "1.0.0", + "author": "Example Corp", + "description": "Time-series storage engine with automatic partitioning", + "api_version": "1.0", + "engine_type": "timescale", + "min_go_version": "1.21", + "dependencies": [ + { + "name": "base_engine", + "version": "2.0.0", + "min_version": "2.0.0", + "max_version": "3.0.0", + "optional": false + } + ], + "entry_point": "create_engine", + "created_at": 1704067200000, + "updated_at": 1704153600000 +} + +``` + +**Поля манифеста** + +| Поле | Тип | Обязательное | Описание | +|------|-----|--------------|----------| +| `name` | string | ✅ | Уникальное имя плагина. Должно совпадать с именем Lua-файла (без расширения) | +| `version` | string | ✅ | Версия плагина в формате Semantic Versioning (X.Y.Z) | +| `author` | string | ❌ | Автор или организация-разработчик плагина | +| `description` | string | ❌ | Краткое описание функциональности плагина | +| `api_version` | string | ✅ | Версия API СУБД, с которой совместим плагин | +| `engine_type` | string | ✅ | **Ключевое поле**. Определяет, что плагин является движком хранения. Значение используется как идентификатор движка при создании коллекций | +| `min_go_version` | string | ❌ | Минимальная версия Go, необходимая для работы плагина | +| `dependencies` | array | ❌ | Список зависимостей от других плагинов | +| `entry_point` | string | ❌ | Имя Lua-функции-фабрики, создающей экземпляр движка. По умолчанию: `create_engine` | +| `created_at` | int64 | ❌ | Время создания манифеста (Unix timestamp в миллисекундах) | +| `updated_at` | int64 | ❌ | Время последнего обновления манифеста | + + + +**Структура зависимости** + +Каждая зависимость в массиве `dependencies` имеет следующую структуру: + + +| Поле | Тип | Обязательное | Описание | +|------|-----|--------------|----------| +| `name` | string | ✅ | Имя зависимого плагина | +| `version` | string | ❌ | Точная версия зависимого плагина (если указана, требует точного соответствия) | +| `min_version` | string | ❌ | Минимальная допустимая версия (включительно) | +| `max_version` | string | ❌ | Максимальная допустимая версия (исключительно) | +| `optional` | boolean | ❌ | Является ли зависимость опциональной. По умолчанию: `false` | + + + +**Процесс загрузки плагина с манифестом** + +1. Обнаружение: Система сканирует директорию плагинов и находит Lua-файлы +2. Чтение манифеста: При наличии JSON-файла с тем же именем система загружает и парсит его. + + Валидация: + + * Проверяется наличие обязательных полей (name, version, api_version) + * Проверяется, что engine_type не пуст (для движков) + * Проверяется совместимость версий зависимостей + +3. Регистрация движка: Если engine_type указан, система автоматически регистрирует плагин в EngineRegistry под этим именем +4. Загрузка Lua-скрипта: Выполняется Lua-скрипт, который должен экспортировать фабричную функцию (по умолчанию create_engine) +5. Вызов фабрики: При создании экземпляра движка для конкретной коллекции вызывается фабричная функция с передачей конфигурации + +**Пример использования** + +**Создание манифеста для Time-Series движка:** + +```sh +{ + "name": "ts_engine", + "version": "1.2.0", + "author": "Futriix Team", + "description": "High-performance time-series storage engine with automatic downsampling", + "api_version": "1.0", + "engine_type": "timeseries", + "dependencies": [ + { + "name": "compression_plugin", + "min_version": "1.0.0", + "optional": false + } + ], + "entry_point": "new_timeseries_engine", + "created_at": 1704067200000, + "updated_at": 1704153600000 +} +``` + +**Рекомендации по версионированию** + +* Используйте Semantic Versioning (MAJOR.MINOR.PATCH) +* Увеличивайте MAJOR-версию при несовместимых изменениях API движка +* Увеличивайте MINOR-версию при добавлении новой функциональности +* Увеличивайте PATCH-версию при исправлении ошибок + + +**Обработка ошибок** + +При отсутствии манифеста система пытается загрузить плагин в "упрощённом режиме", используя значения по умолчанию. Однако для плагинов-движков манифест является обязательным, так как поле engine_type необходимо для корректной регистрации. + +Ошибки при разборе манифеста логируются, но не препятствуют загрузке Lua-скрипта (если это не плагин-движок). При критических ошибках (отсутствие engine_type у движка) загрузка прерывается с соответствующим сообщением. + +
(К началу)
+ ## Контроль доступа В futriix реализована многоуровневая система контроля доступа, основанная на **ACL (Access Contol Lists -Списки контроля доступа**) с аутентификацией по сессиям. В ней поддерживаются следующие роли (read, write, delete, admin) с гранулярным контролем на уровне базы данных и коллекции.