diff --git a/APP_VERSION b/APP_VERSION index 781dcb07..38f77a65 100644 --- a/APP_VERSION +++ b/APP_VERSION @@ -1 +1 @@ -1.1.3 +2.0.1 diff --git a/bin/query b/bin/query index c85681b7..187087f9 100755 --- a/bin/query +++ b/bin/query @@ -32,7 +32,7 @@ try { 'body' => '$query', ] ]); - \$task = QueryProcessor::process(\$request)->run(Task::createRuntime()); + \$task = QueryProcessor::process(\$request)->run(); \$status = \$task->wait(true); printf('Status code: %s' . PHP_EOL, \$status->name); printf('Result: ' . PHP_EOL . '%s', \$task->getResult()->getStruct()); diff --git a/composer.json b/composer.json index 37c9dc81..b135f52d 100644 --- a/composer.json +++ b/composer.json @@ -31,17 +31,18 @@ "react/socket": "^1.12", "manticoresoftware/telemetry": "^0.1.9", "symfony/dependency-injection": "^6.1", - "manticoresoftware/buddy-core": "^v0.1.0", - "manticoresoftware/buddy-plugin-empty-string": "^v0.1.0", - "manticoresoftware/buddy-plugin-backup": "^v0.1.0", - "manticoresoftware/buddy-plugin-emulate-elastic": "^v0.1.0", - "manticoresoftware/buddy-plugin-insert": "^v0.1.0", - "manticoresoftware/buddy-plugin-select": "^v0.1.0", - "manticoresoftware/buddy-plugin-show": "^v0.1.0", - "manticoresoftware/buddy-plugin-cli-table": "^v0.1.0", - "manticoresoftware/buddy-plugin-plugin": "^v0.1.0", - "manticoresoftware/buddy-plugin-test": "^v0.1.0", - "manticoresoftware/buddy-plugin-insert-mva": "^v0.1.0", + "manticoresoftware/buddy-core": "dev-main", + "manticoresoftware/buddy-plugin-empty-string": "dev-main", + "manticoresoftware/buddy-plugin-backup": "dev-main", + "manticoresoftware/buddy-plugin-emulate-elastic": "dev-main", + "manticoresoftware/buddy-plugin-insert": "dev-main", + "manticoresoftware/buddy-plugin-select": "dev-main", + "manticoresoftware/buddy-plugin-show": "dev-main", + "manticoresoftware/buddy-plugin-cli-table": "dev-main", + "manticoresoftware/buddy-plugin-plugin": "dev-main", + "manticoresoftware/buddy-plugin-test": "dev-main", + "manticoresoftware/buddy-plugin-insert-mva": "dev-main", + "manticoresoftware/buddy-plugin-create-table": "dev-main", "php-ds/php-ds": "^1.4" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 1938a48e..003c52cb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3c8d5f6bfe9a94b5417139b9e69767da", + "content-hash": "fd3900dc2c25c7e0ddeb1286a53f3fa8", "packages": [ { "name": "composer/ca-bundle", @@ -811,16 +811,16 @@ }, { "name": "manticoresoftware/buddy-core", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-core.git", - "reference": "0ec2ea462555d31f732939fa5ed1ebfc4c28b2b3" + "reference": "33173cbaee98d79d77979bc7b7b0ee6066de1139" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-core/zipball/0ec2ea462555d31f732939fa5ed1ebfc4c28b2b3", - "reference": "0ec2ea462555d31f732939fa5ed1ebfc4c28b2b3", + "url": "https://api.github.com/repos/manticoresoftware/buddy-core/zipball/33173cbaee98d79d77979bc7b7b0ee6066de1139", + "reference": "33173cbaee98d79d77979bc7b7b0ee6066de1139", "shasum": "" }, "require": { @@ -835,6 +835,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -855,26 +856,26 @@ "description": "The Buddy Core to develop your own plugin for Manticore Search", "support": { "issues": "https://github.com/manticoresoftware/buddy-core/issues", - "source": "https://github.com/manticoresoftware/buddy-core/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-core/tree/main" }, - "time": "2023-09-19T08:31:13+00:00" + "time": "2023-10-19T07:25:53+00:00" }, { "name": "manticoresoftware/buddy-plugin-backup", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-backup.git", - "reference": "2b58863b6fa995f43e4041a1773619ede95fcfbe" + "reference": "6b94c115517dfa026ed697bbcb15d6177bb88545" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-backup/zipball/2b58863b6fa995f43e4041a1773619ede95fcfbe", - "reference": "2b58863b6fa995f43e4041a1773619ede95fcfbe", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-backup/zipball/6b94c115517dfa026ed697bbcb15d6177bb88545", + "reference": "6b94c115517dfa026ed697bbcb15d6177bb88545", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0", + "manticoresoftware/buddy-core": "dev-main", "manticoresoftware/manticoresearch-backup": "^1.0.7" }, "require-dev": { @@ -883,6 +884,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -902,27 +904,27 @@ "description": "The Buddy Backup plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-backup/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-backup/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-backup/tree/main" }, - "time": "2023-10-18T07:39:38+00:00" + "time": "2023-10-18T07:56:17+00:00" }, { "name": "manticoresoftware/buddy-plugin-cli-table", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-cli-table.git", - "reference": "b9bde915803a9c2effceb47dfd6dc4937b1aa1aa" + "reference": "10e2f70418389ca05f8b5315253b699acabed154" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-cli-table/zipball/b9bde915803a9c2effceb47dfd6dc4937b1aa1aa", - "reference": "b9bde915803a9c2effceb47dfd6dc4937b1aa1aa", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-cli-table/zipball/10e2f70418389ca05f8b5315253b699acabed154", + "reference": "10e2f70418389ca05f8b5315253b699acabed154", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0", - "manticoresoftware/buddy-plugin-show": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main", + "manticoresoftware/buddy-plugin-show": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -930,6 +932,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -949,26 +952,73 @@ "description": "The Buddy CLI table plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-cli-table/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-cli-table/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-cli-table/tree/main" }, - "time": "2023-10-18T07:42:54+00:00" + "time": "2023-10-18T08:02:24+00:00" + }, + { + "name": "manticoresoftware/buddy-plugin-create-table", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/manticoresoftware/buddy-plugin-create-table.git", + "reference": "6622410d534240eebf0cabc1b7fb9539316bf8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-create-table/zipball/6622410d534240eebf0cabc1b7fb9539316bf8b4", + "reference": "6622410d534240eebf0cabc1b7fb9539316bf8b4", + "shasum": "" + }, + "require": { + "manticoresoftware/buddy-core": "dev-main" + }, + "require-dev": { + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "slevomat/coding-standard": "^8.5", + "squizlabs/php_codesniffer": "^3.7" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "Manticoresearch\\Buddy\\Plugin\\CreateTable\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Manticore Software Co. Ltd", + "email": "contact@manticoresearch.com" + } + ], + "description": "The Buddy create sharded table plugin", + "support": { + "issues": "https://github.com/manticoresoftware/buddy-plugin-create-table/issues", + "source": "https://github.com/manticoresoftware/buddy-plugin-create-table/tree/main" + }, + "time": "2023-10-18T08:04:00+00:00" }, { "name": "manticoresoftware/buddy-plugin-empty-string", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-empty-string.git", - "reference": "8168f352624de3d7a14a3522ae565722393c021e" + "reference": "c0889f309572d0da2deaec20df8d0ba92b7277dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-empty-string/zipball/8168f352624de3d7a14a3522ae565722393c021e", - "reference": "8168f352624de3d7a14a3522ae565722393c021e", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-empty-string/zipball/c0889f309572d0da2deaec20df8d0ba92b7277dd", + "reference": "c0889f309572d0da2deaec20df8d0ba92b7277dd", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -976,6 +1026,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -995,26 +1046,26 @@ "description": "The Buddy Empty string in query handler plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-empty-string/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-empty-string/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-empty-string/tree/main" }, - "time": "2023-10-18T07:39:55+00:00" + "time": "2023-10-18T08:06:47+00:00" }, { "name": "manticoresoftware/buddy-plugin-emulate-elastic", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-emulate-elastic.git", - "reference": "c57e879d47abbacfdea356fa8515c9abbf4aa411" + "reference": "66c06e863b97651a0da501b368a49887282f7b0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-emulate-elastic/zipball/c57e879d47abbacfdea356fa8515c9abbf4aa411", - "reference": "c57e879d47abbacfdea356fa8515c9abbf4aa411", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-emulate-elastic/zipball/66c06e863b97651a0da501b368a49887282f7b0e", + "reference": "66c06e863b97651a0da501b368a49887282f7b0e", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1022,6 +1073,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1041,26 +1093,26 @@ "description": "The Buddy elastic endpoints emulator plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-emulate-elastic/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-emulate-elastic/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-emulate-elastic/tree/main" }, - "time": "2023-10-18T07:40:03+00:00" + "time": "2023-10-18T08:09:34+00:00" }, { "name": "manticoresoftware/buddy-plugin-insert", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-insert.git", - "reference": "c0a0a9d26f4c6c496279160f76f1392f0dc23dec" + "reference": "19e529b9ccc818824bbc29a8ab40d7912b9d2c8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-insert/zipball/c0a0a9d26f4c6c496279160f76f1392f0dc23dec", - "reference": "c0a0a9d26f4c6c496279160f76f1392f0dc23dec", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-insert/zipball/19e529b9ccc818824bbc29a8ab40d7912b9d2c8e", + "reference": "19e529b9ccc818824bbc29a8ab40d7912b9d2c8e", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1068,6 +1120,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1087,26 +1140,26 @@ "description": "The Buddy INSERT auto schema plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-insert/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-insert/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-insert/tree/main" }, - "time": "2023-10-18T07:40:12+00:00" + "time": "2023-10-18T08:16:17+00:00" }, { "name": "manticoresoftware/buddy-plugin-insert-mva", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-insert-mva.git", - "reference": "b2534c57b0d959579be406f96c9907448188ee29" + "reference": "ca870e7856c62a70d49022cd63de79fa6a4e8882" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-insert-mva/zipball/b2534c57b0d959579be406f96c9907448188ee29", - "reference": "b2534c57b0d959579be406f96c9907448188ee29", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-insert-mva/zipball/ca870e7856c62a70d49022cd63de79fa6a4e8882", + "reference": "ca870e7856c62a70d49022cd63de79fa6a4e8882", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1114,6 +1167,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1133,26 +1187,26 @@ "description": "The Buddy to support insert MVA as a string for mysqldump", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-insert-mva/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-insert-mva/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-insert-mva/tree/main" }, - "time": "2023-10-18T07:40:21+00:00" + "time": "2023-10-18T08:17:17+00:00" }, { "name": "manticoresoftware/buddy-plugin-plugin", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-plugin.git", - "reference": "245d5d7538889a4cdf3221d8c6497f7ff7e0153b" + "reference": "3f8c1945803b907ae1939e649e73691b33eccbb4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-plugin/zipball/245d5d7538889a4cdf3221d8c6497f7ff7e0153b", - "reference": "245d5d7538889a4cdf3221d8c6497f7ff7e0153b", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-plugin/zipball/3f8c1945803b907ae1939e649e73691b33eccbb4", + "reference": "3f8c1945803b907ae1939e649e73691b33eccbb4", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1160,6 +1214,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1179,26 +1234,26 @@ "description": "The Buddy Plugin to manage plugins", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-plugin/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-plugin/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-plugin/tree/main" }, - "time": "2023-10-18T07:40:29+00:00" + "time": "2023-10-18T08:20:42+00:00" }, { "name": "manticoresoftware/buddy-plugin-select", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-select.git", - "reference": "a9b2187fa48349358c89d93741bc05b418f32e58" + "reference": "820c79d90331741923ae5714bc658bbbc96dfee3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-select/zipball/a9b2187fa48349358c89d93741bc05b418f32e58", - "reference": "a9b2187fa48349358c89d93741bc05b418f32e58", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-select/zipball/820c79d90331741923ae5714bc658bbbc96dfee3", + "reference": "820c79d90331741923ae5714bc658bbbc96dfee3", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1206,6 +1261,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1225,26 +1281,26 @@ "description": "The Buddy failed SELECT statement handler plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-select/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-select/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-select/tree/main" }, - "time": "2023-10-18T07:40:38+00:00" + "time": "2023-10-18T08:22:52+00:00" }, { "name": "manticoresoftware/buddy-plugin-show", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-show.git", - "reference": "d1c5c0b0966de876d8adae0ab4fa3400bdbd5038" + "reference": "32a3b71b9edfa816462afbd3d2089a6f757cce39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-show/zipball/d1c5c0b0966de876d8adae0ab4fa3400bdbd5038", - "reference": "d1c5c0b0966de876d8adae0ab4fa3400bdbd5038", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-show/zipball/32a3b71b9edfa816462afbd3d2089a6f757cce39", + "reference": "32a3b71b9edfa816462afbd3d2089a6f757cce39", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1252,6 +1308,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1271,26 +1328,26 @@ "description": "The Buddy SHOW plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-show/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-show/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-show/tree/main" }, - "time": "2023-10-18T07:40:46+00:00" + "time": "2023-10-18T08:01:01+00:00" }, { "name": "manticoresoftware/buddy-plugin-test", - "version": "v0.1.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-plugin-test.git", - "reference": "288c7b929e570028684e0fe3298f08506f57c6dc" + "reference": "155385c0ba6c8d4cd9cfc0c02d645cb36634e191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-test/zipball/288c7b929e570028684e0fe3298f08506f57c6dc", - "reference": "288c7b929e570028684e0fe3298f08506f57c6dc", + "url": "https://api.github.com/repos/manticoresoftware/buddy-plugin-test/zipball/155385c0ba6c8d4cd9cfc0c02d645cb36634e191", + "reference": "155385c0ba6c8d4cd9cfc0c02d645cb36634e191", "shasum": "" }, "require": { - "manticoresoftware/buddy-core": "v0.1.0" + "manticoresoftware/buddy-core": "dev-main" }, "require-dev": { "phpstan/phpstan": "^1.8", @@ -1298,6 +1355,7 @@ "slevomat/coding-standard": "^8.5", "squizlabs/php_codesniffer": "^3.7" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1317,9 +1375,9 @@ "description": "The Buddy test command plugin", "support": { "issues": "https://github.com/manticoresoftware/buddy-plugin-test/issues", - "source": "https://github.com/manticoresoftware/buddy-plugin-test/tree/v0.1.0" + "source": "https://github.com/manticoresoftware/buddy-plugin-test/tree/main" }, - "time": "2023-10-18T07:40:55+00:00" + "time": "2023-10-18T08:28:37+00:00" }, { "name": "manticoresoftware/manticoresearch-backup", @@ -5758,7 +5816,20 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "manticoresoftware/buddy-core": 20, + "manticoresoftware/buddy-plugin-empty-string": 20, + "manticoresoftware/buddy-plugin-backup": 20, + "manticoresoftware/buddy-plugin-emulate-elastic": 20, + "manticoresoftware/buddy-plugin-insert": 20, + "manticoresoftware/buddy-plugin-select": 20, + "manticoresoftware/buddy-plugin-show": 20, + "manticoresoftware/buddy-plugin-cli-table": 20, + "manticoresoftware/buddy-plugin-plugin": 20, + "manticoresoftware/buddy-plugin-test": 20, + "manticoresoftware/buddy-plugin-insert-mva": 20, + "manticoresoftware/buddy-plugin-create-table": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": [], diff --git a/src/Lib/MetricThread.php b/src/Lib/MetricThread.php index 3123b394..e1422772 100644 --- a/src/Lib/MetricThread.php +++ b/src/Lib/MetricThread.php @@ -11,10 +11,9 @@ namespace Manticoresearch\Buddy\Base\Lib; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Tool\Buddy; use Psr\Container\ContainerInterface; -use parallel\Channel; +use Swoole\Process; // This is class that allows us to run separate thread for telemetry collection /** @@ -37,12 +36,7 @@ final class MetricThread { // We set this on initialization (init.php) so we are sure we have it in class protected static ContainerInterface $container; - - /** - * @param Task $task - * @return void - */ - public function __construct(protected Task $task) { + public function __construct(public readonly Process $process) { } /** @@ -65,7 +59,7 @@ public static function destroy(): void { return; } - static::$instance->task->destroy(); + static::$instance->process->exit(); } /** @@ -87,36 +81,28 @@ public static function instance(): static { * @return self */ public static function start(): self { - $task = Task::loopInRuntime( - Task::createRuntime(), - static function (Channel $ch, string $container) { - $container = unserialize($container); - /** @var ContainerInterface $container */ - // This fix issue when we get "sh: 1: cd: can't cd to" error - // while running buddy inside directory that are not allowed for us + $process = new Process( + static function (Process $worker) { chdir(sys_get_temp_dir()); - Metric::setContainer($container); + Metric::setContainer(static::$container); $metric = Metric::instance(); - while ($msg = $ch->recv()) { + + while ($msg = $worker->read()) { + if (!is_string($msg)) { + throw new \Exception('Incorrect data received'); + } + $msg = unserialize($msg); if (!is_array($msg)) { throw new \Exception('Incorrect data received'); } [$method, $args] = $msg; $metric->$method(...$args); } - }, [serialize(static::$container)] + }, true, 2 ); - - return (new self($task))->run(); - } - - /** - * @return self - */ - public function run(): self { - $this->task->run(); - return $this; + $process->start(); + return new self($process); } /** @@ -129,9 +115,8 @@ public function run(): self { * @return static */ public function execute(string $method, array $args = []): static { - $argsJson = json_encode($args); - Buddy::debug("metric: $method $argsJson"); - $this->task->transmit([$method, $args]); + Buddy::debug("metric: $method " . json_encode($args)); + $this->process->write(serialize([$method, $args])); return $this; } } diff --git a/src/Lib/QueryProcessor.php b/src/Lib/QueryProcessor.php index 47dbf1e2..e9347a2b 100644 --- a/src/Lib/QueryProcessor.php +++ b/src/Lib/QueryProcessor.php @@ -13,7 +13,7 @@ use Exception; use Manticoresearch\Buddy\Base\Exception\SQLQueryCommandNotSupported; -use Manticoresearch\Buddy\Base\Network\EventHandler; +use Manticoresearch\Buddy\Base\Sharding\Thread as ShardingThread; use Manticoresearch\Buddy\Core\ManticoreSearch\Client as HTTPClient; use Manticoresearch\Buddy\Core\ManticoreSearch\Settings as ManticoreSettings; use Manticoresearch\Buddy\Core\ManticoreSearch\Settings; @@ -205,7 +205,6 @@ protected static function getHooks(): array { 'installed', function () { static::$extraPlugins = static::$pluggable->fetchExtraPlugins(); - EventHandler::setShouldExit(true); }, ], // Happens when we remove the plugin @@ -214,18 +213,16 @@ function () { 'deleted', function () { static::$extraPlugins = static::$pluggable->fetchExtraPlugins(); - EventHandler::setShouldExit(true); }, ], // Happens when we run create table with shards in options - // TODO: uncomment and add plugin to composer.json - // [ - // 'manticoresoftware/buddy-plugin-create-table', - // 'shard', - // function (array $args) { - // ShardingThread::instance()->execute('shard', $args); - // }, - // ], + [ + 'manticoresoftware/buddy-plugin-create-table', + 'shard', + function (array $args) { + ShardingThread::instance()->execute('shard', $args); + }, + ], ]; } } diff --git a/src/Network/EventHandler.php b/src/Network/EventHandler.php index 7c415b30..45ccfb8c 100644 --- a/src/Network/EventHandler.php +++ b/src/Network/EventHandler.php @@ -11,7 +11,6 @@ namespace Manticoresearch\Buddy\Base\Network; -use Exception; use Manticoresearch\Buddy\Base\Exception\SQLQueryCommandNotSupported; use Manticoresearch\Buddy\Base\Lib\QueryProcessor; use Manticoresearch\Buddy\Core\Error\GenericError; @@ -19,73 +18,17 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\RequestFormat; use Manticoresearch\Buddy\Core\Network\Request; use Manticoresearch\Buddy\Core\Network\Response; -use Manticoresearch\Buddy\Core\Task\Task; -use Manticoresearch\Buddy\Core\Task\TaskPool; -use Manticoresearch\Buddy\Core\Tool\Buddy; -use Manticoresearch\Buddy\Core\Tool\Process; -use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\Loop; -use React\EventLoop\TimerInterface; -use React\Http\Message\Response as HttpResponse; -use React\Promise\Deferred; -use React\Promise\Promise; -use React\Promise\PromiseInterface; -use RuntimeException; +use Manticoresearch\Buddy\Core\Task\Column; +use Manticoresearch\Buddy\Core\Task\TaskResult; +use Swoole\Http\Request as SwooleRequest; +use Swoole\Http\Response as SwooleResponse; use Throwable; -use parallel\Runtime; /** * This is the main class that contains all handlers * for work with connection initiated by React framework */ final class EventHandler { - // How many request we handle in single runtime after we destroy and create new one - const RUNTIME_LIFETIME = 100; - - /** @var array{available:array,blocked:array} $runtimes */ - public static array $runtimes = [ - 'available' => [], - 'blocked' => [], - ]; - - /** @var int */ - public static int $maxRuntimeIndex; - - /** @var bool */ - protected static bool $shouldExit = false; - - /** - * This fucntion must be called before using any request processing to initizalize runtimes for threading - * - * @return void - */ - public static function init(): void { - $threads = (int)(getenv('THREADS', true) ?: 4); - for ($i = 0; $i < $threads; $i++) { - static::$runtimes['available'][] = [0, Task::createRuntime()]; - } - static::$maxRuntimeIndex = $threads - 1; - } - - /** - * @return void - */ - public static function destroy(): void { - try { - foreach (static::$runtimes['available'] as [, $runtime]) { - $runtime->kill(); - } - foreach (static::$runtimes['blocked'] as [, $runtime]) { - $runtime->kill(); - } - static::$runtimes = [ - 'available' => [], - 'blocked' => [], - ]; - } catch (Throwable) { - } - } - /** * Check if a custom error should be sent * @@ -98,328 +41,71 @@ protected static function shouldProxyError(Throwable $e): bool { || ($e instanceof GenericError && $e->getProxyOriginalError()); } - /** - * Process 'data' event on connecction - * - * @param ServerRequestInterface $serverRequest - * @param string $data - * @return PromiseInterface - */ - protected static function data(ServerRequestInterface $serverRequest, string $data): PromiseInterface { - $deferred = new Deferred; - $id = static::getRequestId($serverRequest); - Buddy::debug("[$id] request data: $data"); - - // Get extra properties to identified connectio and host - // and set it for the task first - /** @var string $host */ - $host = $serverRequest->getHeader('Host')[0] ?? ''; - - // We always add periodic timer, just because we keep tracking deferred tasks - // to show it in case of show queries - $tickFn = static function (?TimerInterface $timer = null) use ($id, $data, $host, $deferred) { - static $ts; - static $request; - static $executor; - static $task; - static $firstCall = true; - if (!isset($task)) { - try { - // we try to pop runtime and when we have some, process, otherwise just queue - if (!static::$runtimes['available']) { - return; - } - /** @var array{0:int,1:Runtime} */ - $runtimeStruct = array_pop(static::$runtimes['available']); - [$usageCount, $runtime] = $runtimeStruct; - static::$runtimes['blocked'][$id] = [++$usageCount, $runtime]; - $request = Request::fromString($data, $id); - $executor = QueryProcessor::process($request); - $task = $executor->run($runtime); - } catch (Throwable $e) { - return static::handleExceptionWhileDataProcessing( - $e, $id, $request ?? null, $data, $deferred, $timer, $runtimeStruct ?? null - ); - } - - $task - ->setHost($host) - ->setBody($request->payload); - // Add task to running pool first - TaskPool::add($task); - } - - // Instantly return in case it's a deferred task - if ($firstCall && $task->isDeferred()) { - $firstCall = false; - return static::handleDeferredTask($request, $deferred, $task); - } - - if (!isset($ts)) { - $ts = time(); - } - $now = time(); - // Dump debug message once a 5 sec - if (($now - $ts) >= 5) { - $ts = $now; - $taskId = $task->getId(); - $taskStatus = $task->getStatus()->name; - Buddy::debug("[$request->id] Task $taskId is $taskStatus"); - } - if ($task->isRunning()) { - return; - } - - static::handleTaskFinished($task, $timer, $id); - if ($task->isSucceed()) { - $result = $task->getResult(); - if (!$task->isDeferred()) { - $deferred->resolve( - [$request, Response::fromMessage($result->getStruct(), $request->format)] - ); - return $deferred; - } - } - - if (!$task->isDeferred()) { - $deferred->resolve( - [ - $request, - Response::fromError($task->getError(), $request->format), - ] - ); - return $deferred; - } - }; - - // In case we work with deferred task we - // should return response to the client without waiting - // for results of it - $tickFn(Loop::addPeriodicTimer(0.001, $tickFn)); - - return $deferred->promise(); - } /** * Main handler for HTTP request that returns HttpResponse * - * @param ServerRequestInterface $serverRequest - * @return Promise + * @param SwooleRequest $request + * @param SwooleResponse $response + * @return void */ - public static function request(ServerRequestInterface $serverRequest): Promise { - return new Promise( - function (callable $resolve, callable $reject) use ($serverRequest) { - static $headers = ['Content-Type' => 'application/json']; - - $data = (string)$serverRequest->getBody(); - $promise = static::data($serverRequest, $data); - // Allow only post and otherwise send bad request - if ($serverRequest->getMethod() !== 'POST') { - return $reject( - new HttpResponse( - 400, $headers, (string)Response::none() - ) - ); - } + public static function request(SwooleRequest $request, SwooleResponse $response): void { + // Allow only post and otherwise send bad request + if ($request->server['request_method'] !== 'POST') { + $response->status(400); + $response->end(Response::none()); + return; + } - $promise->then( - function (mixed $payload) use ($headers, $resolve, $serverRequest): mixed { - /** @var array{0:Request,1:Response} $payload */ - [$request, $response] = $payload; - $result = (string)$response; - $id = static::getRequestId($serverRequest); - if ($response->hasError()) { - $respStatus = 400; - $debugMsgPrefix = 'error'; - } else { - $respStatus = 200; - $debugMsgPrefix = ''; - } - Buddy::debug("[$id] $debugMsgPrefix response data: $result"); - $time = (int)((microtime(true) - $request->time) * 1000000); - Buddy::debug("[$id] process time: {$time}µs"); - return $resolve(new HttpResponse($respStatus, $headers, $result)); - } - ); - } - ); + $requestId = $request->header['Request-ID'] ?? '0'; + $result = static::process($requestId, $request->rawContent() ?: ''); + // Send response + $response->header('Content-Type', 'application/json'); + $response->status(200); + $response->end((string)$result); } /** - * Process 'error' event on connection - * - * @param Exception $e + * Process the main request + * @param string $id + * @param string $payload * @return Response */ - public static function error(Exception $e): Response { - Buddy::debug('Error: ' . $e->getMessage()); - return Response::none(); - } - - /** - * Ticker to validate that client is alive or not - * - * @param int $pid Initiale parent pid - * @return callable - */ - public static function clientCheckTickerFn(int $pid): callable { - return function () use ($pid) { - $curPid = Process::getParentPid(); - if ($curPid === $pid && Process::exists($pid)) { - return; + public static function process(string $id, string $payload): Response { + try { + $request = Request::fromString($payload, $id); + $handler = QueryProcessor::process($request)->run(); + // In case deferred we return the ID of the task not the request + if ($handler->isDeferred()) { + $result = TaskResult::withData([['id' => $handler->getId()]]) + ->column('id', Column::Long); + } else { + $handler->wait(true); + $result = $handler->getResult(); } - Buddy::debug('Parrent proccess died, exiting…'); - if (function_exists('posix_kill')) { - posix_kill((int)getmypid(), 1); + $response = Response::fromMessage($result->getStruct(), $request->format); + } catch (Throwable $e) { + var_dump($e->getMessage()); + var_dump($e->getTraceAsString()); + /** @var string $originalError */ + $originalError = match (true) { + isset($request) => $request->error, + default => ((array)json_decode($payload, true))['error'] ?? '', + }; + + // We proxy original error in case when we do not know how to handle query + // otherwise we send our custom error + if (static::shouldProxyError($e)) { + /** @var GenericError $e */ + $e->setResponseError($originalError); + } elseif (!is_a($e, GenericError::class)) { + $e = GenericError::create($originalError); } - exit(0); - }; - } - - /** - * Set flag that will notify our server that we need to stop - * @param bool $shouldExit - * @return void - */ - public static function setShouldExit(bool $shouldExit): void { - static::$shouldExit = $shouldExit; - } - - /** - * Get the flag that will notify if we should exit - * @return bool - */ - public static function shouldExit(): bool { - return static::$shouldExit; - } - - /** - * Get identifier for current request from headers - * - * @param ServerRequestInterface $serverRequest - * @return string - */ - protected static function getRequestId(ServerRequestInterface $serverRequest): string { - return $serverRequest->getHeader('Request-ID')[0] ?? '0'; - } - - /** - * @param Request $request - * @param Deferred $deferred - * @param Task $task - * @return PromiseInterface - */ - protected static function handleDeferredTask(Request $request, Deferred $deferred, Task $task): PromiseInterface { - // TODO: extract it somewhere for better code - $response = [[ - 'columns' => [ - 'id' => [ - 'type' => 'long long', - ], - ], - 'data' => [ - [ - 'id' => $task->getId(), - ], - ], - ], - ]; - $deferred->resolve( - [ - $request, - Response::fromMessage($response, $request->format), - ] - ); - return $deferred->promise(); - } - - /** - * - * @param Throwable $e - * @param string $id - * @param ?Request $request - * @param string $data - * @param Deferred $deferred - * @param ?TimerInterface $timer - * @param ?array{0:int,1:Runtime} $runtimeStruct - * @return PromiseInterface - * @throws RuntimeException - */ - protected static function handleExceptionWhileDataProcessing( - Throwable $e, - string $id, - ?Request $request, - string $data, - Deferred $deferred, - ?TimerInterface $timer, - ?array $runtimeStruct - ): PromiseInterface { - Buddy::debug("[$id] data parse error: {$e->getMessage()}"); - - // If we pop runtime, return back in case of error - if ($runtimeStruct) { - [$usageCount, $runtime] = $runtimeStruct; - array_unshift(static::$runtimes['available'], [++$usageCount, $runtime]); - } - - // Create special generic error in case we have system exception - // And shadowing $e with it - /** @var string $originalError */ - $originalError = match (true) { - isset($request) => $request->error, - default => ((array)json_decode($data, true))['error'] ?? '', - }; - // We proxy original error in case when we do not know how to handle query - // otherwise we send our custom error - if (self::shouldProxyError($e)) { - /** @var GenericError $e */ - $e->setResponseError($originalError); - } elseif (!is_a($e, GenericError::class)) { - $e = GenericError::create($originalError); - } - - static::handleTaskFinished(null, $timer, $id); - $deferred->resolve( - [ - $request ?? Request::default(), - Response::fromError($e, $request->format ?? RequestFormat::JSON), - ] - ); - - return $deferred->promise(); - } - - /** - * - * @param null|Task $task - * @param null|TimerInterface $timer - * @param string $requestId - * @return void - * @throws RuntimeException - */ - public static function handleTaskFinished(?Task $task, ?TimerInterface $timer, string $requestId): void { - // task is finished, we can remove it from the pool - if (isset($task)) { - TaskPool::remove($task); - } - - if ($timer) { - Loop::cancelTimer($timer); - } - // Check if runtime is expired and we need to create one - // We do this just because we still do not know the reason of memory leak - // When after many request of one type of query we switch to another one - // that makes instant memory overflow - // Return runtime back to pool - if (static::$runtimes['blocked'][$requestId][0] > static::RUNTIME_LIFETIME) { - static::$runtimes['blocked'][$requestId][1]->kill(); - unset(static::$runtimes['blocked'][$requestId]); - static::$runtimes['blocked'][$requestId] = [0, Task::createRuntime()]; + $response = Response::fromError($e, $request->format ?? RequestFormat::JSON); } - array_unshift(static::$runtimes['available'], static::$runtimes['blocked'][$requestId]); - unset(static::$runtimes['blocked'][$requestId]); + return $response; } } diff --git a/src/Network/Server.php b/src/Network/Server.php index f69a9c84..58a2eb7f 100644 --- a/src/Network/Server.php +++ b/src/Network/Server.php @@ -12,59 +12,46 @@ namespace Manticoresearch\Buddy\Base\Network; use Exception; -use Manticoresearch\Buddy\Base\Lib\MetricThread; -use Manticoresearch\Buddy\Base\Network\EventHandler; use Manticoresearch\Buddy\Core\Network\Response; use Manticoresearch\Buddy\Core\Tool\Buddy; -use React\EventLoop\Loop; -use React\Http\HttpServer; -use React\Http\Middleware\RequestBodyBufferMiddleware; -use React\Http\Middleware\RequestBodyParserMiddleware; -use React\Http\Middleware\StreamingRequestMiddleware; -use React\Socket\ConnectionInterface; -use React\Socket\SocketServer; +use Swoole\Http\Server as SwooleServer; +use Swoole\Process; +use Swoole\Timer; +use Throwable; final class Server { - /** - * Default config for initializing the socket - */ - const SOCKET_CONFIG = [ - 'tcp' => [ - 'backlog' => 200, - 'so_reuseport' => true, - 'ipv4_v4only' => true, - // 'local_cert' => 'server.pem', - ], - ]; - - /** @var SocketServer */ - protected SocketServer $socket; + /** @var SwooleServer */ + protected SwooleServer $socket; /** @var array */ protected array $handlers = []; - /** @var array{server:array,client:array} */ - protected array $ticks = [ - 'server' => [], - 'client' => [], - ]; + /** @var array */ + protected array $ticks = []; /** @var array */ protected array $onstart = []; + /** @var array */ + protected array $beforeStart = []; + /** @var string $ip */ protected string $ip; + /** @var int $pid */ + protected int $pid; + + /** @var int $ppid */ + protected int $ppid; + /** * @param array $config + * @return void */ - public function __construct( - array $config = [], - ) { - $this->socket = new SocketServer( - '127.0.0.1:0', - array_replace(static::SOCKET_CONFIG, $config) - ); + public function __construct(array $config = []) { + $this->socket = new SwooleServer('127.0.0.1', 0); + $this->socket->set($config); + $this->ppid = posix_getppid(); } /** @@ -95,15 +82,11 @@ public function addHandler(string $event, callable $fn): static { * * @param callable $fn * @param int $period - * @param string $type * One of server or client, todo: move to enum implementation * @return static */ - public function addTicker(callable $fn, int $period = 5, string $type = 'server'): static { - // We should enum, but for now string is ok - assert($type === 'server' || $type === 'client'); - - $this->ticks[$type][] = [$fn, $period]; + public function addTicker(callable $fn, int $period = 5): static { + $this->ticks[] = [$fn, $period]; return $this; } @@ -117,6 +100,47 @@ public function onStart(callable $fn): static { return $this; } + /** + * Add function to be called before we starting server + * @param callable $fn + * @return static + */ + public function beforeStart(callable $fn): static { + $this->beforeStart[] = $fn; + return $this; + } + + /** + * Add process to the server loop + * @param Process $process + * @return static + */ + public function addProcess(Process $process): static { + $this->socket->addProcess($process); + + $this->onStart( + static function () use ($process) { + swoole_event_add( + $process->pipe, function ($pipe) use ($process) { + try { + $output = $process->read(); + if (!$output) { + swoole_event_del($pipe); + $process->wait(); + } + + if (is_string($output)) { + echo $output; + } + } catch (Throwable) { + } + } + ); + } + ); + return $this; + } + /** * Finally start the server and accept connections * @@ -124,56 +148,85 @@ public function onStart(callable $fn): static { */ public function start(): static { // This is must be first! Because its important - echo 'Buddy v' . Buddy::getVersion() - . ' started ' . str_replace('tcp://', '', (string)$this->socket->getAddress()) - . PHP_EOL; - - // Initialize runtimes that we will use for request handling - EventHandler::init(); - - // Process first functions to run on start - foreach ($this->onstart as $fn) { - $fn(); - } - - // First add all ticks to run periodically - foreach ($this->ticks['server'] as [$fn, $period]) { - Loop::addPeriodicTimer($period, $this->wrapFn($fn)); - } + $version = Buddy::getVersion(); + $listen = "{$this->socket->host}:{$this->socket->port}"; + echo "Buddy v{$version} started {$listen}" . PHP_EOL; // Handle connections and subscribe to all events in handlers // Create the socket for future use if (!isset($this->handlers['request'])) { throw new Exception('You are missing "request" handler to handle requests'); } - $http = new HttpServer( - new StreamingRequestMiddleware(), - // new LimitConcurrentRequestsMiddleware(128), // 128 concurrent buffering handlers - new RequestBodyBufferMiddleware(return_bytes(ini_get('post_max_size') ?: '64k')), // 8 MiB per request - new RequestBodyParserMiddleware(), - $this->handlers['request'] - ); - unset($this->handlers['request']); - $this->socket->on( - 'connection', function (ConnectionInterface $connection) { - Buddy::debug('New connection from ' . $connection->getRemoteAddress()); + foreach ($this->beforeStart as $fn) { + $fn(); + } - // First add all ticks to run periodically - foreach ($this->ticks['client'] as [$fn, $period]) { - Loop::addPeriodicTimer($period, $this->wrapFn($fn, $connection)); + // Do custom initialization on start + $this->socket->on( + 'start', function () { + $this->pid = $this->socket->master_pid; + pcntl_async_signals(true); + pcntl_signal(SIGTERM, $this->stop(...)); + pcntl_signal(SIGINT, $this->stop(...)); + + // Process first functions to run on start + foreach ($this->onstart as $fn) { + $fn(); } + } + ); + - foreach ($this->handlers as $event => $fn) { - $connection->on($event, $this->wrapFn($fn, $connection)); + $this->socket->on( + // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed, SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + 'WorkerStart', function (SwooleServer $server, int $workerId) { + if ($workerId !== 0) { + return; + } + Timer::tick( + 5000, function () { + if (Process::kill($this->ppid, 0)) { + return; + } + + Buddy::debug('Parrent proccess died, exiting…'); + $this->stop(); + } + ); + + // First add all ticks to run periodically + foreach ($this->ticks as [$fn, $period]) { + Timer::tick( + $period * 1000, static function (/*int $timerId*/) use ($fn) { + go($fn); + } + ); } } ); - $http->listen($this->socket); + // Add all other handlers + foreach ($this->handlers as $event => $fn) { + $this->socket->on($event, $fn); + } + + $this->socket->start(); return $this; } + /** + * Run task in worker, we do blocking here, but actually we detect + * async mode on the level of our Task + * @param string $requestId + * @param string $payload + * @return Response + */ + public function process(string $requestId, string $payload): Response { + // @phpstan-ignore-next-line + return $this->socket->taskwait([$requestId, $payload], 0); + } + /** * Stop running server * @@ -181,49 +234,12 @@ public function start(): static { * @return static */ public function stop($exit = true): static { - if (is_telemetry_enabled()) { - MetricThread::destroy(); - } - EventHandler::destroy(); - $this->socket->close(); - Loop::stop(); + echo 'stop'; + Timer::clearAll(); + $this->socket->stop(); if ($exit) { exit(0); } return $this; } - - /** - * Little helper to help us to wrap event handler into function - * that will do responses to current connectsion whe we have it - * and also support multiple responses at once - * - * @param callable $fn - * @param ?ConnectionInterface $connection - * @return callable - */ - protected function wrapFn(callable $fn, ?ConnectionInterface $connection = null): callable { - return function (...$args) use ($fn, $connection) { - $result = $fn(...$args); - - if (!$connection) { - return; - } - - if (is_a($result, Response::class)) { - return $connection->write((string)$result); - } - - if (!is_array($result)) { - return; - } - - foreach ($result as $response) { - if (!is_a($response, Response::class)) { - continue; - } - $connection->write((string)$response); - } - }; - } } diff --git a/src/Sharding/Cluster.php b/src/Sharding/Cluster.php index 346bae7b..36094194 100644 --- a/src/Sharding/Cluster.php +++ b/src/Sharding/Cluster.php @@ -168,7 +168,7 @@ public function isActive(): bool { ->sendRequest("SHOW STATUS LIKE 'cluster_{$this->name}_status'") ->getResult(); /** @var array{0:array{data:array{0?:array{Value:string}}}} $res */ - $status = $res[0]['data'][0]['Value'] ?? ''; + $status = $res[0]['data'][0]['Value'] ?? 'primary'; return $status === 'primary'; } diff --git a/src/Sharding/Operator.php b/src/Sharding/Operator.php index 463ff541..dc74b587 100644 --- a/src/Sharding/Operator.php +++ b/src/Sharding/Operator.php @@ -158,7 +158,7 @@ protected function becomeMaster(): static { * @return bool */ public function hasSharding(): bool { - $hasSharding = !!$this->state->get('master'); + $hasSharding = $this->state->isActive(); // If sharding is active and still no cluster // Detect and set it from the state if ($hasSharding && !isset($this->cluster)) { diff --git a/src/Sharding/Queue.php b/src/Sharding/Queue.php index 603ff261..acfcfb72 100644 --- a/src/Sharding/Queue.php +++ b/src/Sharding/Queue.php @@ -54,15 +54,15 @@ public function resetWaitForId(): static { */ public function add(string $nodeId, string $query): int { $table = $this->cluster->getSystemTableName($this->table); - $ts = time(); + $mt = (int)(microtime(true) * 1000); $query = addcslashes($query, "'"); $id = hrtime(true); $this->client->sendRequest( " INSERT INTO {$table} - (`id`, `node`, `query`, `wait_for_id`, `tries`, `status`, `updated_at`) + (`id`, `node`, `query`, `wait_for_id`, `tries`, `status`, `created_at`, `updated_at`, `duration`) VALUES - ($id, '{$nodeId}', '{$query}', $this->waitForId, 0,'created', {$ts}) + ($id, '{$nodeId}', '{$query}', $this->waitForId, 0,'created', {$mt}, {$mt}, 0) " ); return $id; @@ -105,11 +105,12 @@ public function process(Node $node): void { Buddy::debug("Queue query: {$query['query']}"); // TODO: this is a temporary hack, remove when job is done on searchd $this->runMkdir($query['query']); - + $mt = microtime(true); $res = $this->client->sendRequest($query['query'])->getResult(); + $duration = (int)((microtime(true) - $mt) * 1000); Buddy::debug('Queue result: ' . json_encode($res)); $status = empty($res['error']) ? 'processed' : 'error'; - $this->updateStatus($query['id'], $status, $query['tries'] + 1); + $this->updateStatus($query['id'], $status, $query['tries'] + 1, $duration); // When we have error, we stop iterating if ($status === 'error') { Buddy::info("[$node->id] Query error: {$query['query']}"); @@ -156,11 +157,19 @@ protected function dequeue(Node $node): Vector { * @param int $tries * @return static */ - protected function updateStatus(int $id, string $status, int $tries): static { + protected function updateStatus(int $id, string $status, int $tries, int $duration = 0): static { $table = $this->cluster->getSystemTableName($this->table); - $this->client->sendRequest( - "UPDATE {$table} SET `status` = '{$status}', `tries` = '{$tries}' WHERE `id` = {$id}" - ); + $mt = (int)(microtime(true) * 1000); + $update = [ + "`status` = '{$status}'", + "`tries` = {$tries}", + "`updated_at` = {$mt}", + "`duration` = {$duration}", + ]; + + $rows = implode(', ', $update); + $q = "UPDATE {$table} SET {$rows} WHERE `id` = {$id}"; + $this->client->sendRequest($q); return $this; } @@ -181,7 +190,9 @@ public function setup(): void { `wait_for_id` bigint, `tries` int, `status` string, - `updated_at` timestamp + `created_at` bigint, + `updated_at` bigint, + `duration` int )"; $this->client->sendRequest($query); $this->cluster->attachTable($this->table); diff --git a/src/Sharding/State.php b/src/Sharding/State.php index 33eaaa0f..08140845 100644 --- a/src/Sharding/State.php +++ b/src/Sharding/State.php @@ -146,4 +146,12 @@ public function setup(): void { $this->client->sendRequest($query); $this->cluster->attachTable($this->table); } + + /** + * Check if we activated state so we started to shard + * @return bool + */ + public function isActive(): bool { + return $this->client->hasTable($this->table); + } } diff --git a/src/Sharding/Thread.php b/src/Sharding/Thread.php index badeb517..c34feffe 100644 --- a/src/Sharding/Thread.php +++ b/src/Sharding/Thread.php @@ -13,11 +13,10 @@ use Ds\Map; use Ds\Vector; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Tool\Buddy; use Psr\Container\ContainerInterface; +use Swoole\Process as SwooleProcess; use Throwable; -use parallel\Channel; /** * @@ -32,10 +31,10 @@ final class Thread { protected static ContainerInterface $container; /** - * @param Task $task + * @param SwooleProcess $process * @return void */ - public function __construct(protected Task $task) { + public function __construct(public readonly SwooleProcess $process) { } /** @@ -58,7 +57,7 @@ public static function destroy(): void { return; } - static::$instance->task->destroy(); + static::$instance->process->exit(); } /** @@ -86,26 +85,23 @@ public static function instance(): static { * @return self */ // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh - protected static function start(): self { - $task = Task::loopInRuntime( - Task::createRuntime(), - // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter - // phpcs:disable SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter - static function (Channel $ch, string $container) { - $container = unserialize($container); - /** @var ContainerInterface $container */ - - // This fix issue when we get "sh: 1: cd: can't cd to" error - // while running buddy inside directory that are not allowed for us + public static function start(): self { + $process = new SwooleProcess( + static function (SwooleProcess $worker) { chdir(sys_get_temp_dir()); - Process::setContainer($container); + Process::setContainer(static::$container); $ticks = new Vector; try { - start: while ($msg = $ch->recv()) { + start: while ($msg = $worker->read()) { + if (!is_string($msg)) { + throw new \Exception('Incorrect data received'); + } + $msg = unserialize($msg); if (!is_array($msg)) { throw new \Exception('Incorrect data received'); } + [$method, $args] = $msg; Process::$method(...$args); if ($method === 'shard') { @@ -119,9 +115,9 @@ static function (Channel $ch, string $container) { ); } - // Run ticks after ping execution + // Run ticks after ping execution if ($method !== 'ping') { - continue; + continue; } foreach ($ticks as $n => $tick) { @@ -142,23 +138,16 @@ static function (Channel $ch, string $container) { } catch (Throwable $e) { Buddy::debug( "Error while processing sharding: {$e->getMessage()}." - . ' Restarting after 5s' + . ' Restarting after 5s' ); Buddy::debug($e->getTraceAsString()); sleep(5); // <-- add extra protection delay goto start; } - }, [serialize(static::$container)] + }, false, 2 ); - return (new self($task))->run(); - } - - /** - * @return self - */ - public function run(): self { - $this->task->run(); - return $this; + $process->start(); + return new self($process); } /** @@ -170,7 +159,7 @@ public function run(): self { public function execute(string $event, array $args = []): static { $argsJson = json_encode($args); Buddy::debug("Sharding Event: $event $argsJson"); - $this->task->transmit([$event, $args]); + $this->process->write(serialize([$event, $args])); return $this; } } diff --git a/src/init.php b/src/init.php index cc395445..f774268b 100644 --- a/src/init.php +++ b/src/init.php @@ -16,7 +16,6 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Plugin\Pluggable; use Manticoresearch\Buddy\Core\Plugin\TableFormatter; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Tool\Buddy; use Manticoresearch\Buddy\Plugin\Insert\QueryParser\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -51,5 +50,4 @@ MetricThread::setContainer($container); ShardingThread::setContainer($container); -Task::init(__DIR__ . DIRECTORY_SEPARATOR . 'runtime.php'); return $container; diff --git a/src/main.php b/src/main.php index c310ee3b..de6e64c5 100644 --- a/src/main.php +++ b/src/main.php @@ -16,9 +16,7 @@ use Manticoresearch\Buddy\Base\Network\Server; use Manticoresearch\Buddy\Base\Sharding\Thread as ShardingThread; use Manticoresearch\Buddy\Core\Task\Task; -use Manticoresearch\Buddy\Core\Task\TaskPool; use Manticoresearch\Buddy\Core\Tool\Buddy; -use Manticoresearch\Buddy\Core\Tool\Process; // Init autoload first include_once __DIR__ . DIRECTORY_SEPARATOR . 'init.php'; @@ -33,8 +31,44 @@ $initBuffer = ob_get_clean(); putenv("PLUGIN_DIR={$settings->commonPluginDir}"); -$server = Server::create(); -$server->onStart( +/** @var int $threads */ +$threads = (int)(getenv('THREADS', true) ?: swoole_cpu_num()); +$server = Server::create( + [ + 'daemonize' => 0, + 'max_request' => 0, + 'dispatch_mode' => 3, + 'enable_coroutine' => true, + 'task_enable_coroutine' => false, + 'task_max_request' => 0, + 'task_worker_num' => 0, + 'reactor_num' => $threads, + 'worker_num' => max(1, (int)($threads / 4)), + 'enable_reuse_port' => true, + 'input_buffer_size' => 2097152, + 'buffer_output_size' => 32 * 1024 * 1024, // byte in unit + 'tcp_fastopen' => true, + 'max_conn' => $threads * 2, + 'backlog' => 8192, + 'tcp_defer_accept' => 3, + 'open_tcp_keepalive' => false, + 'open_tcp_nodelay' => true, + 'open_http_protocol' => true, + 'open_http2_protocol' => false, + 'open_websocket_protocol' => false, + 'open_mqtt_protocol' => false, + 'reload_async' => false, + 'http_parse_post' => false, + 'http_parse_cookie' => false, + 'upload_tmp_dir' => '/tmp', + 'http_compression' => true, + 'http_compression_level' => 5, + 'compression_min_length' => 20, + 'open_cpu_affinity' => false, + 'max_wait_time' => 5, + ] +); +$server->beforeStart( static function () use ($initBuffer) { echo $initBuffer; $settings = QueryProcessor::getSettings(); @@ -51,6 +85,8 @@ static function () use ($initBuffer) { ) ->onStart( static function () { + // Hack to fix issue with cut the output from manticore daemon + usleep(20000); buddy_metric('invocation', 1); $settings = QueryProcessor::getSettings(); $crashDetector = new CrashDetector($settings); @@ -69,13 +105,23 @@ static function () { ini_set('post_max_size', $settings->maxAllowedPacket); } ) - ->onStart(ShardingThread::instance(...)) + ->beforeStart( + static function () use ($server) { + $process = ShardingThread::instance()->process; + $server->addProcess($process); + } + ) + ->beforeStart( + static function () use ($server) { + $process = MetricThread::instance()->process; + $server->addProcess($process); + } + ) ->addHandler('request', EventHandler::request(...)) - ->addHandler('error', EventHandler::error(...)) ->addTicker( static function () { ShardingThread::instance()->execute('ping', []); - }, 1, 'server' + }, 1 ) ->addTicker( static function () { @@ -83,23 +129,7 @@ static function () { $formatted = number_format($memory, 3).'K'; Buddy::debug("memory usage: {$formatted}"); }, 60 - ) - ->addTicker( - static function () { - $taskCount = TaskPool::getCount(); - Buddy::debug("running {$taskCount} tasks"); - }, 60 - ) - ->addTicker( - static function () use ($server) { - if (!EventHandler::shouldExit()) { - return; - } - - $server->stop(); - }, 1 - ) - ->addTicker(EventHandler::clientCheckTickerFn(Process::getParentPid()), 5, 'server'); + ); if (is_telemetry_enabled()) { $server->addTicker( @@ -109,14 +139,8 @@ static function () { 'checkAndSnapshot', [(int)(getenv('TELEMETRY_PERIOD', true) ?: 300)] ); - }, 10, 'server' + }, 10 ); - register_shutdown_function(MetricThread::destroy(...)); } -register_shutdown_function(ShardingThread::destroy(...)); - -// Shutdown functions MUST be registered here only -register_shutdown_function(EventHandler::destroy(...)); - $server->start(); diff --git a/test/Buddy/functional/MetricThreadTest.php b/test/Buddy/functional/MetricThreadTest.php index b8f893e1..996ce82b 100644 --- a/test/Buddy/functional/MetricThreadTest.php +++ b/test/Buddy/functional/MetricThreadTest.php @@ -28,7 +28,8 @@ public static function setUpBeforeClass(): void { public function testMetricThreadPrintDebugMessages(): void { sleep(11); system('echo "127.0.0.1 telemetry.manticoresearch.com" >> /etc/hosts'); - $labels = (string)system('tail -n 100 ' . static::SEARCHD_LOG_PATH . ' | grep labels:'); + echo static::SEARCHD_LOG_PATH; + $labels = (string)system('grep labels: ' . static::SEARCHD_LOG_PATH); $this->assertStringContainsString('"collector":"buddy"', $labels); $this->assertStringContainsString('"buddy_version"', $labels); $this->assertStringContainsString('"manticore_version"', $labels); @@ -36,7 +37,7 @@ public function testMetricThreadPrintDebugMessages(): void { $this->assertStringContainsString('"manticore_binlog_enabled"', $labels); $this->assertStringContainsString('"manticore_secondary_indexes_enabled"', $labels); - $metrics = (string)system('tail -n 100 ' . static::SEARCHD_LOG_PATH . ' | grep metrics:'); + $metrics = (string)system('grep metrics: ' . static::SEARCHD_LOG_PATH); $this->assertStringContainsString('"uptime"', $metrics); $this->assertStringContainsString('"command_search"', $metrics); $this->assertStringContainsString('"command_excerpt"', $metrics); @@ -59,7 +60,7 @@ public function testMetricThreadPrintDebugMessages(): void { $this->assertStringContainsString('"workers_total"', $metrics); $output = []; - exec('tail -n 100 ' . static::SEARCHD_LOG_PATH . ' | grep metric:', $output); + exec('grep metric: ' . static::SEARCHD_LOG_PATH, $output); $executes = implode(PHP_EOL, $output); $this->assertStringContainsString('metric: add ["invocation",1]', $executes); $this->assertStringContainsString('metric: checkAndSnapshot', $executes); diff --git a/test/Buddy/functional/ProcessKillTest.php b/test/Buddy/functional/ProcessKillTest.php index ff198fd2..b6ffd81e 100644 --- a/test/Buddy/functional/ProcessKillTest.php +++ b/test/Buddy/functional/ProcessKillTest.php @@ -9,11 +9,11 @@ program; if you did not, you can find it at http://www.gnu.org/ */ -use Manticoresearch\Buddy\Core\Tool\Process; use Manticoresearch\BuddyTest\Trait\TestFunctionalTrait; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase; use SebastianBergmann\RecursionContext\InvalidArgumentException; +use Swoole\Process; final class ProcessKillTest extends TestCase { @@ -42,14 +42,15 @@ public function tearDown(): void { * @throws ExpectationFailedException */ public function testBuddyStopsOnManticoreSigKill(): void { - $this->assertEquals(true, Process::exists(self::$manticorePid)); - $this->assertEquals(true, Process::exists(self::$buddyPid)); + $this->assertEquals(true, Process::kill(self::$manticorePid, 0)); + $this->assertEquals(true, Process::kill(self::$buddyPid, 0)); system('kill -9 ' . self::$manticorePid); sleep(1); - $this->assertEquals(false, Process::exists(self::$manticorePid)); - sleep(5); // We have 5 sec tick when we check that no parrent for buddy - $this->assertEquals(false, Process::exists(self::$buddyPid)); + $this->assertEquals(false, Process::kill(self::$manticorePid, 0)); + // We use more, cuz it takes time to shut down all threads + sleep(10); // We have 5 sec tick when we check that no parrent for buddy + $this->assertEquals(false, Process::kill(self::$buddyPid, 0)); } /** @@ -59,14 +60,14 @@ public function testBuddyStopsOnManticoreSigKill(): void { * @throws ExpectationFailedException */ public function testBuddyStopsOnManticoreSigInt(): void { - $this->assertEquals(true, Process::exists(self::$manticorePid)); - $this->assertEquals(true, Process::exists(self::$buddyPid)); + $this->assertEquals(true, Process::kill(self::$manticorePid, 0)); + $this->assertEquals(true, Process::kill(self::$buddyPid, 0)); system('kill -s INT ' . self::$manticorePid); sleep(6); // Give some delay to finish jobs and flush to disk - $this->assertEquals(false, Process::exists(self::$manticorePid)); - $this->assertEquals(false, Process::exists(self::$buddyPid)); + $this->assertEquals(false, Process::kill(self::$manticorePid, 0)); + $this->assertEquals(false, Process::kill(self::$buddyPid, 0)); } /** @@ -76,14 +77,14 @@ public function testBuddyStopsOnManticoreSigInt(): void { * @throws ExpectationFailedException */ public function testBuddyStopsOnManticoreSigTerm(): void { - $this->assertEquals(true, Process::exists(self::$manticorePid)); - $this->assertEquals(true, Process::exists(self::$buddyPid)); + $this->assertEquals(true, Process::kill(self::$manticorePid, 0)); + $this->assertEquals(true, Process::kill(self::$buddyPid, 0)); system('kill -s TERM ' . self::$manticorePid); sleep(5); // Give some delay to finish jobs and flush to disk - $this->assertEquals(false, Process::exists(self::$manticorePid)); - $this->assertEquals(false, Process::exists(self::$buddyPid)); + $this->assertEquals(false, Process::kill(self::$manticorePid, 0)); + $this->assertEquals(false, Process::kill(self::$buddyPid, 0)); } /** @@ -93,18 +94,18 @@ public function testBuddyStopsOnManticoreSigTerm(): void { * @throws ExpectationFailedException */ public function testbuddyRestartedByManticoreOnKill(): void { - $this->assertEquals(true, Process::exists(self::$manticorePid)); - $this->assertEquals(true, Process::exists(self::$buddyPid)); + $this->assertEquals(true, Process::kill(self::$manticorePid, 0)); + $this->assertEquals(true, Process::kill(self::$buddyPid, 0)); // Kill buddy and check that its dead system('kill -9 ' . self::$buddyPid); sleep(1); // Slight delay - $this->assertEquals(false, Process::exists(self::$buddyPid)); + $this->assertEquals(false, Process::kill(self::$buddyPid, 0)); // Wait a bit and check that manticore relaunched buddy with new pid sleep(2); // Wait a bit again and parse new pids $this->loadBuddyPid(); - $this->assertEquals(true, Process::exists(self::$buddyPid)); + $this->assertEquals(true, Process::kill(self::$buddyPid, 0)); } } diff --git a/test/Buddy/src/CliTable/CliTableHandlerTest.php b/test/Buddy/src/CliTable/CliTableHandlerTest.php index 048aee23..fc95ea40 100644 --- a/test/Buddy/src/CliTable/CliTableHandlerTest.php +++ b/test/Buddy/src/CliTable/CliTableHandlerTest.php @@ -15,7 +15,6 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Network\Request; use Manticoresearch\Buddy\Core\Plugin\TableFormatter; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Plugin\Show\Payload; use Manticoresearch\Buddy\Plugin\Show\QueriesHandler as Handler; use Manticoresearch\BuddyTest\Trait\TestHTTPServerTrait; @@ -59,7 +58,7 @@ public function testCliTableOk(): void { $refCls = new ReflectionClass($handler); $refCls->getProperty('manticoreClient')->setValue($handler, $manticoreClient); $refCls->getProperty('tableFormatter')->setValue($handler, $tableFormatter); - $task = $handler->run(Task::createRuntime()); + $task = $handler->run(); $task->wait(); $this->assertEquals(true, $task->isSucceed()); $result = $task->getResult()->getStruct(); diff --git a/test/Buddy/src/InsertQuery/InsertQueryHandlerTest.php b/test/Buddy/src/InsertQuery/InsertQueryHandlerTest.php index 4bc1067d..460147b5 100644 --- a/test/Buddy/src/InsertQuery/InsertQueryHandlerTest.php +++ b/test/Buddy/src/InsertQuery/InsertQueryHandlerTest.php @@ -18,7 +18,6 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\Settings as ManticoreSettings; use Manticoresearch\Buddy\Core\Network\Request; use Manticoresearch\Buddy\Core\Network\Response; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Plugin\Insert\Handler; use Manticoresearch\Buddy\Plugin\Insert\Payload; use Manticoresearch\BuddyTest\Trait\TestHTTPServerTrait; @@ -142,8 +141,7 @@ protected function runTask(Request $networkRequest, string $serverUrl, string $r $handler = new Handler($payload); $handler->setManticoreClient($manticoreClient); ob_flush(); - $runtime = Task::createRuntime(); - $task = $handler->run($runtime); + $task = $handler->run(); $task->wait(); $this->assertEquals(true, $task->isSucceed()); diff --git a/test/Buddy/src/Lib/QueryProcessorTest.php b/test/Buddy/src/Lib/QueryProcessorTest.php index 286b2a78..d014fffc 100644 --- a/test/Buddy/src/Lib/QueryProcessorTest.php +++ b/test/Buddy/src/Lib/QueryProcessorTest.php @@ -17,7 +17,6 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\RequestFormat; use Manticoresearch\Buddy\Core\ManticoreSearch\Settings as ManticoreSettings; use Manticoresearch\Buddy\Core\Network\Request; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Plugin\Backup\Handler as BackupHandler; use Manticoresearch\Buddy\Plugin\Backup\Payload as BackupPayload; use Manticoresearch\Buddy\Plugin\Insert\Error\AutoSchemaDisabledError; @@ -111,7 +110,7 @@ public function testNotAllowedCommandProcessFail(): void { $refCls = new ReflectionClass(QueryProcessor::class); $refCls->setStaticPropertyValue('settings', static::getSettings(['searchd.auto_schema' => '0'])); $this->expectException(AutoSchemaDisabledError::class); - QueryProcessor::process($request)->run(Task::createRuntime()); + QueryProcessor::process($request)->run(); } /** diff --git a/test/Buddy/src/Network/ServerTest.php b/test/Buddy/src/Network/ServerTest.php index 02f067e3..ccb65406 100644 --- a/test/Buddy/src/Network/ServerTest.php +++ b/test/Buddy/src/Network/ServerTest.php @@ -104,7 +104,7 @@ public function testServerOutput(): void { // ->addTicker( // static function () use ($testFilepath) { // file_put_contents($testFilepath, 'Ok'); - // }, 1, 'server' + // }, 1 // ); // try { @@ -146,7 +146,7 @@ protected function serverTestHelper(string $testTarget): void { $server->addHandler('request', EventHandler::request(...)); switch ($testTarget) { case 'ticker': - $server->addTicker($fn, 1, 'client'); + $server->addTicker($fn, 1); break; case 'handler': $server->addHandler('close', $fn); diff --git a/test/Buddy/src/ShowQueries/ExecutorTest.php b/test/Buddy/src/ShowQueries/ExecutorTest.php index d574df0c..be492e42 100644 --- a/test/Buddy/src/ShowQueries/ExecutorTest.php +++ b/test/Buddy/src/ShowQueries/ExecutorTest.php @@ -15,7 +15,6 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Network\Request as NetRequest; use Manticoresearch\Buddy\Core\Plugin\TableFormatter; -use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Plugin\Show\Payload; use Manticoresearch\Buddy\Plugin\Show\QueriesHandler as Handler; use Manticoresearch\BuddyTest\Trait\TestHTTPServerTrait; @@ -60,7 +59,7 @@ public function testShowQueriesExecutesProperly(): void { $handler = new Handler($payload); $handler->setManticoreClient($manticoreClient); $handler->setTableFormatter(new TableFormatter()); - $task = $handler->run(Task::createRuntime()); + $task = $handler->run(); $task->wait(); $this->assertEquals(true, $task->isSucceed()); $result = $task->getResult()->getStruct(); diff --git a/test/src/Trait/TestFunctionalTrait.php b/test/src/Trait/TestFunctionalTrait.php index 29eb3554..c795a5ed 100644 --- a/test/src/Trait/TestFunctionalTrait.php +++ b/test/src/Trait/TestFunctionalTrait.php @@ -70,10 +70,9 @@ public static function setUpBeforeClass(): void { system('searchd --config ' . static::$manticoreConfigFilePath); self::$manticorePid = (int)trim((string)file_get_contents('/var/run/manticore-test/searchd.pid')); sleep(5); // <- give 5 secs to protect from any kind of lags - self::loadBuddyPid(); - $buddyPid = self::$buddyPid; - static::$listenBuddyPort = (int)system("ss -nlp | grep 'pid={$buddyPid},' | cut -d: -f2 | cut -d' ' -f1"); + static::$listenBuddyPort = (int)system("ss -nlp | grep 'manticore-execu' | cut -d: -f2 | cut -d' ' -f1"); + static::loadBuddyPid(); // Clean up all tables and run fresh instance $output = static::runSqlQuery('show tables'); @@ -97,16 +96,9 @@ public static function setUpBeforeClass(): void { */ public static function tearDownAfterClass(): void { system('pgrep -f searchd | xargs kill -9'); - // echo "Waiting searchd to stop…\n"; - // while(shell_exec('pgrep -f searchd')) { - // echo '.'; - // sleep(1); - // } - // echo "\n"; - - // To be sure run again kills for each pid - system('kill -9 ' . self::$manticorePid . ' 2> /dev/null'); - system('kill -9 ' . self::$buddyPid . ' 2> /dev/null'); + system('pgrep -f manticore-executor | xargs kill -9 2> /dev/null'); + // system('kill -9 ' . self::$manticorePid . ' 2> /dev/null'); + // system('kill -9 ' . self::$buddyPid . ' 2> /dev/null'); } /** @@ -427,15 +419,10 @@ protected static function updateManticoreConf($conf): void { } /** - * Helper that allows us to reload fresh pid for relaunched - * Buddy process by the Manticore + * Helper to load Buddy pid * @return void */ protected static function loadBuddyPid(): void { - $buddyPid = (int)trim(system('pgrep -P ' . self::$manticorePid) ?: ''); - if (!$buddyPid) { - throw new Exception('Failed to find Buddy pid for ' . self::$manticorePid); - } - self::$buddyPid = $buddyPid; + static::$buddyPid = (int)shell_exec('pgrep -f manticore-executor | sort | head -n1'); } }