Эта статья была написана для 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: синтаксическая ошибка, неожиданный идентификатор, ожидание VARIABLES рядом с '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. Вот так базовая система понимает, что ей нужно использовать этот плагин в случае, если мы получим запрос, который показывает имя хоста.
Финальный diff, который мы сделали для 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 будет выглядеть следующим образом:
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
, он автоматически становится локальным плагином. Чтобы использовать его, просто:
- В корневой директории 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.