Привет, друзья. Захватывающие новости о Manticore Buddy: мы завершили миграцию на архитектуру плагинов! Это означает, что вы можете создать собственный запрос Manticore Search SQL/JSON в виде плагина, опубликовать его на 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 и содержит базовую логику, обеспечивающую работу системы и поиск нужного плагина для запуска по команде.
Для более ясного понимания процесса представляем диаграмму, иллюстрирующую поток Request → Response:

Учебник
Чтобы упростить вам задачу и погрузиться в разработку собственного плагина, давайте рассмотрим, как создать простой плагин для 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) и убедитесь, что он работает.Вы должны увидеть несколько строк, начинающихся с# Launch daemon inside the container and keep it foreground 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-[your-name], где [your-name] — название вашего плагина. Например, поскольку мы разрабатываем плагин выбора имени хоста, назовём его 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, и на этом этапе нам нужно разобрать запрос, извлечь полезную информацию и записать её в данные payload, которые будут переданы Handler.
Handler — это класс, который фактически исполняет реализованную команду. Он делает это в потоковой среде, используя расширение parallel, не блокируя основной цикл сервера. Есть простой метод 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(): 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::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.

