Сервер поисковой машины для проекта Omoide.
Принимает запросы по HTTP, ищет записи по заданным тегам. Позволяет применять логические операции с тегами, например "кошки + собаки". Мне не удалось найти простого и удобного способа искать по тегам в базе данных, поэтому я написал свой поиск на базе питоновского словарика.
TODO - Описать как запускать контейнер.
Используемые переменные окружения:
- OMOIDE_INDEX_DATABASE_URI - ссылка для подключения к базе данных.
- OMOIDE_INDEX_RELOAD_ON_START - включает и выключает автоматическую сборку индекса при первом запуске.
Сам индекс хранится в памяти в единственном экземпляре, поэтому сервис не может масштабироваться горизонтально. Текущая реализация подразумевает только вертикальное масштабирование, сопряжённое с покупкой более производительного железа. В основном, опасения вызывает расход памяти и риск сожрать её всю. Но предполагается, что проект не разрастётся настолько, что будет невозможно за адекватные деньги подобрать железо для его запуска.
По сути, вся история с этим индексом и сервером - моё желание проверить, насколько много данных можно засунуть в питоновский словарик, а также то, сможет ли он заменить базу данных. Сама идея изначально казалось глупой, но быстродействие и простота реализации говорят об обратном.
Просто позволяет понять, что сервис вообще живой.
Пример запроса:
curl http://127.0.0.1:9000/
Пример ответа:
{
"result": "omoide-index 2021.12.20"
}
Предназначено для вызова человеком для проверки состояния сервиса. В первую очередь - проверки расхода памяти.
Пример запроса:
curl http://127.0.0.1:9000/status
В ответ вернётся JSON объект с набором параметров.
Имя поля | Пример значения | Смысл поля |
---|---|---|
version | 2021.12.20 | Текущая версия сервера |
server_restart | 2021-10-05 20:15:21+00:00 | Время последней перезагрузки сервера |
server_uptime | 15s | Сколько времени прошло с последней перезагрузки сервера |
server_memory | 99.6 MiB | Расход памяти на весь процесс сервера |
index_status | active | Текущее состояние сервера (init, active, reloading, fail) |
index_reload | 2021-10-05 20:15:24+00:00 | Время последней перезагрузки индекса |
index_uptime | 11s | Сколько времени прошло с последней перезагрузки индекса |
index_duration | 3.74 | Сколько секунд было потрачено на перезагрузку индекса |
index_traceback | Текстовое описание сбоев при перезагрузке (пустая строка если всё нормально) | |
index_records | 19733 | Общее число записей в индексе |
index_buckets | 20289 | Число "ячеек" индекса. Ячейка это набор uuid для одного тега |
index_avg_bucket | 0.97 | Среднее число записей на один тег |
index_min_bucket | 1 | Минимальное число записей на один тег |
index_max_bucket | 17846 | Максимальное число записей на один тег |
index_memory | 46.8 MiB | Расход памяти на объект индекса |
users | 4 | Общее число пользователей, для которых есть данные в индексе |
Предназначено для ручного вызова, после обновления базы данных. Позволяет мягко перезагрузить содержимое индекса без перезагрузки самого сервера. Без этого функционала при перезагрузке даунтайм сервера может достигать нескольких минут (и чем больше будет расти индекс, тем больше времени понадобится). А при работе через инструменты вроде gunicorn - достаточно долго, чтобы мастер процесс посчитал, будто воркер уже умер. Фактически без специальных настроек gunicorn вообще не может запустить сервер начиная с некоторого размера индекса.
Пример запроса:
curl -X POST http://127.0.0.1:9000/reload
Пример ответа:
{
"result": "reloading index"
}
Возвращает ответ мгновенно. Само задание исполняется в фоне. Факт окончания
можно узнавать делая запрос /status
. Операция будет закончена, когда статус
перейдёт из reloading
в active
или failed
.
Если переменная окружения OMOIDE_INDEX_RELOAD_ON_START имеет значение
yes
, эта операция также будет выполнена при старте индекса. В этом случае о
готовности к работе говорит переход из статуса init
в active
.
Если при перезагрузке индекса что-то пошло не так, статус изменится на
failed
. Работоспособность при этом не пострадает, старый индекс останется
актуальным.
Главная операция, ради которой сервер вообще существует. Предполагается, что он очень быстро произведёт поиск по индексу и вернёт соответствующие записи.
Пример запроса:
curl -H "Content-Type: application/json" http://127.0.0.1:9000/search -d '...'
Пример тела запроса:
{
"user_uuid": "e1e977fa-b58b-458a-85e9-0a65df46aef4",
"tags_and": [
"movie"
],
"tags_or": [
"matrix"
],
"tags_not": [
"matrix 4"
],
"page": 1,
"items_per_page": 10
}
Поле user_uuid
говорит о том, для кого делается запрос. Вернутся только
результаты, на которые у пользователя есть права.
Блоки and
/or
/not
это списки тегов, требующие соответствующей логической
операции.
Параметр items_per_page
показывает на сколько страниц нарезать результат, а
параметр page
показывает какую страницу из получившейся нарезки вернуть.
Пример ответа, когда сервер ещё не собрал индекс при первом запуске:
{
"items": [],
"page": 0,
"total_pages": 0,
"total_items": 0,
"announce": "Please wait a few minutes for server init after reload"
}
Пример полноценного ответа:
{
"items": [
"010a6971-1209-46ef-b6f4-07546d676de4",
"014e07f9-7119-4fd1-95e0-391e78c315a7",
"01c1fd44-7f5a-4e03-bedf-6639b647a930",
"01fd7287-4db1-4c2d-a3d6-01995349e32f",
"03a26e29-3273-4766-8885-1fc3584d240e",
"04137754-90cc-404e-9b8f-928f1ab27889",
"0479f19c-9105-40aa-b5da-92d36cfe8f7e",
"04a6e92c-ab26-4925-aeff-89d81ab6cf38",
"05678e0d-0dec-4416-a621-35120ab41dac",
"059605e5-2494-4f45-bb8a-c23608b0f95f"
],
"page": 1,
"total_pages": 49,
"total_items": 486,
"announce": ""
}
В поле announce
могут быть текстовые примечания, которые стоит показать
пользователю (например сообщение о том, что индекс прямо сейчас
перезагружается).
Вызывается, когда у существующего пользователя изменился доступ к каким-либо сущностям. Также применяется для добавления новых пользователей.
Пример запроса:
curl -X POST -H "Content-Type: application/json" http://127.0.0.1:9000/users -d '...'
Пример тела запроса:
{
"user_uuid": "e1e977fa-b58b-458a-85e9-0a65df46aef4",
"refresh_all": false,
"refresh_items": [
"01fd7287-4db1-4c2d-a3d6-01995349e32f",
"03a26e29-3273-4766-8885-1fc3584d240e",
"04137754-90cc-404e-9b8f-928f1ab27889"
]
}
Пример ответа:
{
"user_uuid": "e1e977fa-b58b-458a-85e9-0a65df46aef4",
"action": "refreshing user"
}
Флаг refresh_all
говорит о том, что надо вычитать из базы вообще все записи
для этого пользователя. Если этот флаг не выставлен, можно указать конкретные
записи, для которых надо обновить доступы.
Сами правила видимости при этом не передаются. Сервис самостоятельно сходит в базу и получит данные из неё.
Удалить из индекса этого пользователя и его зону видимости. Вызывается, когда пользователь удалён в основном приложении и в индексе больше не требуется. Проверка существования пользователя не производится. Если пользователь не существует, то ничего не произойдёт.
Пример запроса:
curl -X DELETE -H "Content-Type: application/json" http://127.0.0.1:9000/users -d '...'
Пример тела запроса:
{
"user_uuid": "e1e977fa-b58b-458a-85e9-0a65df46aef4"
}
Пример ответа:
{
"user_uuid": "e1e977fa-b58b-458a-85e9-0a65df46aef4",
"action": "deleting user"
}