diff --git a/README.md b/README.md
deleted file mode 100644
index 59d836c..0000000
--- a/README.md
+++ /dev/null
@@ -1,1774 +0,0 @@
-
-
-
-
-
-
-
-
- Futriix-встроенная распределённая субд в сервер-приложений (falcot) с поддержкой модулей на языке lua, написанная на языке Rust
-
-
-
-
(К началу)
- -## -**Почему именно HTAP? Анализ характеристик falcot:** - -OLTP (Online Transactional Processing- Онлайн оработка транзакций) черты, присущие falcot: - -1. **Поддержка транзакций - есть BEGIN/COMMIT/ROLLBACK** -2. **CRUD операции - полноценные Create, Read, Update, Delete** -3. **Wait-free архитектура - оптимизирована для быстрых коротких операций** -4. **Поддержка индексов - ускоряет поиск и точки доступа** -5. **ACID-подобное поведение - на уровне отдельных операций** -(К началу)
- - -## Лицензия - -Проект распространяется под 3-пунктной лицензией BSD. Подробнсти смотрите в файле `LICENSE.txt`. -Эта лицензия является одной из самых демократичных лицензий свободного программного обеспечения. Она позволяет использовать, изменять и распространять код в коммерческих целях без каких-либо ограничений, за исключением сохранения уведомления об авторских правах. - -В том числе, вы можете использовать falcot и futriix в своих коммерческих продуктах, приложениях или сервисах, не беспокоясь о каких-либо юридических ограничениях, связанных с лицензией. - -Все дополнительное программное обеспечение (включая модули на языке lua, утилиту тестирования) предоставляются "как есть", без гарантий и обязательств со стороны разработчиков. Разработчики не несут ответственности за прямой или косвенный ущерб, вызванный использованием открытого кода falcot и futriix или технических решений, использующих этот код. - -(К началу)
- - -## Подготовка - -**Для операционных систем семейства Debian** выполните следующие шаги: -* Устанавливаем язык программирования Rust - - ```sh - # apt update - # apt upgrade - # curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -**Для операционных систем семейства Red Hat (Fedora, Aurora)** выполните следующие шаги: -* Устанавливаем язык программирования Rust - - ```sh - # dnf update - # curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -**Для операционной системы Alpine** выполните следующие шаги: -* Устанавливаем язык программирования Rust - - ```sh - # apk update - # curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -(К началу)
- -## Компиляция - -1. Копируем репозиторий - ```sh - $ git clone https://source.futriix.ru/gvsafronov/falcot - ``` -2. Переходим в каталог с исходном кодом src - ```sh - $ cd falcot/ - ``` -3. Компилируем Futriix с помощью пакетного менеджера `Cargo` - ```sh - $ cargo build - ``` - > [!WARNING] -> **Futriix может быть скомпилирован для следующих операционных систем: `Linux`, `OSX`, `Open Indiana`, `FreeBSD`, но сборка для этих операционных систем не проводилась!!!** -(К началу)
- -## Тестирование - -В состав проекта, входит утилита `integration_tests.rs` **integration_tests.rs** - это интеграционный тестовый набор, который при запуске создает и выполняет сразу несколько различных типов тестов. С её помощью можно запустить как сразу все тесты, так и определённый тест. -Вышеописанная утилита - является мощным инструментом для комплексного тестирования всей системы Falcot, позволяющий быстро выявлять проблемы на разных уровнях приложения и обеспечивать высокое качество кода. - -**Falcot поддерживает пять типов тестов:** - - * **Регрессионный тест - проверяет базовую функциональность** - * **Unit-тест - тестирует конкретный модуль (индексы)** - * **Smoke-тест - проверяет запуск системы** - * **Нагрузочный тест - проверяет производительность** - * **Стресс-тест - проверяет устойчивость при высокой нагрузке** - -**Запуск всех тестов** - -Для запуска всех тестов сразу используйте команду в терминале: - -```sh -$ cargo test --test integration_tests -- --nocapture -``` - -**Запуск конкретного теста** - -```sh -#### Только регрессионный тест -$ cargo test --test integration_tests regression_test -- --nocapture - -#### Только нагрузочный тест -$ cargo test --test integration_tests load_test -- --nocapture - -``` - -**Запуск теста с фильтром** - -```sh -#### Все тесты, содержащие "test" в названии -$ cargo test --test integration_tests test -- --nocapture -``` - -**Что происходит при запуске** -> [!TIP] -> * Создается изолированная тестовая среда - каждый тест работает с чистой копией базы данных -> * Тесты выполняются параллельно (где это безопасно) -> * Каждый тест независим - результаты одного теста не влияют на другие -> * Выводятся подробные логи о ходе выполнения тестов - -(К началу)
- - - -## Примеры команд субд -```sh -./falcot config.toml - -В интерактивном режиме: - -Loading configuration from: config.toml -Database initialized with system collections - -Falcot Database Server -Version: 1.0.0 -Features: Wait-Free Architecture, Master-Master Replication, Lua Scripting, HTTP/HTTPS Support -HTTP server started on 127.0.0.1:8082 -Starting Lua interpreter... -Lua interpreter ready. Type 'inbox.start' to enter database mode. -Type 'exit' to quit. -lua> falcot_log("Добро пожаловать в Falcot!") -LUA: Добро пожаловать в Falcot! - -lua> inbox.start -Entering database mode. Type CRUD commands or 'inbox.stop' to exit. - -falcot:~> create users '{"name": "Иван", "age": 25, "city": "Москва"}' -Document created with ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890 - -falcot:~> create users '{"name": "Мария", "age": 30, "city": "Санкт-Петербург"}' -Document created with ID: b2c3d4e5-f6g7-8901-bcde-f23456789012 - -falcot:~> list users -Documents in collection: [{"_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","name":"Иван","age":25,"city":"Москва"},{"_id":"b2c3d4e5-f6g7-8901-bcde-f23456789012","name":"Мария","age":30,"city":"Санкт-Петербург"}] - -falcot:~> begin trans1 -Transaction started successfully - -falcot:~> create products '{"name": "Ноутбук", "price": 50000, "category": "электроника"}' -Document created with ID: c3d4e5f6-g7h8-9012-cdef-345678901234 - -falcot:~> create products '{"name": "Телефон", "price": 25000, "category": "электроника"}' -Document created with ID: d4e5f6g7-h8i9-0123-defg-456789012345 - -falcot:~> commit trans1 -Transaction committed successfully - -falcot:~> inbox.stop -Exiting database mode. Back to Lua interpreter. - -lua> procedure create count_users ' -function count_users() - local result = falcot_db.query("users", "{}") - local count = 0 - for _ in string.gmatch(result, "\\\"name\\\":") do - count = count + 1 - end - return "Всего пользователей: " .. count -end -return count_users -' -Stored procedure created successfully - -lua> procedure call count_users -Procedure result: Всего пользователей: 2 - -lua> exit -Shutting down Falcot server... -``` - -**Параллельно запускаем в другом терминале:** - -```sh -#### Проверка HTTP API -curl http://127.0.0.1:8082/api/ -#### {"status": "ok", "message": "Falcot Server is running"} - -#### Получение списка пользователей -curl http://127.0.0.1:8082/api/query?collection=users -#### [{"_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","name":"Иван","age":25,"city":"Москва"},...] -``` -(К началу)
- - -## Обработка статических страниц - -Запуск статических веб-страниц, из сервера приложений falcot - -Falcot имеет встроенную поддержку статических файлов: -Настройка статических файлов: - -```sh - Создайте каталог `static` в корневой директории приложения: - - $ mkdir static - ``` - Разместите файлы в каталоге static: - ```sh - falcot/ -├── static/ -│ ├── index.html -│ ├── style.css -│ ├── script.js -│ ├── images/ -│ │ └── logo.png -│ └── api-docs.html -└── config.toml -``` - -После чего HTTP сервер автоматически будет обслуживать эти файлы: -```sh -Примеры доступа: - -# Главная страница -http://127.0.0.1:8082/ - -# Конкретный файл -http://127.0.0.1:8082/index.html -http://127.0.0.1:8082/style.css -http://127.0.0.1:8082/images/logo.png - -# API документация -http://127.0.0.1:8082/api-docs.html -``` - -**Falcot поддерживает следующие типы файлов:** - - * HTML (.html) - * CSS (.css) - * JavaScript (.js) - * Изображения (.png, .jpg, .jpeg) - * Аудио (.mp3) - * Видео (.mp4) - * JSON (.json) - * Текстовые файлы (.txt) - * Файлы в формате **pdf** (.pdf) - * Markdown (.md) - - - -(К началу)
- - -## Репликация - -Сервер-приложенй falcot поддерживает синхронную мастер-мастер репликацию. -За управление репликацией отвечает секция `[replication]` в конфигурационном файле `config.toml` - -```sh -# config.toml -[server] -host = "127.0.0.1" -port = 8081 -http_port = 8082 - -[replication] -enabled = true -master_nodes = [ - "127.0.0.1:8081", - "127.0.0.1:8083", - "127.0.0.1:8085" -] -sync_interval = 2000 # 2 секунды -``` - -**Запуск нескольких экземпляров сервера** - -```sh -# Терминал 1 - основной сервер на порту 8081 -$ cargo run -- config1.toml - -# Терминал 2 - реплика на порту 8083 -$ cargo run -- config2.toml - -# Терминал 3 - реплика на порту 8085 -$ cargo run -- config3.toml -``` - -**Тестирование репликации** - -```sh --- replication_test.lua -falcot_log("Testing replication...") - --- Добавляем данные на основном сервере -local doc1 = falcot_db.create("test_data", '{"type": "main", "value": "from_server_1"}') -local doc2 = falcot_db.create("test_data", '{"type": "main", "value": "from_server_1_again"}') - -falcot_log("Documents created on main server: " .. doc1 .. ", " .. doc2) - --- Ждем синхронизации -falcot_log("Waiting for replication...") -os.execute("sleep 3") -- Ждем дольше интервала синхронизации - --- Проверяем на репликах (это нужно делать с разных клиентов) -falcot_log("Checking replicated data...") -local all_data = falcot_db.query("test_data", "{}") -falcot_log("All data: " .. all_data) -``` - -**Мониторинг репликации** - -```sh -# В Lua shell можно проверять статус репликации -lua> inbox.start - -# Проверяем статус репликации -falcot:~> print(falcot.engine.replication.status()) - -# Смотрим список узлов -falcot:~> print("Nodes: " .. table.concat(falcot.engine.replication.get_nodes(), ", ")) - -# Запускаем принудительную синхронизацию -falcot:~> falcot.engine.replication.sync() -``` - -(К началу)
- -**Пример конфигурационных файлов репликации для узлов кластера** - -**config1.toml (основной сервер):** - -```sh -[server] -host = "127.0.0.1" -port = 8081 -http_port = 8082 - -[replication] -enabled = true -master_nodes = ["127.0.0.1:8083", "127.0.0.1:8085"] -sync_interval = 1000 - -[lua] -scripts_dir = "lua_scripts" -auto_execute = ["init.lua"] -``` - -**config2.toml (Реплика 1):** - -```sh -[server] -host = "127.0.0.1" -port = 8083 -http_port = 8084 - -[replication] -enabled = true -master_nodes = ["127.0.0.1:8081", "127.0.0.1:8085"] -sync_interval = 1000 -``` - -**config3.toml (Реплика 2):** - -```sh -[server] -host = "127.0.0.1" -port = 8085 -http_port = 8086 - -[replication] -enabled = true -master_nodes = ["127.0.0.1:8081", "127.0.0.1:8084"] -sync_interval = 1000 -``` - -**config4.toml (Реплика 3):** - -```sh -[server] -host = "127.0.0.1" -port = 8086 -http_port = 8087 - -[replication] -enabled = true -master_nodes = ["127.0.0.1:8081", "127.0.0.1:8083"]4sync_interval = 1000 -``` - -**Мониторинг и управление** - -```sh -#### Проверка статуса репликации через HTTP API -curl http://127.0.0.1:8082/api/replication/status - -#### Принудительная синхронизация -curl -X POST http://127.0.0.1:8082/api/replication/sync - -#### Просмотр статистики -curl http://127.0.0.1:8082/api/stats -``` - -**Пример lua-скрипта по обработки ошибок репликации** - -```sh --- error_handling.lua -falcot_log("Testing replication error handling") - --- Пытаемся добавить данные при недоступности реплик -local success, result = pcall(function() - return falcot_db.create("test_collection", '{"data": "test"}') -end) - -if success then - falcot_log("Data created successfully: " .. result) - - -- Проверяем статус репликации - local rep_status = falcot.engine.replication.status() - if rep_status ~= "active" then - falcot_log("Warning: Replication is not active. Status: " .. rep_status) - end - -else - falcot_error("Failed to create data: " .. result) - - -- Пытаемся работать в offline режиме - falcot_log("Trying offline operation...") - local offline_data = falcot_db.query("test_collection", "{}") - falcot_log("Offline data available: " .. #offline_data) -end -``` - -## Резервное копирование - -Для встроенной в сервер-приложений falcot, субд **futriix** предусмотрен механизм восстановления из резервных копий (бекапов) -Бекапы можно создавать c помощью языка lua. - -**Создание бекапа через lua** - -```sh --- Создаем бэкап -local result = falcot.engine.backup.start() -print(result) -- "Backup created successfully: /falcot/backups/backup_20231201_143022.json" - --- Или через прямое обращение к функции -local result = falcot_db.backup_start() -print(result) - --- Создаем несколько тестовых документов перед бэкапом -falcot_db.create('products', '{"name": "Laptop", "price": 999.99, "category": "electronics"}') -falcot_db.create('products', '{"name": "Phone", "price": 499.99, "category": "electronics"}') -falcot_db.create('users', '{"name": "Alice", "email": "alice@example.com", "role": "admin"}') - --- Создаем бэкап с данными -local backup_result = falcot.engine.backup.start() -``` - -**Восстановление из бекапа** - -```sh --- Восстанавливаем из конкретного бэкапа -local restore_result = falcot.engine.backup.restore('/falcot/backups/backup_20231201_143022.json') -print(restore_result) -- "Backup restored successfully" - --- Или через прямое обращение -local restore_result = falcot_db.backup_restore('/falcot/backups/backup_20231201_143022.json') - --- Проверяем, что данные восстановились -local users = falcot_db.read('users', 'user123') -local products = falcot_db.query('products', '{}') -print('Users:', users) -print('Products count:', #products) - -``` -**Использование бекапов в интерактивной оболочке** - -```sh -#### Создаем бэкап -backup start -# Output: Backup created successfully: /falcot/backups/backup_20231201_143022.json - -#### Восстанавливаем из бэкапа -backup restore /falcot/backups/backup_20231201_143022.json -#### Output: Backup restored successfully - -#### Смотрим список доступных бэкапов -!ls /falcot/backups/ -#### Output: backup_20231201_143022.json backup_20231202_020001.json - -#### Создаем тестовые данные -create products '{"name": "Test Product", "price": 100}' -create users '{"name": "Test User", "email": "test@example.com"}' - -#### Создаем бэкап и сразу проверяем восстановление -backup start -delete products test_product_id -delete users test_user_id -backup restore /falcot/backups/backup_20231201_143022.json -read products test_product_id -#### Данные восстановяться -``` - -**Интеграция с триггерами для создания автоматических бекапов** - -```sh --- Триггер для создания бэкапа при критических изменениях -falcot_db.add_trigger('auto_backup_on_change', 'after_update', 'config', [[ - local config = json.decode(document) - if config.critical_setting then - -- Создаем бэкап при изменении критических настроек - local backup_result = falcot_db.backup_start() - falcot_log('Auto-backup created due to config change: ' .. backup_result) - end -]]) - --- Триггер для бэкапа перед массовыми операциями -falcot_db.add_trigger('backup_before_bulk_operation', 'before_delete', 'users', [[ - -- Проверяем, это одиночное удаление или массовая операция - if bulk_operation then - local backup_result = falcot_db.backup_start() - falcot_log('Backup created before bulk operation: ' .. backup_result) - end -]]) - -``` - -(К началу)
- - -## HTTP API - -Использование curl для работы с HTTP API: - -```sh -#### Проверка статуса сервера -curl http://127.0.0.1:8082/ - -##### Создание документа -curl -X POST http://127.0.0.1:8082/api/create \ - -H "Content-Type: application/json" \ - -d '{ - "collection": "users", - "document": {"name": "John Doe", "email": "john@example.com", "age": 30} - }' - -#### Чтение документа -curl "http://127.0.0.1:8082/api/read?collection=users&id=document_id_here" - -#### Запрос документов -curl -X POST http://127.0.0.1:8082/api/query \ - -H "Content-Type: application/json" \ - -d '{ - "collection": "users", - "filter": {"age": {"$gt": 25}} - }' - -#### Обновление документа -curl -X PUT http://127.0.0.1:8082/api/update \ - -H "Content-Type: application/json" \ - -d '{ - "collection": "users", - "id": "document_id_here", - "document": {"name": "John Updated", "age": 31} - }' - -#### Удаление документа -curl -X DELETE http://127.0.0.1:8082/api/delete \ - -H "Content-Type: application/json" \ - -d '{ - "collection": "users", - "id": "document_id_here" - }' - ``` - -(К началу)
- - -## Аутентификация - -Для повышения безопасности в сервере-приложений falcot используется `Аутентификация`. -За параметры авторизации отвечает секция `[security]` в конфигурационном файле `./falcot/config.toml` - -```sh -[security] -require_authentication = false -jwt_secret = "your-secret-key-here" -password_hashing_rounds = 12 -``` -(К началу)
- -## HTTPS - -Сервер-приложенй falcot поддерживает протоколы https и http2. -Утилита `generate_certs` - Генерация сертификатов - -Назначение: Генерация самоподписанных SSL/TLS сертификатов для HTTPS. -Запуск утилиты для генерации тестовых сертификатов: `cargo run --bin generate_certs` - -По итогу работы утитилиты создаётся следующее дерево каталогов: - -```sh -certs/ -├── cert.pem # Публичный сертификат -└── key.pem # Приватный ключ -``` - -Процесс генерации сертификата: - - **1.Создается пара ключей (публичный и приватный)** - **2.Генерируется самоподписанный сертификат** - **3.Сертификат подписывается приватным ключом** - **4.Файлы сохраняются в папку `certs` ** - - -**Примеры конфигураций** - - -**Пример 1: Базовая конфигурация** - -```sh -[tls] -enabled = true -cert_path = "certs/cert.pem" -key_path = "certs/key.pem" - -[server] -https_port = 8443 -``` - -**Пример 2: Генерация сертификатов и запуск** - -```sh -# Генерируем сертификаты -cargo run --bin generate_certs - -# Запускаем сервер -cargo run - -# Тестируем подключение -curl -k https://localhost:8443/api/status -curl http://localhost:8082/api/status -``` - -> [!TIP] -> Безопасность: -> * Самоподписанные сертификаты подходят для разработки и внутреннего использования -> * Для продакшена рекомендуется использовать сертификаты от Let's Encrypt или других CA -> * ACL обеспечивает дополнительный уровень безопасности -> * HTTPS шифрует трафик между клиентом и сервером -> * ACL защищает от нежелательных подключений, а `generate_certs` позволяет быстро настроить HTTPS для безопасного соединения. - - -(К началу)
- - -## ACL - -**ACL** - это система управления доступом, которая позволяет разрешать или запрещать подключения к серверу на основе IP-адресов. -Как работает ACL в Falcot: - -Принцип работы: - - **1.Проверка запрещенных IP - если IP в списке denied_ips, доступ блокируется** - **2.Проверка разрешенных IP - если список allowed_ips не пустой, проверяется наличие IP в нем** - **3.Если ACL отключен - все подключения разрешены** - - -**Примеры использования в конфигурации:** - -```sh -#### Разрешить только локальные подключения -[acl] -enabled = true -allowed_ips = ["127.0.0.1", "::1"] -denied_ips = [] - -#### Заблокировать конкретные проблемные IP -[acl] -enabled = true -allowed_ips = [] # Пустой список = разрешены все -denied_ips = ["192.168.1.100", "10.0.0.25"] - -#### Разрешить только внутреннюю сеть -[acl] -enabled = true -allowed_ips = ["192.168.1.0/24", "10.0.0.0/8"] -denied_ips = [] -``` -(К началу)
- - -## Индексы - -Falcot поддерживает два стандартных типа индекса: первичные индексы и вторичные индексы - -**Различия между первичным и вторичным индексом** - -1. **Первичный индекс (Primary Index)** - -**Особенности:** - - 1. **Обязательно уникальный - не допускает дублирования значений** - 2. **Автоматически создается для поля id в каждой коллекции и не требует ручного создания** - 3. **Используется для быстрого поиска документов по их идентификатору** - 4. **Гарантирует целостность данных - предотвращает создание документов с одинаковым `ID`** - -**Пример создания** - -```sh --- Поиск по ID (использует первичный индекс) -local document = falcot_db.read("users", "550e8400-e29b-41d4-a716-446655440000") -``` - -2. **Вторичный индекс (Secondary Index)** - -**Особенности:** - - 1. **Может быть как уникальным, так и неуникальным** - 2. **Создается вручную для любых полей документа** - 3. **Используется для оптимизации запросов по не-`ID полям`** - 4. **Поддерживает различные типы данных (строки, числа, булевы значения)** - - -**Пример создания** - -```sh --- Неуникальный индекс по полю 'email' -falcot_db.create_index("users", "email_idx", "email", false) - --- Уникальный индекс по полю 'username' -falcot_db.create_index("users", "username_idx", "username", true) -``` - - -**Создание и использование индексов через Lua shell** - -```sh -#### Запускаем сервер -$ cargo run - -#### Входим в режим inbox -$ lua> inbox.start - -#### Создаем коллекцию пользователей -falcot:~> create users '{"name": "Alice", "age": 30, "email": "alice@example.com"}' -falcot:~> create users '{"name": "Bob", "age": 25, "email": "bob@example.com"}' -falcot:~> create users '{"name": "Charlie", "age": 35, "email": "charlie@example.com"}' - -#### Создаем вторичный индекс по полю "name" -falcot:~> index create users name_index name - -#### Создаем уникальный индекс по полю "email" -falcot:~> index create users email_index email unique - -#### Ищем по индексу name -falcot:~> index query users name_index "Alice" - -#### Ищем по индексу email -falcot:~> index query users email_index "bob@example.com" - -#### Пытаемся создать дубликат email (должна быть ошибка) -falcot:~> create users '{"name": "Another Bob", "age": 28, "email": "bob@example.com"}' -``` -**Создание и использование индексов через Lua скрипты:** - -```sh --- create_indexes.lua -falcot_log("Creating indexes...") - --- Создаем индексы -falcot_db.create_index("users", "name_index", "name", false) -falcot_db.create_index("users", "email_index", "email", true) - --- Добавляем данные -falcot_db.create("users", '{"name": "Alice", "age": 30, "email": "alice@example.com"}') -falcot_db.create("users", '{"name": "Bob", "age": 25, "email": "bob@example.com"}') - --- Поиск по индексу -local result = falcot_db.query_by_index("users", "name_index", "Alice") -falcot_log("Search result: " .. result) - --- Проверка уникальности (должна вызвать ошибку) -local status, err = pcall(function() - falcot_db.create("users", '{"name": "Another", "age": 28, "email": "bob@example.com"}') -end) -if not status then - falcot_error("Unique constraint violation: " .. err) -end -``` - -**Производительность индексов** - -**Первичный индекс:** - - * ** Максимальная скорость поиска по ID** - * **Всегда в памяти (кешируется)** - * **Минимальные накладные расходы** - -**Вторичный индекс:** - - * **Скорость зависит от размера индексируемых данных** - * **Может требовать дополнительной памяти** - * **Оптимизирует конкретные типы запросов** - -**Рекомендации по использованию индексов** - -Используйте первичный индекс для: - - * **Быстрого доступа к документам по их ID** - * **Операций обновления/удаления конкретных документов** - * **Гарантии уникальности идентификаторов** - -Используйте вторичный индекс для: - - * **Поиска документов по любым другим полям** - * **Оптимизации часто выполняемых запросов** - * **Обеспечения уникальности бизнес-ключей (email, username и т.д.)** - * **Ускорения сортировки и фильтрации** - - -#### Обработка ошибок индексов - -**Первичный индекс (автоматическая проверка) на языке lua: ** - -```sh --- Попытка создать документ с существующим ID вызовет ошибку -local status, err = pcall(function() - falcot_db.create("users", '{"id": "existing_id", "name": "Duplicate"}') -end) -``` - -**Вторичный индекс (ручная проверка уникальности) на языке lua: :** - -```sh --- При unique=true попытка дублирования вызовет ошибку -local status, err = pcall(function() - falcot_db.create("users", '{"email": "existing@example.com", "name": "Duplicate"}') - falcot_db.create("users", '{"email": "existing@example.com", "name": "Duplicate2"}') -end) -if not status then - falcot_error("Unique constraint violation: " .. err) -end -``` - -Таким образом, первичный индекс в falcot - это автоматически создаваемый уникальный индекс для поля `id`, в то время как вторичные индексы создаются вручную для оптимизации произвольных запросов и могут быть как уникальными, так и неуникальными. - -(К началу)
- - -## Constraints (Ограничения) - -**Ограничения (Constraints)** — это правила, применяемые к данным в таблице в реляционных субд (или её аналоге в не реляцционных субд) для поддержания их корректности и надёжности. Они играют важную роль в обеспечении целостности данных и соответствия бизнес-правилам. - -При создании таблицы или измененинии её структуры, можно определить различные ограничения,предотвращающие добавление, изменение или удаление данных, нарушающих установленные правила. Это помогает избежать нежелательных ситуаций, например таких как: - - * **Наличие нескольких пользователей с одинаковыми идентификаторами** - * **Ссылки на несуществующие записи в других таблицах** - * **Отсутствие данных обязательных для заполнения** - * **Ввод некорректных значений (например, отрицательного возраста или будущей даты рождения)** - - Ограничения реализованы на уровне встроенной субд **futriix**, ниже приведы примеры использования Ограничений: -(К началу)
- - -## Хранимые процедуры - -**Хранимая процедура в falcot** – это откомпилированная во внутреннее представление сервера субд подпрограмма, хранящаяся в базе данных. Хранимые процедуры пишутся на специальном языке хранимых процедур и триггеров, в котором имеются операторы присваивания, ветвлений и циклов, и в которых можно использовать операторы SQL, такие как INSERT, DELETE, UPDATE и SELECT. - - **Создание хранимой процедуры** - - ```sh - -- Создание хранимой процедуры для расчета статистики - local procedure_code = [[ function calculate_stats(collection_name) - local documents = falcot_db.query(collection_name, "{}") - local count = 0 - local total_age = 0 - - for doc in string.gmatch(documents, '([^,]+)') do - count = count + 1 - -- Здесь можно парсить JSON и считать статистику - end - - return "Документов: " .. count .. ", Средний возраст: " .. (total_age / count) - end - return calculate_stats ]] - version = "1.0.0" - edition = "2024" - ``` - - ```sh --- Сохраняем процедуру -falcot_db.create_procedure("calculate_stats", procedure_code) -``` - -**Работа с хранимыми процедурами в lua интерпретаторе:** - -```sh --- Создание процедуры -procedure create calculate_stats ' -function calculate_stats(collection_name) - local result = falcot_db.query(collection_name, "{}") - local count = 0 - for _ in string.gmatch(result, "\\\"_id\\\":") do - count = count + 1 - end - return "Количество документов в " .. collection_name .. ": " .. count -end -return calculate_stats -' - --- Вызов процедуры -procedure call calculate_stats -``` - -**Создание хранимых процедур во одноимённой встроенной субд** - -```sh -# Создание процедуры -procedure create user_stats ' -function calculate_user_stats() - local users = falcot_db.query("users", "{}") - local count = 0 - for _ in string.gmatch(users, "\\\"name\\\":") do - count = count + 1 - end - return "Всего пользователей: " .. count -end -return calculate_user_stats -' -``` - -```sh -#### Вызов процедуры -procedure call user_stats -``` - -(К началу)
- - -## Триггеры - -Falcot помимо хранимых процедур поддерживает триггеры (обратные вызовы) -Триггеры можно создавать тремя способами: через lua-shell, через интерактивную оболочку, через хранимые процедуры встроенной субд - -**Создание триггеров через lua-shell** - -```sh - --- Создаем триггер, который логирует создание документов в коллекции 'users' -falcot_db.add_trigger('log_user_creation', 'after_create', 'users', [[ - falcot_log('New user created with data: ' .. document) - -- Можно добавить дополнительную логику, например: - -- - Отправка уведомления - -- - Валидация данных - -- - Обновление связанных документов -]]) - --- Триггер для проверки данных перед обновлением -falcot_db.add_trigger('validate_user_update', 'before_update', 'users', [[ - local user_data = json.decode(document) - if not user_data.email or not user_data.email:match('^[^@]+@[^@]+%.[^@]+$') then - error('Invalid email format') - end - if user_data.age and user_data.age < 0 then - error('Age cannot be negative') - end -]]) - --- Триггер для очистки связанных данных при удалении -falcot_db.add_trigger('cleanup_user_data', 'before_delete', 'users', [[ - -- Удаляем связанные записи из других коллекций - falcot_db.delete('user_sessions', id) - falcot_db.delete('user_preferences', id) - falcot_log('Cleaned up user data for ID: ' .. id) -]]) -``` - -**Создание триггеров через интерактивную оболочку** - -```sh -##### Переходим в режим inbox -inbox.start - -##### Создаем триггер для логирования -trigger add log_creation after_create orders "falcot_log('New order created: ' .. document)" - -#### Триггер для автоматического обновления статистики -trigger add update_stats after_create orders [[ - -- Увеличиваем счетчик заказов - local stats = falcot_db.read('statistics', 'order_count') or '0' - local count = tonumber(stats) + 1 - falcot_db.update('statistics', 'order_count', tostring(count)) -]] - -#### Триггер для проверки цены перед созданием -trigger add validate_price before_create products [[ - local product = json.decode(document) - if product.price <= 0 then - error('Price must be positive') - end -]] - -``` - -**Пример создание триггеров через хранимые процедуры** - -```sh - --- Создаем документ - сработает триггер after_create -falcot_db.create('users', '{"name": "John", "email": "john@example.com", "age": 25}') --- В логах появится: "LUA: New user created with data: {"name": "John", "email": "john@example.com", "age": 25}" - --- Попытка создать пользователя с невалидным email -falcot_db.create('users', '{"name": "Invalid", "email": "invalid", "age": 30}') --- Получим ошибку: "Invalid email format" - --- Обновляем пользователя -falcot_db.update('users', 'user123', '{"name": "John Updated", "email": "john.new@example.com", "age": 26}') --- Сработает триггер before_update для валидации - --- Удаляем пользователя -falcot_db.delete('users', 'user123') --- Сработает триггер before_delete для очистки связанных данных - -``` - -(К началу)
- -## Lua-скрипты - -> [!CAUTION] -> **Поддержка работы lua в настоящий момент эксперементальная и может вызвать аварийное завершение сервера!!!** - -В Falcot существует несколько способов запуска Lua скриптов - - -**Способ 1: Непосредственный ввод кода в lua-интерпретатор** -```sh -lua> falcot_log("Привет, мир!") -LUA: Привет, мир! - -lua> local x = 10 + 5 -lua> falcot_log("Результат: " .. x) -LUA: Результат: 15 -``` - -**Способ 2: Многострочный ввод (через конкатенацию)** -```sh -lua> local script = [[ ->> for i = 1, 3 do ->> falcot_log("Итерация: " .. i) ->> end ->> ]] -lua> falcot.engine.execute_script(script) -LUA: Итерация: 1 -LUA: Итерация: 2 -LUA: Итерация: 3 -``` - -**Способ 3: Запуск из файла** - - 1. **`lua_scripts` - это каталог (директория), где хранятся Lua-скрипты для выполнения сервером Falcot** - 2. **При запуске сервера автоматически выполняются скрипты из `auto_execute` списка, находящиеся в этой директории** - 3. **Сервер автоматически создает этот каталог при первом запуске, если он не существует** - -**Как это работает:** - - 1. **Сервер при запуске создает каталог lua_scripts (если его нет)** - 2. **В этот каталог можно помещать Lua-скрипты** - 3. **Скрипты из списка auto_execute выполняются автоматически при старте сервера** - 4. **Другие скрипты можно выполнять вручную через Lua-интерпретатор командой falcot.engine.lua.execute("имя_скрипта.lua")** - - -```sh - -Пример структуры каталогов falcot: - -lua_scripts/ -├── init.lua (автоматически выполняется при старте) -├── utils.lua (вспомогательные функции) -├── procedures/ (подкаталог для хранимых процедур) -│ ├── user_management.lua -│ └── data_processing.lua -└── config/ (подкаталог для конфигурационных скриптов) - └── system_config.lua -``` - -### Примеры lua-скриптов -```sh --- Простой Lua скрипт для демонстрации -falcot_log("Запуск примера Lua скрипта") - --- Создание документа -falcot_db.create("users", '{"name": "John", "age": 30, "email": "john@example.com"}') - --- Чтение документа -local result = falcot_db.read("users", "some-document-id") -falcot_log("Результат чтения: " .. result) -``` - -```sh --- Математические операции -local x = 10 -local y = 20 -falcot_log("Сумма: " .. (x + y)) - --- Циклы и условия -for i = 1, 5 do - if i % 2 == 0 then - falcot_log("Четное число: " .. i) - else - falcot_log("Нечетное число: " .. i) - end -end - -``` -(К началу)
- -## Транзакции - -Работа с транзакциями, во встроенной субд: - -```sh -# Начало транзакции -begin transaction_123 - -# Несколько операций в транзакции -create users '{"name": "Alice", "age": 25}' -create users '{"name": "Bob", "age": 30}' -create users '{"name": "Charlie", "age": 35}' - -# Фиксация транзакции -commit transaction_123 - -# Или откат при ошибке -begin transaction_456 -create users '{"name": "David", "age": 40}' -rollback transaction_456 -``` -(К началу)
- - -## Шардинг - -Встроенная в falcot субд **futriix** поддерживает горинзонтальный шардинг, т.е. горизонтальное масштабирование. -По умолчанию шардинг производится `по алгоритму Hash-based с консистентным хэшированием`. Шифрование производится согласно алгоритму `SipHasher13`. -Но также поддерживается возможность управлять шардингом вручную. Ниже приведены команды по управлению шардингом: - -**Пример добавления узла** - -```sh -#### Добавляем новый узел шардинга -falcot:~> shard add node1 127.0.0.1:8084 1024 - -#### Где: -#### - node1: идентификатор узла -#### - 127.0.0.1:8084: адрес узла -#### - 1024: емкость в MB -``` - -**Пример удаления узла** - -```sh -#### Удаляем узел из кластера -falcot:~> shard remove node1 -``` - -**Пример миграции между шардами узла** - -```sh -#### Мигрируем данные коллекции между узлами -falcot:~> shard migrate users node1 node2 user_id - -#### Где: -#### - users: коллекция для миграции -#### - node1: исходный узел -#### - node2: целевой узел -#### - user_id: ключ шардирования -``` - -**Пример просмотра статуса кластера** - -```sh -#### Показывает статус всего кластера -falcot:~> shard status - -#### Пример вывода: -#### === Cluster Status === -#### Total capacity: 2048 GB -#### Total used: 512 MB -#### Rebalance needed: false -#### -#### Node node1: -#### Address: 127.0.0.1:8081 -#### Capacity: 1024 MB -#### Used: 256 MB -#### Usage: 25.0% -#### Collections: users, products -``` - -**Пример ручной ребалансировки кластера** - -```sh -#### Запускает автоматическую ребалансировку -falcot:~> cluster rebalance -``` - -**Пример создания шардированной системы пользователей** - -```sh -#### Добавляем узлы -falcot:~> shard add node1 127.0.0.1:8081 1024 -falcot:~> shard add node2 127.0.0.1:8082 1024 - -#### Создаем constraints для пользователей -falcot:~> constraint add users unique_email unique email -falcot:~> constraint add users valid_age range age "{\"min\":13,\"max\":150}" -falcot:~> constraint add users valid_username pattern username "^[a-zA-Z0-9_]{3,20}$" - -#### Распределяем пользователей по шардам -shard migrate users node1 node2 user_id -``` - -**Мониторинг шардинга** - -```sh -#### Проверяем статус -falcot:~> shard status - -#### Если нужно перебалансировать -falcot:~> cluster rebalance - -#### Проверяем constraints -falcot:~> constraint list users -``` - -(К началу)
- - -## Сферы применения - -Идеальными сферами применения проекта falcot, являются следующие: - -1. **Микросервисы с потребностью в оперативной аналитике** -2. **Работающая в режиме реального времени панель мониторинга - для администрирования бекенда** -3. **Приложения, тербующие среднего масштабирования со смешанными рабочими нагузками (англ. workload)** -4. **Прототипирование перед выбором специализированного решения** - -(К началу)
- - -## Дорожная карта - -- [x] Реализовать поддержку хранимых процедур -- [x] Реализовать поддержку триггеров (обратных вызовов) -- [x] Реализовать поддержку многопоточности -- [x] Реализовать неблокирующие чтение/запись -- [x] Реализовать мульти-мастер асинхронную репликацию через файл конфигурации -- [x] Реализовать логирование -- [x] Реализовать поддержку синхронной мастер-мастер репликации -- [x] Реализовать поддержку протоколов HTTPS и HTTP2 -- [x] Реализовать поддержку первичных индексов -- [x] Реализовать поддержку протокола MessagePack -- [x] Реализовать поддержку транзакций -- [x] Реализовать поддержку первичных и вторичных индексов -- [x] Добавить механизм сторонних модулей на языке lua, расширяющих базовый функционал сервера -- [x] Реализовать проверку запуска сервера при запуске клиента (если сервер НЕ запущен клиент не запускается) -- [x] Реализовать поддержку HTTP-restfull API -- [x] Исправить ошибки записи журнала логов (в журнал лога кроме текущего времени добавить текущий год) -- [x] Реализовать утилиту тестирования сервера на количество запросов на чтение/запись -- [x] Переписать асинхронную мастер-мастер репликацию на синхронную мастер-мастер репликацию -- [ ] Реализовать журнал WAL -- [ ] Реализовать графический веб-интерфейс для упраления кластером -- [x] Реализовать автоматический шардинг с консистентным хэшированием -- [ ] Реализовать поддержку алгоритма Raft -- [ ] Реализовать поддержку SQL -- [ ] Реализовать поддержку ACID-транзакций -- [ ] Интегрировать интеллектуального помощник FutBot на официальный сайт -- [ ] Реализовать полноценного интеллектуального помощника FutBot, задачами которого будут быстрый поиск ответов на вопросы, возникающие при эксплуатации субд Futrix. - -См. [Открытые проблемы](https://source.futriix.ru/gvsafronov/futriixw/issues) полный список предлагаемых функций (и известных проблем). - -(К началу)
- - - - - -## Контакты - -Григорий Сафронов - [E-mail](gvsafronov@yandex.ru) - -Ссылка на Интеллектуальный помощник - [FutBot](https://t.me/Futriix_bot) - -(К началу)