falcot/README.md

1715 lines
74 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- Improved compatibility of К началу link: See: https://github.com/othneildrew/Best-README-Template/pull/73 -->
<a id="readme-top"></a>
<!--
*** Thanks for checking out the Best-README-Template. If you have a suggestion
*** that would make this better, please fork the repo and create a pull request
*** or simply open an issue with the tag "enhancement".
*** Don't forget to give the project a star!
*** Thanks again! Now go create something AMAZING! :D
-->
<!-- PROJECT LOGO -->
<br />
<div align="center">
<!-- <a href="https://github.com/othneildrew/Best-README-Template"> -->
<img src="Logo-Futriix.png" height=100></img>
</a>
<h3 align="center">falcot && futriix</h3>
<p align="center">
<b>Futriix-встроенная распределённая субд в сервер-приложений (falcot) с поддержкой модулей на языке lua, написанная на языке Rust.</b> <br>
<br />
<br />
<!-- <a href="">Сообщить об ошибке</a>
&middot;
<!-- <a href="">Предложение новой функциональности</a> -->
</p>
</div>
## Краткая документация проекта Futriix
<!-- TABLE OF CONTENTS -->
<br>
<!-- <details> -->
<summary><b>Содержание</b></summary></br>
<ol>
<li>
<a href="#о-проекте">О проекте</a>
<li><a href="#лицензия">Лицензия</a></li>
<li><a href="#глоссарий">Глоссарий</a></li>
<li><a href="#подготовка">Подготовка</a></li>
<li><a href="#компиляция">Компиляция</a></li>
<li><a href="#тестирование">Тестирование</a></li>
<li><a href="#примеры-команд-субд">Примеры команд субд</a></li>
<li><a href="#обработка-статических-страниц">Обработка статических страниц</a></li>
<li><a href="#http-api">HTTP API</a></li>
<li><a href="#https">HTTPS</a></li>
<li><a href="#репликация">Репликация</a></li>
<li><a href="#резервное-копирование">Резервное копирование</a></li>
<li><a href="#acl">ACL</a></li>
<li><a href="#индексы">Индексы</a></li>
<li><a href="#ограничения-constraints">Ограничения Constraints</a></li>
<li><a href="#хранимые-процедуры">Хранимые процедуры</a></li>
<li><a href="#триггеры">Триггеры</a></li>
<li><a href="#транзакции">Транзакции</a></li>
<li><a href="#шардинг">Шардинг</a></li>
<li><a href="#lua-скрипты">Lua-скрипты</a></li>
<li><a href="#сферы-применения">Сферы применения</a></li>
<li><a href="#дорожная-карта">Дорожная карта</a></li>
<li><a href="#вклад">Вклад</a></li>
<li><a href="#контакты">Контакты</a></li>
</ol>
<!-- </details> -->
<!-- ABOUT THE PROJECT -->
## О проекте
Falcot это http сервер-приложений со встроенной мультимодельной NOSQL субд без блокировок (которая называется **futriix**) , написанной на языке программирования Rust. <br>
Поддерживает следующие модели хранения данных: модель временных рядов (time series), документную, ключ-значение.
Для расширения базового функционала имеет встроенный lua-интепретатор.<br>
CУБД `futriix` является резидентной, **HTAP (Hybrid Transactional/Analytical Processing) с определёнными нюансами** субд, т.е. хранящей свои данные в оперативной памяти, с их периодическим сохранением на внутренний носитель: HDD (жёсткий диск) или SSD-накопитель.
## Глоссарий
* **База Данных(БД)** -массив информация, хранящийся, например, на флешке, в файле, на кластере
* **Система Управления Базами Данных(СУБД)** - Это программа для внесения изменений в базу данных и поиска по ней
* **Мультимодельная СУБД** - Это субд, поддерживающая одновременно несколько моделей хранения данных
* **Резидентная СУБД** - субд, хранящая все свои данные в оперативной памяти, с периодическим сохранением на HDD или SSD
* **Инстанс** - запущенный экземляр базы данных
* **Узел (хост,нода)** - физический сервер
* **Слайс (от англ. "slice"-слой)** - аналог документа в любой документно-ориентированной субд
* **Репликасет** - группа актуальных данных,хранящиеся на нескольких узлах
* **Временные ряды (time series)** - это данные, последовательно собранные в регулярные промежутки времени, полученные из какого-либо устройства (цены на акции, данные температуры, объёмы продаж и.т.д.)
* **OLTP (Online Transactional Processing-Онлайн оработка транзакций)**- технология обработки транзакций в режиме реального времени. Её основная задача заключается в обеспечении быстрого и надёжного выполнения операций, которые происходят ежесекундно в бизнесе.Они обеспечивают быстрое выполнение операций вставки, обновления и удаления данных, поддерживая целостность и надежность транзакций.
* **OLAP (Online Analytical Processing- Оперативная аналитическая обработка)** — это технология, которая работает с историческими массивами информации, извлекая из них закономерности и производя анализ больших объемов данных, поддерживает многоразмерные запросы и сложные аналитические операции. Данная технология оптимизирована для выполнения сложных запросов и предоставления сводной информации для принятия управленческих решений.
* **HTAP (Hybrid Transactional and Analytical Processing- Гибридная транзакционно-аналитическая обработка)**- это технология, которая заключаются в эффективном совмещении операционных и аналитических запросов, т.е. классов OLTP и OLAP.
* **Кластер** - группа компьютеров, объединённых высокоскоростными каналами связи и представляющая с точки зрения пользователя единый аппаратный ресурс
* Команды, выполняемые с привилегиями суперпользователя (root), отмечены символом приглашения **«#»**
* Команды, выполняемые с правами обычного пользователя(user), отмечены символом приглашения **«$»**
* **FutBot** - интеллектуальный помощник в мессенджере Телеграмм, помогающий осущесвлять быстрый поиск по документации проекта
* **Сервер-приложений (англ. application-server)**-это программное обеспечение, которое обеспечивает выполнение бизнес-логики и обработку запросов от клиентов (например, веб-браузеров или мобильных приложений). Он служит платформой для развертывания и управления приложениями, имея встроенные интепретаторы и/или компиляторы популярных языков программирования (php,go,python) обеспечивая взаимодействие между пользователями, базами данных и другими системами.
* **futriix** - сервер проекта futriix
* **Интерактивная оболочка (неофициальное название "clif")**- клиент для работы со встроенной субд
* **workflow ((англ. workflow — «поток работы»)** — принцип организации рабочих процессов, в соответствии с которым повторяющиеся задачи представлены как последовательность стандартных шагов.)
* **CA (англ. Certificate Authority)-Центры Сертификации, организации, выдающие доверенне криптографические сертификаты**
* **Резидентная субд**- Это субд, хранящая данные в оперативной памяти
<p align="right">(<a href="#readme-top">К началу</a>)</p>
##
**Почему именно HTAP? Анализ характеристик falcot:**
OLTP (Online Transactional Processing- Онлайн оработка транзакций) черты, присущие falcot:
1. **Поддержка транзакций - есть BEGIN/COMMIT/ROLLBACK**
2. **CRUD операции - полноценные Create, Read, Update, Delete**
3. **Wait-free архитектура - оптимизирована для быстрых коротких операций**
4. **Поддержка индексов - ускоряет поиск и точки доступа**
5. **ACID-подобное поведение - на уровне отдельных операций**
<br>
<br>
OLAP (Online Analytical Processing- Оперативная аналитическая обработка) черты, присущие falcot:
1. **Документо-ориентированная модель - удобна для аналитических запросов**
2. **Поддержка сложных запросов - через Lua-скрипты**
3. **Мастер-мастер репликация - позволяет распределять аналитические нагрузки**
4. **Возможность агрегаций - через пользовательские процедуры**
<br>
<br>
HTAP (Hybrid Transactional Analytical Processing- Гибридная обработка транзакций) черты, присущие falcot:
1. **Единая платформа - обрабатывает и транзакции, и аналитику**
2. **Wait-free архитектура - подходит для mixed workload**
3. **Lua-скрипты - мост между операционными и аналитическими задачами**
4. **Реализация индексов - поддерживает оба типа нагрузок**
<br>
<br>
Если посмотреть на архитектурные особенности falcot, то можно заметить следующее:
1. **Wait-free доступ подходит для concurrent transactional workload**
2. **Document-oriented модель удобна для analytical queries**
3. **Master-master репликация позволяет разделять нагрузки**
4. **Функциональные возможности обоих классов OLTP и OLAP (См. пример ниже)**
<br>
> [!CAUTION]
> **А поскольку falcot НЕ поддерживает:**
> * Полноценные распределённые транзакции
> * Сложные ограничения (constraints)
> * Хранилища типа "Семейство столбцов" (Columnar Storage) для аналитики
> * Сложные агрегации
> * Язык запросов SQL
> * ACID-транзакции
<br>
<br>
> [!NOTE]
>**Falcot** - это lightweight HTAP система занимающая нишу прагматичного HTAP - достаточно мощная для большинства реальных задач, но без > избыточной сложности enterprise-решений, **с акцентом на:**
> * Простота использования через Lua-интерфейс
> * Гибридная модель для mixed workloads
> * Wait-free performance для concurrent access
> * Умеренную масштабируемость (достаточную для большинства задач)
<p align="right">(<a href="#readme-top">К началу</a>)</p>
<!-- LICENSE -->
## Лицензия
Проект распространяется под 3-пунктной лицензией BSD. Подробнсти смотрите в файле `LICENSE.txt`.
Эта лицензия является одной из самых демократичных лицензий свободного программного обеспечения. Она позволяет использовать, изменять и распространять код в коммерческих целях без каких-либо ограничений, за исключением сохранения уведомления об авторских правах.
В том числе, вы можете использовать falcot и futriix в своих коммерческих продуктах, приложениях или сервисах, не беспокоясь о каких-либо юридических ограничениях, связанных с лицензией.
Все дополнительное программное обеспечение (включая модули на языке lua, утилиту тестирования) предоставляются "как есть", без гарантий и обязательств со стороны разработчиков. Разработчики не несут ответственности за прямой или косвенный ущерб, вызванный использованием открытого кода falcot и futriix или технических решений, использующих этот код.
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Подготовка
**Для операционных систем семейства 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
```
<br>
<br>
> [!IMPORTANT]
> Для дальнейшей корректной работы приложения создаем файл `.cargo/config.toml` для подавления некоторых предупреждений, следующего содержания:
<br>
<br>
```sh
#### .cargo/config.toml
[build]
rustflags = ["-A", "dead_code", "-A", "unused_variables", "-A", "unused_imports"]
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Компиляция
1. Копируем репозиторий
```sh
$ git clone https://source.futriix.ru/gvsafronov/falcot
```
2. Переходим в каталог с исходном кодом src
```sh
$ cd falcot/
```
3. Компилируем Futriix с помощью пакетного менеджера `Cargo`
```sh
$ cargo build
```
4. Запускаем серверв futriix'а с помощью команды `./falcot`
```sh
$ ./falcot
````
```sh
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>
```
> [!WARNING]
> **Futriix может быть скомпилирован для следующих операционных систем: `Linux`, `OSX`, `Open Indiana`, `FreeBSD`, но сборка для этих операционных систем не проводилась!!!**
5.** Компиляция и запуск тестов. Для запуска тестов запускаем команды:**
```sh
$ cargo test --test integration # запуск только интеграционных тестов
$ cargo test --bench benches # запуск только бенчмарков
```
**Компиляция и запуск тестов c помощью утилиты тестирования с выводом логов**
```sh
cargo test --test integration_tests -- --nocapture
```
**Только компиляция утилиты тестирования без запуска**
Приведённая команда ниже только скомпилирует тесты, но не запускает их.
```sh
$ cargo test --test integration_tests --no-run
```
**Компиляция утилиты тестирования с конкретным тестом**
```sh
#### Компиляция и запуск конкретного теста
$ cargo test --test integration_tests regression_test
#### С выводом логов
$ cargo test --test integration_tests regression_test -- --nocapture
```
**Компиляция утилиты тестирования для debug-режима**
```sh
#### Обычная компиляция (debug по умолчанию)
$ cargo test --test integration_tests
#### Компиляция в release-режиме (оптимизированная)
$ cargo test --test integration_tests --release
```
**Проверка компиляции без запуска тестов с помощью утилиты тестирования**
```sh
#### Проверить, что код компилируется без ошибок
$ cargo check --test integration_tests
```
**Компиляция утилиты тестирования с дополнительными флагами**
```sh
# С подробным выводом компиляции
$ cargo test --test integration_tests -v
# С цветным выводом
$ cargo test --test integration_tests --color=always
```
> [!TIP]
> После компиляции тестовый бинарный файл создается в следующей директории:
> `target/debug/deps/integration_tests-<hash>`
> Например, так: `target/debug/deps/integration_tests-abc123def456`
**Пример полного workflow по компиляции**
```sh
# 1. Проверка компиляции
$ cargo check --test integration_tests
# 2. Компиляция и запуск всех тестов
$ cargo test --test integration_tests -- --nocapture
# 3. Компиляция и запуск только нагрузочного теста
$ cargo test --test integration_tests load_test -- --nocapture
# 4. Компиляция в release-режиме
$ cargo test --test integration_tests --release -- --nocapture
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Тестирование
В состав проекта, входит утилита `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]
> * Создается изолированная тестовая среда - каждый тест работает с чистой копией базы данных
> * Тесты выполняются параллельно (где это безопасно)
> * Каждый тест независим - результаты одного теста не влияют на другие
> * Выводятся подробные логи о ходе выполнения тестов
<br>
<br>
> [!TIP]
> **Пример вывода**
> * Running 5 tests:
> * regression_test - passed in 0.2s
> * unit_test_indexes - passed in 0.1s
> * smoke_test - passed in 0.05s
> * load_test - passed in 1.8s (1000 documents)
> * stress_test - passed in 12.3s (2500 operations)
> * All 5 tests passed!
<br>
<br>
> [!TIP]
> **Как интерпретировать результаты**
> * Все тесты passed - система стабильна, можно выпускать в production
> * Regression test failed - сломана базовая функциональность
> * Load test failed - проблемы с производительностью
> * Stress test failed - система не устойчива под нагрузкой
> * Unit test failed - проблемы в конкретном модуле
<br>
<br>
> [!TIP]
> **Важные моменты**
> * Тесты компилируются автоматически при первом запуске `cargo test`
> * Изменения в коде требуют перекомпиляции при следующем запуске
> * Бинарник тестов временный и пересоздается при изменении кода
> * Можно запускать напрямую скомпилированный бинарник (но это сложнее)
Таким образом, команда `cargo test --test integration_tests` одновременно компилирует и запускает все тесты из указанного файла.
<p align="right">(<a href="#readme-top">К началу</a>)</p>
<!-- USAGE EXAMPLES -->
## Примеры команд субд
```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":"Москва"},...]
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Обработка статических страниц
Запуск статических веб-страниц, из сервера приложений 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)
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Репликация
Сервер-приложенй 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()
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
**Пример конфигурационных файлов репликации для узлов кластера**
**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
]])
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## 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"
}'
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## 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: Запуск с ACL для разработки**
```sh
[acl]
enabled = true
allowed_ips = ["127.0.0.1", "::1", "192.168.1.0/24"]
denied_ips = []
[tls]
enabled = true
cert_path = "certs/cert.pem"
key_path = "certs/key.pem"
[server]
http_port = 8082
https_port = 8443
http2_enabled = true
```
**Пример 3: Продвинутая ACL конфигурация**
```sh
[acl]
enabled = true
# Разрешить только внутренние адреса и конкретные внешние
allowed_ips = [
"127.0.0.1",
"::1",
"192.168.1.0/24",
"10.0.0.0/8",
"203.0.113.5" # Конкретный внешний IP
]
# Заблокировать проблемные IP
denied_ips = [
"192.168.1.100",
"10.0.0.25",
"198.51.100.0/24" # Целая подсеть спамеров
]
```
**Пример 4: Генерация сертификатов и запуск**
```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 для безопасного соединения.
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## 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 = []
```
**Формат IP-адресов:**
* 127.0.0.1 - конкретный IPv4
* ::1 - IPv6 localhost
* 192.168.1.0/24 - подсеть CIDR
* 10.0.0.0/8 - большая подсеть
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Индексы
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`, в то время как вторичные индексы создаются вручную для оптимизации произвольных запросов и могут быть как уникальными, так и неуникальными.
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Ограничения Constraints
**Ограничения (Constraints)** — это правила, применяемые к данным в таблице в реляционных субд (или её аналоге в не реляцционных субд) для поддержания их корректности и надёжности. Они играют важную роль в обеспечении целостности данных и соответствия бизнес-правилам.
При создании таблицы или измененинии её структуры, можно определить различные ограничения,предотвращающие добавление, изменение или удаление данных, нарушающих установленные правила. Это помогает избежать нежелательных ситуаций, например таких как:
* **Наличие нескольких пользователей с одинаковыми идентификаторами**
* **Ссылки на несуществующие записи в других таблицах**
* **Отсутствие данных обязательных для заполнения**
* **Ввод некорректных значений (например, отрицательного возраста или будущей даты рождения)**
Ограничения реализованы на уровне встроенной субд **futriix**, ниже приведы примеры использования Ограничений:
**Пример уникального ограничения поля **
```sh
#### Гарантируем уникальность email в коллекции users
falcot:~> constraint add users unique_email unique email
#### Где:
#### - users: коллекция
#### - unique_email: название ограничения
#### - unique: тип ограничения
#### - email: поле
```
**Пример ограничениея диапазона**
```sh
#### Ограничиваем возраст пользователей (18-120 лет)
falcot:~> constraint add users age_range range age "{\"min\":18,\"max\":120}"
#### Где range - тип ограничения, можно передавать JSON значение
```
**Пример Ограничения по шаблону**
```sh
#### Проверяем формат email
falcot:~> constraint add users email_pattern pattern email "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
```
**Пример Внешний ключ (foreign key)**
```sh
#### Связываем заказы с пользователями
falcot:~> constraint add orders user_foreign_key foreign user_id "users/id"
```
**Просмотр ограничений**
```sh
#### Список всех constraints для коллекции
falcot:~> constraint list users
#### Пример вывода:
#### Constraints for collection 'users':
#### - unique_email (field: email, type: unique)
#### - age_range (field: age, type: range(18-120))
#### - email_pattern (field: email, type: pattern)
```
**Удаление ограничения**
```sh
#### Удаляем ограничение
falcot:~> constraint remove users unique_email
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Хранимые процедуры
**Хранимая процедура в 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 ]]
```
```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
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Триггеры
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 для очистки связанных данных
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## 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
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Транзакции
Работа с транзакциями, во встроенной субд:
```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
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Шардинг
Встроенная в 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
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
## Сферы применения
Идеальными сферами применения проекта falcot, являются следующие:
1. **Микросервисы с потребностью в оперативной аналитике**
2. **Работающая в режиме реального времени панель мониторинга - для администрирования бекенда**
3. **Приложения, тербующие среднего масштабирования со смешанными рабочими нагузками (англ. workload)**
4. **Прототипирование перед выбором специализированного решения**
<br>
**Пример функциональных возможностей falcot классов OLTP и OLAP для микросервисов с потребностью в оперативной аналитике**
<br>
```sh
-- OLTP-операция: быстрая транзакция
falcot_db.update("users", "user123", '{"balance": 100}')
-- OLAP-операция: аналитический запрос
local analytics = falcot_db.query("transactions", '{"date": {"$gt": "2024-01-01"}}')
```
<p align="right">(<a href="#readme-top">К началу</a>)</p>
<!-- ROADMAP -->
## Дорожная карта
- [v] Реализовать поддержку хранимых процедур
- [v] Реализовать поддержку триггеров (обратных вызовов)
- [v] Реализовать поддержку многопоточности
- [v] Реализовать неблокирующие чтение/запись
- [v] Реализовать мульти-мастер асинхронную репликацию через файл конфигурации
- [v] Реализовать логирование
- [v] Реализовать поддержку синхронной мастер-мастер репликации
- [v] Реализовать поддержку протоколов HTTPS и HTTP2
- [v] Реализовать поддержку первичных индексов
- [v] Реализовать поддержку протокола MessagePack
- [v] Реализовать поддержку транзакций
- [v] Реализовать поддержку первичных и вторичных индексов
- [v] Добавить механизм сторонних модулей на языке lua, расширяющих базовый функционал сервера
- [v] Реализовать проверку запуска сервера при запуске клиента (если сервер НЕ запущен клиент не запускается)
- [v] Реализовать поддержку HTTP-restfull API
- [v] Исправить ошибки записи журнала логов (в журнал лога кроме текущего времени добавить текущий год)
- [v] Реализовать утилиту тестирования сервера на количество запросов на чтение/запись
- [v] Переписать асинхронную мастер-мастер репликацию на синхронную мастер-мастер репликацию
- [ ] Реализовать журнал WAL
- [ ] Реализовать графический веб-интерфейс для упраления кластером
- [v] Реализовать автоматический шардинг с консистентным хэшированием
- [ ] Реализовать поддержку алгоритма Raft
- [ ] Реализовать поддержку SQL
- [ ] Реализовать поддержку ACID-транзакций
- [ ] Интегрировать интеллектуального помощник FutBot на официальный сайт
- [ ] Реализовать полноценного интеллектуального помощника FutBot, задачами которого будут быстрый поиск ответов на вопросы, возникающие при эксплуатации субд Futrix.
См. [Открытые проблемы](https://source.futriix.ru/gvsafronov/futriixw/issues) полный список предлагаемых функций (и известных проблем).
<p align="right">(<a href="#readme-top">К началу</a>)</p>
<!-- CONTRIBUTING -->
## Вклад
Вклады — это то, что делает сообщество открытого исходного кода таким замечательным местом для обучения, вдохновения и творчества. Любой ваш вклад **очень ценится**.
Если у вас есть предложение, которое могло бы улучшить ситуацию, создайте форк репозитория и создайте запрос на включение. Также можно просто открыть задачу с тегом «улучшение».
<!-- CONTRIBUTING -->
1. Форкните проект
2. Создайте свою ветку функций (`git checkout -b Feature/AmazingFeature`)
3. Зафиксируйте свои изменения (git commit -m 'Add some AmazingFeature'`)
4. Отправьте в ветку (`git push main Feature/AmazingFeature`)
5. Откройте запрос на включение
<!-- CONTACT -->
## Контакты
Григорий Сафронов - [E-mail](gvsafronov@yandex.ru)
Ссылка на Интеллектуальный помощник - [FutBot](https://t.me/Futriix_bot)
<p align="right">(<a href="#readme-top">К началу</a>)</p>