Эта статья была написана для Buddy v1.x. Проверьте обновленную версию здесь .
Привет, друзья. У нас захватывающие новости о 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 https://github.com/manticoresoftware/manticoresearch-buddy.git
cd manticoresearch-buddy
git checkout v1.x
Теперь у вас есть весь исходный код Buddy, но ни один из пакетов не установлен. Buddy использует Composer для управления своими зависимостями, и нам нужно сначала установить их, чтобы запустить приложение. Однако перед этим мы запустим специальный контейнер Docker, который мы подготовили специально для разработки. Образ Manticore Executor Kit включает все необходимые инструменты для плавной разработки Manticore Buddy, независимо от того, создаете ли вы новые плагины или вносите вклад в сам Buddy.
docker pull ghcr.io/manticoresoftware/manticoresearch:test-kit-6.2.12
docker create --privileged --entrypoint bash \
-v $(pwd):/workdir -w /workdir --name manticore-buddy \
-it ghcr.io/manticoresoftware/manticoresearch:test-kit-6.2.12
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]. Когда вы захотите остановить процесс, просто используйте Ctrl + C.
На этом этапе все готово для подготовки вашей среды разработки для 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 функционирует правильно и все настроено верно.
Шаблон плагина
Мы создали
специальный репозиторий шаблона GitHub
, который мы настоятельно рекомендуем использовать для создания любого плагина Manticore Buddy. Все плагины должны начинаться с buddy-plugin-[ваше-имя], где [ваше-имя] — это имя вашего плагина. Например, поскольку мы разрабатываем плагин для выбора имени хоста, мы назовем его buddy-plugin-show-hostname. Итак:
- Откройте https://github.com/manticoresoftware/buddy-plugin-template .
- Выберите ветку
v1.x - Нажмите
Use this template, а затемCreate a new repository. - Заполните форму с именем вашего репозитория и создайте его. Убедитесь, что имя вашего репозитория начинается с
buddy-plugin-, так как это обязательно. git cloneваш новый репозиторий в директориюpluginsрепозитория Manticore Buddy, который вы ранее развернули. Обратите внимание, что лучше делать это вне контейнера, особенно если вы клонируете из частного репозитория.
В
https://github.com/manticoresoftware/buddy-plugin-show-hostname
(ветка: v1.x) вы можете найти всю реализованную задачу. Если вы не хотите углубляться в детали, вы можете просто 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внутри контейнера.
Поток запроса от 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: add logic of parsing request into payload here
// We just need to do something, but actually its' just for 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: validate $request->payload and return true, if your plugin should handle it
- 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(Runtime $runtime): Task {
- // TODO: your logic goes into closure and should return TaskResult as response
$taskFn = static function (): TaskResult {
- return TaskResult::none();
+ $hostname = gethostname();
+ return TaskResult::withRow([
+ 'hostname' => $hostname,
+ ])->column('hostname', Column::String);
};
return Task::createInRuntime(
Отладка и разработка
Теперь, когда вы завершили реализацию, пришло время протестировать и отладить (если необходимо) ваш плагин. Существует специальный тип плагина под названием 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 'v1.x';
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, уже доступной в пакетах для разработчиков Linux и скоро появится в следующем релизе (после Manticore 6.0.4, так что если вы читаете это, когда вышла более новая версия, она, вероятно, уже включена). Вы можете начать разрабатывать ваш плагин прямо сейчас, следуя предоставленным нами инструкциям. Хотя это базовое введение в систему плагинов, мы планируем создать и опубликовать более продвинутую статью о разработке сложного плагина. Не стесняйтесь задавать нам вопросы в наших чатах Slack или Telegram , и не стесняйтесь предлагать темы для учебника по сложным плагинам.
Помните, что также хорошая идея — взглянуть на код нашего основного плагина , чтобы углубиться и лучше понять, как это работает в более сложных случаях.
С уважением,
Команда Manticore.
