Привет, народ. У нас захватывающие новости о Manticore Buddy: мы завершили миграцию на модульный дизайн! Это означает, что вы можете создать собственный SQL/JSON запрос Manticore Search в качестве плагина, опубликовать его на
packagist.org
и установить с помощью SQL команды CREATE PLUGIN
. Давайте углубимся в архитектуру модульной системы и простой туториал, который поможет вам начать.
Архитектура
Введение
Если вы не знакомы с Buddy, мы рекомендуем прочитать блоги:
которые мы публиковали ранее.
Изначально Buddy был разработан на PHP, со всеми расширениями и дополнительными обработчиками команд в одной кодовой базе. После выхода Manticore Search 6 у нас появились вопросы о добавлении пользовательской функциональности, и мы осознали, что текущая система не обладает гибкостью. Вот почему мы решили перейти на модульную архитектуру.
Мы считаем, что самый важный принцип в разработке программного обеспечения – не изобретать велосипед и сохранять простоту. В результате мы не тратя много времени на размышления, выбрали самый известный и популярный менеджер пакетов в мире PHP для управления системой плагинов – Packagist .
Типы плагинов
Существует три типа плагинов:
core
- включены по умолчанию с Buddy и являются частью пакета, который вы получаете при установке Manticore.local
- используются для разработки и отладки перед публикацией.external
- устанавливаются с помощью командыCREATE PLUGIN
.
Этот учебник объясняет, как сначала создать local
плагин, а затем сделать его external
, что позволит любому пользователю Manticore улучшить свою конфигурацию, используя ваш плагин.
Процесс -> ответный поток
Чтобы это работало, мы извлекли общие компоненты в Buddy и всех плагинов в новый пакет – Buddy Core . Он должен быть включен при разработке вашего плагина, чтобы упростить работу в вашей IDE и поддерживать подсказки и автозаполнение.
Код, который позволяет Buddy функционировать как демон и выполнять внутренние задачи, включая соединение между Core и кодом плагина, называется Buddy Base. Это приложение на ReactPHP, которое также использует Buddy Core и содержит базовую логику, чтобы все работало и находило правильный плагин для запуска по команде.
Для более ясного понимания процесса вот схема, иллюстрирующая поток Запрос → Ответ:
Учебник
Чтобы упростить задачу и углубиться в разработку собственного плагина, давайте рассмотрим, как мы можем создать простой плагин для Buddy, который поддерживает команду SHOW HOSTNAME
и возвращает текущий хостнейм машины. Это поможет вам понять процесс, который вы должны следовать при создании собственного плагина, и это также невероятно простой пример для начала. Если мы рассмотрим, как работает SHOW HOSTNAME
в Manticore Search перед реализацией его логики, мы можем ожидать результат, похожий на этот:
mysql> SHOW HOSTNAME;
ERROR 1064 (42000): sphinxql: syntax error, unexpected identifier, expecting VARIABLES near 'HOSTNAME'
Подготовка
Первым делом мы должны подготовить нашу среду разработки. Вам нужно сделать это только один раз, а затем вы сможете обновлять Buddy из
GIT репозитория
, чтобы получать последние обновления. Давайте откроем терминал, клонируем Buddy на наш компьютер в папку под названием manticoresearch-buddy
и перейдем в клонированные папки.
git clone --depth 1 https://github.com/manticoresoftware/manticoresearch-buddy.git
cd manticoresearch-buddy
Теперь у вас есть весь исходный код Buddy, но ни один из пакетов не установлен. Buddy использует Composer для управления своими зависимостями, и нам нужно установить их сначала, чтобы запустить приложение. Однако перед этим мы запустим специальный контейнер Docker, который мы подготовили специально для разработки. Образ Manticore Executor Kit включает все необходимые инструменты для комфортной разработки Manticore Buddy, будь то создание новых плагинов или внесение вклада в сам Buddy.
docker pull ghcr.io/manticoresoftware/manticoresearch:test-kit-latest
docker create --privileged --entrypoint bash \
-v $(pwd):/workdir -w /workdir --name manticore-buddy \
--network host -it ghcr.io/manticoresoftware/manticoresearch:test-kit-latest
docker start manticore-buddy
Поздравляем! Вы только что запустили контейнер Docker с Manticore Search и Manticore Executor для разработки Buddy и плагинов. Рабочая директория, в которой вы находитесь, сопоставлена с /workdir
внутри контейнера. Ваш следующий шаг – установить зависимости Composer. Помните, что эта и все последующие команды должны выполняться внутри контейнера manticore-buddy
.
docker exec -it manticore-buddy bash
composer install
Ваш Buddy теперь готов к использованию, разработке, отладке и тестированию. Далее вам нужно завершить две вещи:
- Во-первых, отредактируйте файл
/etc/manticoresearch/manticore.conf
внутри контейнера и добавьтеbuddy_path
с нашими исходниками. Это даст знать Manticore Search, что нам нужно использовать пользовательский путь запуска Buddy из исходников, а не из установленных модулей. Добавьте это в секциюsearchd
:buddy_path = manticore-executor /workdir/src/main.php --debug
- Во-вторых, попробуйте запустить
searchd
(сервер Manticore Search) и убедитесь, что он работает.Вы должны увидеть несколько строк, начинающихся с# Запустите демон внутри контейнера и держите его в активном режиме searchd --nodetach
[BUDDY]
.
На этом этапе всё готово для подготовки вашей среды разработки для Buddy и начала реализации нового плагина. Вы всё еще можете проводить эксперименты и пытаться выполнять некоторые запросы, чтобы убедиться, что всё работает правильно. Например, откройте другое окно терминала и выполните следующее:
$ docker exec -it manticore-buddy mysql -h0 -P9306
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 6.0.5 3bcbd00fa@230320 dev (columnar 2.0.5 8171c1a@230320) (secondary 2.0.5 8171c1a@230320) git branch HEAD (no branch)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show queries;
+------+--------------+----------+-----------------+
| id | query | protocol | host |
+------+--------------+----------+-----------------+
| 10 | select | http | 127.0.0.1:19148 |
| 9 | show queries | mysql | 127.0.0.1:54484 |
+------+--------------+----------+-----------------+
2 rows in set (0.008 sec)
MySQL [(none)]>
Вы только что отправили команду SHOW QUERIES
в Manticore Search, которая затем была направлена в Buddy и успешно выполнена. Вы можете увидеть, что Buddy получил и его ответ в логе searchd на первой вкладке терминала. Итак, мы можем подтвердить, что Buddy функционирует корректно и всё настроено правильно.
Когда вы хотите остановить процесс searchd, просто нажмите Ctrl + C в первом окне/вкладке терминала.
Шаблон плагина
Мы создали
специальный репозиторий шаблона на GitHub
, который мы настоятельно рекомендуем использовать для создания любого плагина Manticore Buddy. Все плагины должны начинаться с префикса buddy-plugin-[ваше-имя]
, где [ваше-имя]
- это имя вашего плагина. Например, поскольку мы разрабатываем плагин для выбора имени хоста, мы назовем его buddy-plugin-show-hostname
. Итак:
- Откройте https://github.com/manticoresoftware/buddy-plugin-template .
- Нажмите
Use this template
, а затемCreate a new repository
. - Заполните форму с именем вашего репозитория и создайте его. Убедитесь, что имя вашего репозитория начинается с
buddy-plugin-
, так как это обязательно. git clone
ваш новый репозиторий в директориюplugins
репозитория Manticore Buddy, который вы развернули ранее. Обратите внимание, что лучше сделать это вне контейнера, особенно если вы клонируете из частного репозитория.
В
https://github.com/manticoresoftware/buddy-plugin-show-hostname
вы можете найти всю реализованную задачу. Если вы не хотите углубляться в детали, вы можете просто git clone
это вместо вашего форка. Однако если вы хотите освоить создание плагина, продолжим.
Добавьте реальный код
Теперь нам нужно следовать следующим шагам и обновить наш шаблон с соответствующими данными для нашего нового плагина.
- Сначала откройте
composer.json
в директории вашего клонированного плагина и обновите имя плагина, описание и пространства имен. Таким образом, в конечном итоге ваши изменения должны выглядеть так (обязательно используйте имя вашего репозитория плагина):
diff --git a/composer.json b/composer.json
index 23c252b..f36cb6e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,11 +1,11 @@
{
- "name": "manticoresoftware/buddy-plugin-template",
- "description": "The Buddy template handler plugin",
+ "name": "manticoresoftware/buddy-plugin-show-hostname",
+ "description": "The Buddy SHOW hostname handler plugin",
"type": "library",
"license": "GPL-2.0-or-later",
"autoload": {
"psr-4": {
- "Manticoresearch\\Buddy\\Plugin\\Template\\": "src/"
+ "Manticoresearch\\Buddy\\Plugin\\ShowHostname\\": "src/"
}
},
"authors": [
- Нам также нужно обновить пространства имен двух классов в вашем плагине —
Payload
иHandler
. Разница должна выглядеть так:
diff --git a/src/Handler.php b/src/Handler.php
index 3756dc3..07fcfd0 100644
--- a/src/Handler.php
+++ b/src/Handler.php
@@ -8,7 +8,7 @@
version. You should have received a copy of the GPL license along with this
program; if you did not, you can find it at http://www.gnu.org/
*/
-namespace Manticoresearch\Buddy\Plugin\Template;
+namespace Manticoresearch\Buddy\Plugin\ShowHostname;
use Manticoresearch\Buddy\Core\Plugin\BaseHandler;
use Manticoresearch\Buddy\Core\Task\Task;
diff --git a/src/Payload.php b/src/Payload.php
index b170340..a35f201 100644
--- a/src/Payload.php
+++ b/src/Payload.php
@@ -8,7 +8,7 @@
version. You should have received a copy of the GPL license along with this
program; if you did not, you can find it at http://www.gnu.org/
*/
-namespace Manticoresearch\Buddy\Plugin\Template;
+namespace Manticoresearch\Buddy\Plugin\ShowHostname;
use Manticoresearch\Buddy\Core\Network\Request;
use Manticoresearch\Buddy\Core\Plugin\BasePayload;
- В качестве последнего шага не забудьте установить новую зависимость, выполнив
composer install
внутри контейнера (в/workdir
).
Поток запроса от Manticore Search к вашему плагину и обратно
Мы готовы реализовать нашу логику теперь. Но сначала давайте научимся немного больше о том, как это обрабатывается внутри.
Предположим, что мы отправляем запрос SHOW HOSTNAME
к запущенному процессу searchd
, используя MySQL клиент. Manticore Search не может это обработать и отправляет это в Buddy, чтобы дождаться ответа. Buddy может вернуть точный ответ, который просто будет проксирован обратно клиенту MySQL.
Как только Buddy получает запрос от Manticore Search, он разбирает его и проводит валидацию по всем плагинам: сначала по основным плагинам, а затем по внешним плагинам. Для выполнения этой валидации он выполняет метод Payload::hasMatch($request)
, передавая ему запрос, который содержит запрос и некоторые метаданные, такие как запрашиваемая конечная точка, тип (JSON или SQL) и так далее.
Payload
представляет собой структуру, содержащую все необходимые данные для обработки команды. Если Payload
плагина возвращает true в методе hasMatch
, это означает, что мы будем использовать этот плагин для обработки запроса. Он создается из Request
, и на этом этапе нам нужно разобрать запрос, извлечь ценную информацию и установить ее в наши данные полезной нагрузки, которые будут переданы в Handler
.
Handler
— это класс, который фактически выполняет реализованную команду. Он делает это в многопоточной среде, используя расширение параллельности, без блокировки основного цикла сервера. Существует простой метод run
, который создает замыкание, которое должно выполнить задачу и вернуть ответ обратно в Manticore Search, который затем будет проксирован пользователю.
В нашем случае нам просто нужно добавить проверку для поддержки синтаксиса запроса SHOW HOSTNAME
, а затем написать логику Handler
, чтобы вызвать функцию PHP gethostname
и вернуть ее в качестве ответа. Вот и все! Давайте начнем с Payload
.
Реализация Payload
Когда вы откроете src/Payload.php
, вы увидите, что там всего два метода: fromRequest
и hasMatch
. Мы пометили строки, которые нужно редактировать, комментариями TODO
, поэтому их должно быть легко найти. В нашем случае запрос очень прост и вовсе не гибок, поэтому нам не нужно вносить изменения в метод fromRequest
. Мы можем просто удалить комментарии TODO. Что нам нужно сделать, так это обновить статическую функцию hasMatch()
. Там нам нужно реализовать проверку, чтобы запрос строго соответствовал строке SHOW HOSTNAME
без учета регистра. После того, как будет найдено совпадение, мы должны вернуть true. В противном случае мы должны вернуть false. Таким образом, базовая система понимает, что ей нужно использовать этот плагин в случае, если мы получим запрос, который отображает имя хоста.
Итоговый дифф, который мы внесли в Payload
, должен выглядеть так:
diff --git a/src/Payload.php b/src/Payload.php
index a35f201..bd0795e 100644
--- a/src/Payload.php
+++ b/src/Payload.php
@@ -26,7 +26,6 @@ final class Payload extends BasePayload {
*/
public static function fromRequest(Request $request): static {
$self = new static();
- // TODO: добавить логику разбора запроса в полезную нагрузку здесь
// Нам просто нужно сделать что-то, но на самом деле это только для PHPstan
$self->path = $request->path;
return $self;
@@ -37,7 +36,6 @@ final class Payload extends BasePayload {
* @return bool
*/
public static function hasMatch(Request $request): bool {
- // TODO: проверить $request->payload и вернуть true, если ваш плагин должен его обрабатывать
- return $request->payload === 'template';
+ return stripos($request->payload, 'show hostname') !== false;
}
}
С изменениями в Payload
мы закончили и можем перейти к Handler
, чтобы реализовать настоящую логику.
Реализация Handler
Теперь давайте откроем src/Handler.php
и рассмотрим отметки TODO, а также краткое описание того, что происходит. Нам нужно перейти к методу run
и обновить его.
Мы видим замыкание, которое возвращает TaskResult
, что является специальным типом результата, который оборачивает стандартный JSON-ответ.
Мы добавим вызов gethostname()
и подготовим ответ, обернув его в TaskResult
, который будет возвращен клиенту. Итоговый дифф будет выглядеть следующим образом:
diff --git a/src/Handler.php b/src/Handler.php
index 07fcfd0..944899b 100644
--- a/src/Handler.php
+++ b/src/Handler.php
@@ -11,6 +11,7 @@
namespace Manticoresearch\Buddy\Plugin\ShowHostname;
use Manticoresearch\Buddy\Core\Plugin\BaseHandler;
+use Manticoresearch\Buddy\Core\Task\Column;
use Manticoresearch\Buddy\Core\Task\Task;
use Manticoresearch\Buddy\Core\Task\TaskResult;
use RuntimeException;
@@ -33,9 +34,11 @@ final class Handler extends BaseHandler {
* @throws RuntimeException
*/
public function run(): Task {
- // TODO: ваша логика идет в замыкание и должна возвращать TaskResult в качестве ответа
$taskFn = static function (): TaskResult {
- return TaskResult::none();
+ $hostname = gethostname();
+ return TaskResult::withRow([
+ 'hostname' => $hostname,
+ ])->column('hostname', Column::String);
};
return Task::create(
Отладка и разработка
Теперь, когда вы завершили реализацию, пришло время протестировать и отладить (если необходимо) ваш плагин. Существует специальный тип плагина под названием local
, который специально предназначен для этой цели. Поскольку ваш плагин уже находится в директории plugins
, он автоматически становится плагином типа local
. Чтобы использовать его, просто:
- В корневом каталоге Buddy выполните команду
composer require [your-plugin-name]:dev-main
, чтобы включить плагин.your-plugin-name
— это название из вашегоcomposer.json
плагина, который вы редактировали ранее. - Перезапустите
searchd
, чтобы убедиться, что код обновлен.
Этот метод позволяет вам разрабатывать, отлаживать, редактировать и тестировать ваш плагин в реальном времени, не отправляя его в репозиторий Git и не публикуя на packagist.org .
Публикация и установка
Когда вы закончите с отладкой и будете готовы опубликовать ваш плагин, просто зафиксируйте изменения в репозитории Git и опубликуйте свой пакет на packagist.org .
После этого проверьте, что он работает так, как ожидалось, выполнив команду CREATE PLUGIN [your-plugin-name] TYPE 'buddy' VERSION 'dev-main'
, которая попытается загрузить плагин с помощью Composer и установить его в plugin_dir
.
Как это:
$ docker exec -it manticore-buddy mysql -h0 -P9306
MySQL [(none)]> CREATE PLUGIN manticoresoftware/buddy-plugin-show-hostname type 'buddy' VERSION 'dev-main';
Query OK, 0 rows affected (1 min 12.213 sec)
MySQL [(none)]> show hostname;
+----------+
| hostname |
+----------+
| dev |
+----------+
1 row in set (0.011 sec)
MySQL [(none)]>
Поздравляю! Ваш плагин работает отлично и позволяет вам получать имя хоста с помощью запроса SHOW hostname
.
Заключение
Мы надеемся, что вам понравилась эта статья и вы получили более глубокое понимание новой плаваемой архитектуры Buddy, доступной с версии Manticore 6.0.4. Вы можете сразу начать разрабатывать свой плагин, следуя предоставленным нами инструкциям. Хотя это базовое введение в плаваемую систему, мы планируем создать и опубликовать более продвинутую статью о разработке сложного плагина. Не стесняйтесь задавать нам вопросы в нашем Slack или Telegram чатах, и не стесняйтесь предлагать темы для руководства по сложному плагину.
Помните, что хорошей идеей будет изучить встроенный код плагина Buddy, чтобы глубже понять, как он работает в более сложных сценариях.
Искренне ваш,
Команда Manticore.