From 0ac7842a017fe25dff62090ad4f5a95b0675fdc4 Mon Sep 17 00:00:00 2001 From: Mateusz Charytoniuk <mateusz.charytoniuk@protonmail.com> Date: Fri, 22 Mar 2024 00:16:23 +0100 Subject: [PATCH] feat: observable tasks timeout iterator --- composer.json | 3 +- composer.lock | 592 ++++++++++-------- psalm.xml | 4 + src/Attribute/BuildsPDOPoolConnection.php | 19 - src/CurlErrorMessage.php | 22 + src/CurlException.php | 6 +- src/DatabaseConnectionPoolRepository.php | 1 + src/LlamaCppClient.php | 52 +- src/ObservableTask.php | 27 +- src/ObservableTaskInterface.php | 4 +- src/ObservableTaskTable.php | 46 +- ...eTaskTableSlotStatusUpdateIteratorTest.php | 25 +- src/ObservableTaskTableTest.php | 21 +- src/ObservableTaskTimeoutIterator.php | 91 +++ src/PDOPool.php | 106 ---- src/PDOPoolConnectionBuilder.php | 7 - src/PDOPoolConnectionBuilderCollection.php | 45 -- src/PDOPoolConnectionBuilderInterface.php | 12 - ...tabaseConnectionPoolRepositoryProvider.php | 5 +- ...oolConnectionBuilderCollectionProvider.php | 53 -- src/SwooleCoroutineHelper.php | 4 +- src/SwooleServer.php | 12 +- src/SwooleTableAvailableRowsPool.php | 26 +- src/SwooleTimeout.php | 28 + src/SwooleTimeoutScheduled.php | 47 ++ src/SwooleTimeoutScheduler.php | 23 + src/SwooleTimeoutTest.php | 55 ++ src/TwigResonanceFilesystemLoader.php | 29 + .../LlamaCppSubjectActionPromptResponder.php | 44 +- src/views/observable_tasks_dashboard.twig | 24 + 30 files changed, 818 insertions(+), 615 deletions(-) delete mode 100644 src/Attribute/BuildsPDOPoolConnection.php create mode 100644 src/CurlErrorMessage.php create mode 100644 src/ObservableTaskTimeoutIterator.php delete mode 100644 src/PDOPool.php delete mode 100644 src/PDOPoolConnectionBuilder.php delete mode 100644 src/PDOPoolConnectionBuilderCollection.php delete mode 100644 src/PDOPoolConnectionBuilderInterface.php delete mode 100644 src/SingletonProvider/PDOPoolConnectionBuilderCollectionProvider.php create mode 100644 src/SwooleTimeout.php create mode 100644 src/SwooleTimeoutScheduled.php create mode 100644 src/SwooleTimeoutScheduler.php create mode 100644 src/SwooleTimeoutTest.php create mode 100644 src/TwigResonanceFilesystemLoader.php create mode 100644 src/views/observable_tasks_dashboard.twig diff --git a/composer.json b/composer.json index f68dffeb..31379541 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,8 @@ }, "require-dev": { "phpunit/phpunit": "^11.0", - "swoole/ide-helper": "^5.1" + "swoole/ide-helper": "^5.1", + "symfony/var-dumper": "^7.0" }, "suggest": { "ext-ds": "For better memory management", diff --git a/composer.lock b/composer.lock index 49a1edd9..81efe8ae 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": "fef9182645967627d0f98ca0760efe74", + "content-hash": "a4aa534fc5b3b730ea6124cfcff9b223", "packages": [ { "name": "amphp/amp", @@ -310,16 +310,16 @@ }, { "name": "amphp/process", - "version": "v1.1.4", + "version": "v1.1.5", "source": { "type": "git", "url": "https://github.com/amphp/process.git", - "reference": "76e9495fd6818b43a20167cb11d8a67f7744ee0f" + "reference": "04b4517bbfe436ab822b853d511165dafbfe115a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/process/zipball/76e9495fd6818b43a20167cb11d8a67f7744ee0f", - "reference": "76e9495fd6818b43a20167cb11d8a67f7744ee0f", + "url": "https://api.github.com/repos/amphp/process/zipball/04b4517bbfe436ab822b853d511165dafbfe115a", + "reference": "04b4517bbfe436ab822b853d511165dafbfe115a", "shasum": "" }, "require": { @@ -363,7 +363,7 @@ "homepage": "https://github.com/amphp/process", "support": { "issues": "https://github.com/amphp/process/issues", - "source": "https://github.com/amphp/process/tree/v1.1.4" + "source": "https://github.com/amphp/process/tree/v1.1.5" }, "funding": [ { @@ -371,7 +371,7 @@ "type": "github" } ], - "time": "2022-07-06T23:50:12+00:00" + "time": "2024-02-24T21:06:11+00:00" }, { "name": "amphp/serialization", @@ -564,16 +564,16 @@ }, { "name": "bref/bref", - "version": "2.1.15", + "version": "2.1.16", "source": { "type": "git", "url": "https://github.com/brefphp/bref.git", - "reference": "ffdcd2667ac6eaeab88f82a2d5949fa5697f7a24" + "reference": "b90057f076e95d8ce6d122c4da2e6c6d47dd920a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brefphp/bref/zipball/ffdcd2667ac6eaeab88f82a2d5949fa5697f7a24", - "reference": "ffdcd2667ac6eaeab88f82a2d5949fa5697f7a24", + "url": "https://api.github.com/repos/brefphp/bref/zipball/b90057f076e95d8ce6d122c4da2e6c6d47dd920a", + "reference": "b90057f076e95d8ce6d122c4da2e6c6d47dd920a", "shasum": "" }, "require": { @@ -627,7 +627,7 @@ ], "support": { "issues": "https://github.com/brefphp/bref/issues", - "source": "https://github.com/brefphp/bref/tree/2.1.15" + "source": "https://github.com/brefphp/bref/tree/2.1.16" }, "funding": [ { @@ -639,7 +639,7 @@ "type": "github" } ], - "time": "2024-02-16T14:07:58+00:00" + "time": "2024-03-15T10:23:05+00:00" }, { "name": "crwlr/query-string", @@ -1007,16 +1007,16 @@ }, { "name": "doctrine/collections", - "version": "2.1.4", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "72328a11443a0de79967104ad36ba7b30bded134" + "reference": "420480fc085bc65f3c956af13abe8e7546f94813" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/72328a11443a0de79967104ad36ba7b30bded134", - "reference": "72328a11443a0de79967104ad36ba7b30bded134", + "url": "https://api.github.com/repos/doctrine/collections/zipball/420480fc085bc65f3c956af13abe8e7546f94813", + "reference": "420480fc085bc65f3c956af13abe8e7546f94813", "shasum": "" }, "require": { @@ -1028,7 +1028,7 @@ "ext-json": "*", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.11" }, "type": "library", @@ -1073,7 +1073,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.1.4" + "source": "https://github.com/doctrine/collections/tree/2.2.1" }, "funding": [ { @@ -1089,20 +1089,20 @@ "type": "tidelift" } ], - "time": "2023-10-03T09:22:33+00:00" + "time": "2024-03-05T22:28:45+00:00" }, { "name": "doctrine/dbal", - "version": "3.8.2", + "version": "3.8.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "a19a1d05ca211f41089dffcc387733a6875196cb" + "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/a19a1d05ca211f41089dffcc387733a6875196cb", - "reference": "a19a1d05ca211f41089dffcc387733a6875196cb", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/db922ba9436b7b18a23d1653a0b41ff2369ca41c", + "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c", "shasum": "" }, "require": { @@ -1118,12 +1118,12 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.57", + "phpstan/phpstan": "1.10.58", "phpstan/phpstan-strict-rules": "^1.5", "phpunit/phpunit": "9.6.16", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.8.1", + "squizlabs/php_codesniffer": "3.9.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" @@ -1186,7 +1186,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.2" + "source": "https://github.com/doctrine/dbal/tree/3.8.3" }, "funding": [ { @@ -1202,7 +1202,7 @@ "type": "tidelift" } ], - "time": "2024-02-12T18:36:36+00:00" + "time": "2024-03-03T15:55:06+00:00" }, { "name": "doctrine/deprecations", @@ -1582,16 +1582,16 @@ }, { "name": "doctrine/migrations", - "version": "3.7.2", + "version": "3.7.4", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a" + "reference": "954e0a314c2f0eb9fb418210445111747de254a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/47af29eef49f29ebee545947e8b2a4b3be318c8a", - "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/954e0a314c2f0eb9fb418210445111747de254a6", + "reference": "954e0a314c2f0eb9fb418210445111747de254a6", "shasum": "" }, "require": { @@ -1664,7 +1664,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.7.2" + "source": "https://github.com/doctrine/migrations/tree/3.7.4" }, "funding": [ { @@ -1680,32 +1680,32 @@ "type": "tidelift" } ], - "time": "2023-12-05T11:35:05+00:00" + "time": "2024-03-06T13:41:11+00:00" }, { "name": "doctrine/orm", - "version": "3.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "5b8b5f28f535e1f03b54dcfb0427407ed92f5b72" + "reference": "716fc97b70cf8116f74eaa0588eef51420874bf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/5b8b5f28f535e1f03b54dcfb0427407ed92f5b72", - "reference": "5b8b5f28f535e1f03b54dcfb0427407ed92f5b72", + "url": "https://api.github.com/repos/doctrine/orm/zipball/716fc97b70cf8116f74eaa0588eef51420874bf9", + "reference": "716fc97b70cf8116f74eaa0588eef51420874bf9", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/collections": "^2.1", - "doctrine/dbal": "^3.6 || ^4", + "doctrine/collections": "^2.2", + "doctrine/dbal": "^3.8.2 || ^4", "doctrine/deprecations": "^0.5.3 || ^1", "doctrine/event-manager": "^1.2 || ^2", "doctrine/inflector": "^1.4 || ^2.0", "doctrine/instantiator": "^1.3 || ^2", "doctrine/lexer": "^3", - "doctrine/persistence": "^3.1.1", + "doctrine/persistence": "^3.3.1", "ext-ctype": "*", "php": "^8.1", "psr/cache": "^1 || ^2 || ^3", @@ -1715,12 +1715,12 @@ "require-dev": { "doctrine/coding-standard": "^12.0", "phpbench/phpbench": "^1.0", - "phpstan/phpstan": "1.10.35", + "phpstan/phpstan": "1.10.59", "phpunit/phpunit": "^10.4.0", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^5.4 || ^6.2 || ^7.0", - "vimeo/psalm": "5.16.0" + "vimeo/psalm": "5.22.2" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1766,22 +1766,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.0.0" + "source": "https://github.com/doctrine/orm/tree/3.1.0" }, - "time": "2024-02-03T16:50:09+00:00" + "time": "2024-03-03T17:45:20+00:00" }, { "name": "doctrine/persistence", - "version": "3.2.0", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603" + "reference": "477da35bd0255e032826f440b94b3e37f2d56f42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/63fee8c33bef740db6730eb2a750cd3da6495603", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/477da35bd0255e032826f440b94b3e37f2d56f42", + "reference": "477da35bd0255e032826f440b94b3e37f2d56f42", "shasum": "" }, "require": { @@ -1850,7 +1850,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.2.0" + "source": "https://github.com/doctrine/persistence/tree/3.3.2" }, "funding": [ { @@ -1866,20 +1866,20 @@ "type": "tidelift" } ], - "time": "2023-05-17T18:32:04+00:00" + "time": "2024-03-12T14:54:36+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.1.3", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5" + "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/25a06c7bf4c6b8218f47928654252863ffc890a5", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a321d114e0a18e6497f8a2cd6f890e000cc17ecc", + "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc", "shasum": "" }, "require": { @@ -1916,9 +1916,9 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.1.3" + "source": "https://github.com/doctrine/sql-formatter/tree/1.2.0" }, - "time": "2022-05-23T21:33:49+00:00" + "time": "2023-08-16T21:49:04+00:00" }, { "name": "dragonmantank/cron-expression", @@ -2111,24 +2111,24 @@ }, { "name": "google/common-protos", - "version": "v3.2.0", + "version": "v4.5.0", "source": { "type": "git", "url": "https://github.com/googleapis/common-protos-php.git", - "reference": "57d4ad36cc48cc0369123042908013ef2a86bb98" + "reference": "dfc232e90823cedca107b56e7371f2e2f35b9427" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/common-protos-php/zipball/57d4ad36cc48cc0369123042908013ef2a86bb98", - "reference": "57d4ad36cc48cc0369123042908013ef2a86bb98", + "url": "https://api.github.com/repos/googleapis/common-protos-php/zipball/dfc232e90823cedca107b56e7371f2e2f35b9427", + "reference": "dfc232e90823cedca107b56e7371f2e2f35b9427", "shasum": "" }, "require": { - "google/protobuf": "^3.6.1" + "google/protobuf": "^3.6.1", + "php": ">=7.4" }, "require-dev": { - "phpunit/phpunit": "^4.8.36||^8.5", - "sami/sami": "*" + "phpunit/phpunit": "^9.0" }, "type": "library", "autoload": { @@ -2157,9 +2157,9 @@ ], "support": { "issues": "https://github.com/googleapis/common-protos-php/issues", - "source": "https://github.com/googleapis/common-protos-php/tree/v3.2.0" + "source": "https://github.com/googleapis/common-protos-php/tree/v4.5.0" }, - "time": "2023-01-12T16:51:46+00:00" + "time": "2023-11-29T21:08:16+00:00" }, { "name": "google/protobuf", @@ -2995,16 +2995,16 @@ }, { "name": "hyperf/engine", - "version": "v2.10.4", + "version": "v2.10.5", "source": { "type": "git", "url": "https://github.com/hyperf/engine.git", - "reference": "34ba1825f5b596c677d027e60ec4e2b75c65d09e" + "reference": "b3e1a025e388815612815a0b08fc4f2439140676" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/engine/zipball/34ba1825f5b596c677d027e60ec4e2b75c65d09e", - "reference": "34ba1825f5b596c677d027e60ec4e2b75c65d09e", + "url": "https://api.github.com/repos/hyperf/engine/zipball/b3e1a025e388815612815a0b08fc4f2439140676", + "reference": "b3e1a025e388815612815a0b08fc4f2439140676", "shasum": "" }, "require": { @@ -3017,11 +3017,11 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.0", "hyperf/guzzle": "^3.0", - "hyperf/http-message": " 3.0.*", + "hyperf/http-message": "^3.0", "mockery/mockery": "^1.5", "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.4", - "swoole/ide-helper": "dev-master" + "swoole/ide-helper": "5.*" }, "suggest": { "ext-sockets": "*", @@ -3059,7 +3059,7 @@ ], "support": { "issues": "https://github.com/hyperf/engine/issues", - "source": "https://github.com/hyperf/engine/tree/v2.10.4" + "source": "https://github.com/hyperf/engine/tree/v2.10.5" }, "funding": [ { @@ -3071,7 +3071,7 @@ "type": "open_collective" } ], - "time": "2023-12-15T07:47:12+00:00" + "time": "2024-03-12T06:06:19+00:00" }, { "name": "hyperf/engine-contract", @@ -3209,20 +3209,20 @@ }, { "name": "hyperf/grpc", - "version": "v3.1.0", + "version": "v3.1.11", "source": { "type": "git", "url": "https://github.com/hyperf/grpc.git", - "reference": "0acecce9c89c3065dfcd750208586adb1ee513bc" + "reference": "63d8c8aac9a9fd7e586aa1298d9928107e6e0e27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/grpc/zipball/0acecce9c89c3065dfcd750208586adb1ee513bc", - "reference": "0acecce9c89c3065dfcd750208586adb1ee513bc", + "url": "https://api.github.com/repos/hyperf/grpc/zipball/63d8c8aac9a9fd7e586aa1298d9928107e6e0e27", + "reference": "63d8c8aac9a9fd7e586aa1298d9928107e6e0e27", "shasum": "" }, "require": { - "google/common-protos": "^3.2", + "google/common-protos": "^3.2 || ^4.4", "google/protobuf": "^3.6.1", "php": ">=8.1" }, @@ -3268,7 +3268,7 @@ "type": "open_collective" } ], - "time": "2023-11-24T03:10:53+00:00" + "time": "2024-02-28T03:13:03+00:00" }, { "name": "hyperf/grpc-client", @@ -3460,16 +3460,16 @@ }, { "name": "hyperf/stringable", - "version": "v3.1.0", + "version": "v3.1.13", "source": { "type": "git", "url": "https://github.com/hyperf/stringable.git", - "reference": "10465337a7bbf528ab28bd84330d795a5b3e06bd" + "reference": "b79f7204c35874a4ea0e917239b74fd230c93e1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/stringable/zipball/10465337a7bbf528ab28bd84330d795a5b3e06bd", - "reference": "10465337a7bbf528ab28bd84330d795a5b3e06bd", + "url": "https://api.github.com/repos/hyperf/stringable/zipball/b79f7204c35874a4ea0e917239b74fd230c93e1f", + "reference": "b79f7204c35874a4ea0e917239b74fd230c93e1f", "shasum": "" }, "require": { @@ -3527,20 +3527,20 @@ "type": "open_collective" } ], - "time": "2023-11-24T03:10:53+00:00" + "time": "2024-03-10T09:19:40+00:00" }, { "name": "hyperf/support", - "version": "v3.1.7", + "version": "v3.1.13", "source": { "type": "git", "url": "https://github.com/hyperf/support.git", - "reference": "5f3bb356632089f92feefb7dd7202c22444404e5" + "reference": "cd5d284d83d0c031be38e3c5d07f6b96b837a42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/support/zipball/5f3bb356632089f92feefb7dd7202c22444404e5", - "reference": "5f3bb356632089f92feefb7dd7202c22444404e5", + "url": "https://api.github.com/repos/hyperf/support/zipball/cd5d284d83d0c031be38e3c5d07f6b96b837a42f", + "reference": "cd5d284d83d0c031be38e3c5d07f6b96b837a42f", "shasum": "" }, "require": { @@ -3597,7 +3597,7 @@ "type": "open_collective" } ], - "time": "2024-01-22T08:45:43+00:00" + "time": "2024-03-13T08:47:07+00:00" }, { "name": "hyperf/tappable", @@ -3662,16 +3662,16 @@ }, { "name": "jean85/pretty-package-versions", - "version": "2.0.5", + "version": "2.0.6", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af" + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af", - "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", "shasum": "" }, "require": { @@ -3679,9 +3679,9 @@ "php": "^7.1|^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.17", + "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^0.12.66", + "phpstan/phpstan": "^1.4", "phpunit/phpunit": "^7.5|^8.5|^9.4", "vimeo/psalm": "^4.3" }, @@ -3715,9 +3715,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" }, - "time": "2021-10-08T21:21:46+00:00" + "time": "2024-03-08T09:58:59+00:00" }, { "name": "lcobucci/clock", @@ -4432,16 +4432,16 @@ }, { "name": "nette/php-generator", - "version": "v4.1.3", + "version": "v4.1.4", "source": { "type": "git", "url": "https://github.com/nette/php-generator.git", - "reference": "08ab9bff22ae34fe4e1d2fe8ba16b3770ea2459f" + "reference": "b135071d8da108445e4df2fc6a75522b23c0237d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/08ab9bff22ae34fe4e1d2fe8ba16b3770ea2459f", - "reference": "08ab9bff22ae34fe4e1d2fe8ba16b3770ea2459f", + "url": "https://api.github.com/repos/nette/php-generator/zipball/b135071d8da108445e4df2fc6a75522b23c0237d", + "reference": "b135071d8da108445e4df2fc6a75522b23c0237d", "shasum": "" }, "require": { @@ -4495,9 +4495,9 @@ ], "support": { "issues": "https://github.com/nette/php-generator/issues", - "source": "https://github.com/nette/php-generator/tree/v4.1.3" + "source": "https://github.com/nette/php-generator/tree/v4.1.4" }, - "time": "2024-01-18T17:44:20+00:00" + "time": "2024-03-07T23:06:26+00:00" }, { "name": "nette/schema", @@ -5463,16 +5463,16 @@ }, { "name": "riverline/multipart-parser", - "version": "2.1.1", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/Riverline/multipart-parser.git", - "reference": "2418bdfc2eab01e39bcffee808b1a365c166292a" + "reference": "7a9f4646db5181516c61b8e0225a343189beedcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Riverline/multipart-parser/zipball/2418bdfc2eab01e39bcffee808b1a365c166292a", - "reference": "2418bdfc2eab01e39bcffee808b1a365c166292a", + "url": "https://api.github.com/repos/Riverline/multipart-parser/zipball/7a9f4646db5181516c61b8e0225a343189beedcd", + "reference": "7a9f4646db5181516c61b8e0225a343189beedcd", "shasum": "" }, "require": { @@ -5513,9 +5513,9 @@ ], "support": { "issues": "https://github.com/Riverline/multipart-parser/issues", - "source": "https://github.com/Riverline/multipart-parser/tree/2.1.1" + "source": "https://github.com/Riverline/multipart-parser/tree/2.1.2" }, - "time": "2023-04-28T18:53:59+00:00" + "time": "2024-03-12T16:46:05+00:00" }, { "name": "rubix/ml", @@ -5680,16 +5680,16 @@ }, { "name": "rubix/tensor", - "version": "3.0.4", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/RubixML/Tensor.git", - "reference": "e1537119c5f1f87eb506852df3b5b7c7e34c452a" + "reference": "9f0ee170319280dcf081984adccefa8b0e6f06b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RubixML/Tensor/zipball/e1537119c5f1f87eb506852df3b5b7c7e34c452a", - "reference": "e1537119c5f1f87eb506852df3b5b7c7e34c452a", + "url": "https://api.github.com/repos/RubixML/Tensor/zipball/9f0ee170319280dcf081984adccefa8b0e6f06b8", + "reference": "9f0ee170319280dcf081984adccefa8b0e6f06b8", "shasum": "" }, "require": { @@ -5779,20 +5779,20 @@ "type": "github" } ], - "time": "2023-09-20T05:03:49+00:00" + "time": "2024-03-15T19:43:50+00:00" }, { "name": "symfony/cache", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "2207eceb2433d74df81232d97439bf508cb9e050" + "reference": "fc822951dd360a593224bb2cef90a087d0dff60f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/2207eceb2433d74df81232d97439bf508cb9e050", - "reference": "2207eceb2433d74df81232d97439bf508cb9e050", + "url": "https://api.github.com/repos/symfony/cache/zipball/fc822951dd360a593224bb2cef90a087d0dff60f", + "reference": "fc822951dd360a593224bb2cef90a087d0dff60f", "shasum": "" }, "require": { @@ -5859,7 +5859,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.0.3" + "source": "https://github.com/symfony/cache/tree/v7.0.4" }, "funding": [ { @@ -5875,7 +5875,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/cache-contracts", @@ -5955,16 +5955,16 @@ }, { "name": "symfony/clock", - "version": "v7.0.3", + "version": "v7.0.5", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "1c680e565dc0044d8ed3baeb57835fcacd9c6aed" + "reference": "8b9d08887353d627d5f6c3bf3373b398b49051c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/1c680e565dc0044d8ed3baeb57835fcacd9c6aed", - "reference": "1c680e565dc0044d8ed3baeb57835fcacd9c6aed", + "url": "https://api.github.com/repos/symfony/clock/zipball/8b9d08887353d627d5f6c3bf3373b398b49051c2", + "reference": "8b9d08887353d627d5f6c3bf3373b398b49051c2", "shasum": "" }, "require": { @@ -6009,7 +6009,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.0.3" + "source": "https://github.com/symfony/clock/tree/v7.0.5" }, "funding": [ { @@ -6025,20 +6025,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-03-02T12:46:12+00:00" }, { "name": "symfony/console", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c5010d50f1ee4b25cfa0201d9915cf1b14071456" + "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c5010d50f1ee4b25cfa0201d9915cf1b14071456", - "reference": "c5010d50f1ee4b25cfa0201d9915cf1b14071456", + "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", + "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", "shasum": "" }, "require": { @@ -6102,7 +6102,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.3" + "source": "https://github.com/symfony/console/tree/v7.0.4" }, "funding": [ { @@ -6118,7 +6118,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6189,16 +6189,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.0.3", + "version": "v7.0.5", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "fbea8d2b5f5c6cf0a2aab882571a047ee9238cb4" + "reference": "e3cf34996df541c62acc1bd5f187aacc18a204d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/fbea8d2b5f5c6cf0a2aab882571a047ee9238cb4", - "reference": "fbea8d2b5f5c6cf0a2aab882571a047ee9238cb4", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/e3cf34996df541c62acc1bd5f187aacc18a204d2", + "reference": "e3cf34996df541c62acc1bd5f187aacc18a204d2", "shasum": "" }, "require": { @@ -6275,7 +6275,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.3" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.5" }, "funding": [ { @@ -6291,7 +6291,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T13:55:15+00:00" + "time": "2024-02-27T12:34:35+00:00" }, { "name": "symfony/event-dispatcher", @@ -6578,16 +6578,16 @@ }, { "name": "symfony/http-client", - "version": "v7.0.3", + "version": "v7.0.5", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "3d2605c07cd14aec294f72f5bf8147702f7a5ada" + "reference": "425f462a59d8030703ee04a9e1c666575ed5db3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/3d2605c07cd14aec294f72f5bf8147702f7a5ada", - "reference": "3d2605c07cd14aec294f72f5bf8147702f7a5ada", + "url": "https://api.github.com/repos/symfony/http-client/zipball/425f462a59d8030703ee04a9e1c666575ed5db3b", + "reference": "425f462a59d8030703ee04a9e1c666575ed5db3b", "shasum": "" }, "require": { @@ -6650,7 +6650,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.0.3" + "source": "https://github.com/symfony/http-client/tree/v7.0.5" }, "funding": [ { @@ -6666,7 +6666,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-03-02T12:46:12+00:00" }, { "name": "symfony/http-client-contracts", @@ -6748,16 +6748,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f24e2568376e98978022fd09ce45e2dd049e67c8" + "reference": "439fdfdd344943254b1ef6278613e79040548045" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f24e2568376e98978022fd09ce45e2dd049e67c8", - "reference": "f24e2568376e98978022fd09ce45e2dd049e67c8", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045", + "reference": "439fdfdd344943254b1ef6278613e79040548045", "shasum": "" }, "require": { @@ -6805,7 +6805,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.0.3" + "source": "https://github.com/symfony/http-foundation/tree/v7.0.4" }, "funding": [ { @@ -6821,20 +6821,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-08T19:22:56+00:00" }, { "name": "symfony/mailer", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "2f71c0f6d62d28784783fdc5477e19dd57065d78" + "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/2f71c0f6d62d28784783fdc5477e19dd57065d78", - "reference": "2f71c0f6d62d28784783fdc5477e19dd57065d78", + "url": "https://api.github.com/repos/symfony/mailer/zipball/72e16d87bf50a3ce195b9470c06bb9d7b816ea85", + "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85", "shasum": "" }, "require": { @@ -6885,7 +6885,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.0.3" + "source": "https://github.com/symfony/mailer/tree/v7.0.4" }, "funding": [ { @@ -6901,20 +6901,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-03T21:34:19+00:00" }, { "name": "symfony/messenger", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "6271373f5dd4cc1750eccb73839d20797bd66072" + "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/6271373f5dd4cc1750eccb73839d20797bd66072", - "reference": "6271373f5dd4cc1750eccb73839d20797bd66072", + "url": "https://api.github.com/repos/symfony/messenger/zipball/804a8997f93313a8f7ed19e8cca3b44fdd18bdec", + "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec", "shasum": "" }, "require": { @@ -6971,7 +6971,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.0.3" + "source": "https://github.com/symfony/messenger/tree/v7.0.4" }, "funding": [ { @@ -6987,7 +6987,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T13:55:15+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/mime", @@ -7941,16 +7941,16 @@ }, { "name": "symfony/process", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "937a195147e0c27b2759ade834169ed006d0bc74" + "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/937a195147e0c27b2759ade834169ed006d0bc74", - "reference": "937a195147e0c27b2759ade834169ed006d0bc74", + "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9", + "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9", "shasum": "" }, "require": { @@ -7982,7 +7982,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.0.3" + "source": "https://github.com/symfony/process/tree/v7.0.4" }, "funding": [ { @@ -7998,20 +7998,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/routing", - "version": "v7.0.3", + "version": "v7.0.5", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "858b26756ffc35a11238b269b484ee3a393a74d3" + "reference": "ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/858b26756ffc35a11238b269b484ee3a393a74d3", - "reference": "858b26756ffc35a11238b269b484ee3a393a74d3", + "url": "https://api.github.com/repos/symfony/routing/zipball/ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19", + "reference": "ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19", "shasum": "" }, "require": { @@ -8063,7 +8063,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.0.3" + "source": "https://github.com/symfony/routing/tree/v7.0.5" }, "funding": [ { @@ -8079,7 +8079,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T13:55:15+00:00" + "time": "2024-02-27T12:34:35+00:00" }, { "name": "symfony/service-contracts", @@ -8227,16 +8227,16 @@ }, { "name": "symfony/string", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "524aac4a280b90a4420d8d6a040718d0586505ac" + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/524aac4a280b90a4420d8d6a040718d0586505ac", - "reference": "524aac4a280b90a4420d8d6a040718d0586505ac", + "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", "shasum": "" }, "require": { @@ -8293,7 +8293,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.3" + "source": "https://github.com/symfony/string/tree/v7.0.4" }, "funding": [ { @@ -8309,7 +8309,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-01T13:17:36+00:00" }, { "name": "symfony/uid", @@ -8387,16 +8387,16 @@ }, { "name": "symfony/var-exporter", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8" + "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", - "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", + "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", "shasum": "" }, "require": { @@ -8441,7 +8441,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.3" + "source": "https://github.com/symfony/var-exporter/tree/v7.0.4" }, "funding": [ { @@ -8457,7 +8457,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-26T10:35:24+00:00" }, { "name": "symfony/yaml", @@ -8953,16 +8953,16 @@ }, { "name": "webonyx/graphql-php", - "version": "v15.9.1", + "version": "v15.11.1", "source": { "type": "git", "url": "https://github.com/webonyx/graphql-php.git", - "reference": "d6c965ecbd78cd5260ebc083978562f8c9409d63" + "reference": "ab4ff2719b101dc3bfc3aaaf800edc21a98c56dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/d6c965ecbd78cd5260ebc083978562f8c9409d63", - "reference": "d6c965ecbd78cd5260ebc083978562f8c9409d63", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/ab4ff2719b101dc3bfc3aaaf800edc21a98c56dc", + "reference": "ab4ff2719b101dc3bfc3aaaf800edc21a98c56dc", "shasum": "" }, "require": { @@ -8975,19 +8975,19 @@ "amphp/http-server": "^2.1", "dms/phpunit-arraysubset-asserts": "dev-master", "ergebnis/composer-normalize": "^2.28", - "friendsofphp/php-cs-fixer": "3.48.0", + "friendsofphp/php-cs-fixer": "3.51.0", "mll-lab/php-cs-fixer-config": "^5", "nyholm/psr7": "^1.5", "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "1.10.57", - "phpstan/phpstan-phpunit": "1.3.15", + "phpstan/phpstan": "1.10.59", + "phpstan/phpstan-phpunit": "1.3.16", "phpstan/phpstan-strict-rules": "1.5.2", "phpunit/phpunit": "^9.5 || ^10", "psr/http-message": "^1 || ^2", "react/http": "^1.6", "react/promise": "^2.0 || ^3.0", - "rector/rector": "^0.19", + "rector/rector": "^1.0", "symfony/polyfill-php81": "^1.23", "symfony/var-exporter": "^5 || ^6 || ^7", "thecodingmachine/safe": "^1.3 || ^2" @@ -9015,7 +9015,7 @@ ], "support": { "issues": "https://github.com/webonyx/graphql-php/issues", - "source": "https://github.com/webonyx/graphql-php/tree/v15.9.1" + "source": "https://github.com/webonyx/graphql-php/tree/v15.11.1" }, "funding": [ { @@ -9023,7 +9023,7 @@ "type": "open_collective" } ], - "time": "2024-01-25T09:10:40+00:00" + "time": "2024-03-11T10:21:05+00:00" } ], "packages-dev": [ @@ -9088,16 +9088,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.0", + "version": "v5.0.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc" + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc", - "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", "shasum": "" }, "require": { @@ -9140,26 +9140,27 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" }, - "time": "2024-01-07T17:17:35+00:00" + "time": "2024-03-05T20:51:40+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -9200,9 +9201,15 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -9257,16 +9264,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "11.0.0", + "version": "11.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5e238e4b982cb272bf9faeee6f33af83d465d0e2" + "reference": "7e35a2cbcabac0e6865fd373742ea432a3c34f92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5e238e4b982cb272bf9faeee6f33af83d465d0e2", - "reference": "5e238e4b982cb272bf9faeee6f33af83d465d0e2", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e35a2cbcabac0e6865fd373742ea432a3c34f92", + "reference": "7e35a2cbcabac0e6865fd373742ea432a3c34f92", "shasum": "" }, "require": { @@ -9323,7 +9330,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.0" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.3" }, "funding": [ { @@ -9331,7 +9338,7 @@ "type": "github" } ], - "time": "2024-02-02T06:03:46+00:00" + "time": "2024-03-12T15:35:40+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9580,16 +9587,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.0.3", + "version": "11.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "de24e7e7c67fbf437f7b6cd7bc919f2dc6fd89d4" + "reference": "afa8d61ba7ae78da739938c999140eb767a1ad7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de24e7e7c67fbf437f7b6cd7bc919f2dc6fd89d4", - "reference": "de24e7e7c67fbf437f7b6cd7bc919f2dc6fd89d4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/afa8d61ba7ae78da739938c999140eb767a1ad7f", + "reference": "afa8d61ba7ae78da739938c999140eb767a1ad7f", "shasum": "" }, "require": { @@ -9660,7 +9667,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.0.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.0.7" }, "funding": [ { @@ -9676,20 +9683,20 @@ "type": "tidelift" } ], - "time": "2024-02-10T06:31:16+00:00" + "time": "2024-03-21T07:33:30+00:00" }, { "name": "sebastian/cli-parser", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "efd6ce5bb8131fe981e2f879dbd47605fbe0cc6f" + "reference": "00a74d5568694711f0222e54fb281e1d15fdf04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efd6ce5bb8131fe981e2f879dbd47605fbe0cc6f", - "reference": "efd6ce5bb8131fe981e2f879dbd47605fbe0cc6f", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/00a74d5568694711f0222e54fb281e1d15fdf04a", + "reference": "00a74d5568694711f0222e54fb281e1d15fdf04a", "shasum": "" }, "require": { @@ -9725,7 +9732,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.1" }, "funding": [ { @@ -9733,7 +9740,7 @@ "type": "github" } ], - "time": "2024-02-02T05:48:04+00:00" + "time": "2024-03-02T07:26:58+00:00" }, { "name": "sebastian/code-unit", @@ -9985,16 +9992,16 @@ }, { "name": "sebastian/diff", - "version": "6.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3e3f502419518897a923aa1c64d51f9def2e0aff" + "reference": "ab83243ecc233de5655b76f577711de9f842e712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3e3f502419518897a923aa1c64d51f9def2e0aff", - "reference": "3e3f502419518897a923aa1c64d51f9def2e0aff", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ab83243ecc233de5655b76f577711de9f842e712", + "reference": "ab83243ecc233de5655b76f577711de9f842e712", "shasum": "" }, "require": { @@ -10040,7 +10047,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.1" }, "funding": [ { @@ -10048,7 +10055,7 @@ "type": "github" } ], - "time": "2024-02-02T05:56:35+00:00" + "time": "2024-03-02T07:30:33+00:00" }, { "name": "sebastian/environment", @@ -10116,16 +10123,16 @@ }, { "name": "sebastian/exporter", - "version": "6.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d0c0a93fc746b0c066037f1e7d09104129e868ff" + "reference": "f291e5a317c321c0381fa9ecc796fa2d21b186da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d0c0a93fc746b0c066037f1e7d09104129e868ff", - "reference": "d0c0a93fc746b0c066037f1e7d09104129e868ff", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f291e5a317c321c0381fa9ecc796fa2d21b186da", + "reference": "f291e5a317c321c0381fa9ecc796fa2d21b186da", "shasum": "" }, "require": { @@ -10182,7 +10189,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.0.1" }, "funding": [ { @@ -10190,20 +10197,20 @@ "type": "github" } ], - "time": "2024-02-02T05:58:52+00:00" + "time": "2024-03-02T07:28:20+00:00" }, { "name": "sebastian/global-state", - "version": "7.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "590e7cbc6565fa2e26c3df4e629a34bb0bc00c17" + "reference": "c3a307e832f2e69c7ef869e31fc644fde0e7cb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/590e7cbc6565fa2e26c3df4e629a34bb0bc00c17", - "reference": "590e7cbc6565fa2e26c3df4e629a34bb0bc00c17", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c3a307e832f2e69c7ef869e31fc644fde0e7cb3e", + "reference": "c3a307e832f2e69c7ef869e31fc644fde0e7cb3e", "shasum": "" }, "require": { @@ -10244,7 +10251,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.1" }, "funding": [ { @@ -10252,7 +10259,7 @@ "type": "github" } ], - "time": "2024-02-02T05:59:33+00:00" + "time": "2024-03-02T07:32:10+00:00" }, { "name": "sebastian/lines-of-code", @@ -10633,18 +10640,101 @@ }, "time": "2024-02-01T22:28:11+00:00" }, + { + "name": "symfony/var-dumper", + "version": "v7.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670", + "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.0.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-15T11:33:06+00:00" + }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -10673,7 +10763,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -10681,7 +10771,7 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], diff --git a/psalm.xml b/psalm.xml index 037a8ec9..5d0cb6db 100644 --- a/psalm.xml +++ b/psalm.xml @@ -11,6 +11,10 @@ xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" > + <forbiddenFunctions> + <function name="dump"/> + </forbiddenFunctions> + <projectFiles> <directory name="src" /> <file name="constants.php" /> diff --git a/src/Attribute/BuildsPDOPoolConnection.php b/src/Attribute/BuildsPDOPoolConnection.php deleted file mode 100644 index ad0686af..00000000 --- a/src/Attribute/BuildsPDOPoolConnection.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Distantmagic\Resonance\Attribute; - -use Attribute; -use Distantmagic\Resonance\Attribute as BaseAttribute; - -#[Attribute(Attribute::TARGET_CLASS)] -readonly class BuildsPDOPoolConnection extends BaseAttribute -{ - /** - * @param non-empty-string $name - */ - public function __construct( - public string $name, - ) {} -} diff --git a/src/CurlErrorMessage.php b/src/CurlErrorMessage.php new file mode 100644 index 00000000..4780aa8c --- /dev/null +++ b/src/CurlErrorMessage.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use CurlHandle; +use Stringable; + +readonly class CurlErrorMessage implements Stringable +{ + public function __construct(private CurlHandle $curlHandle) {} + + public function __toString(): string + { + return sprintf( + 'curl request failed because of error: (%d)"%s"', + curl_errno($this->curlHandle), + curl_error($this->curlHandle), + ); + } +} diff --git a/src/CurlException.php b/src/CurlException.php index 15e1069d..0fc9781d 100644 --- a/src/CurlException.php +++ b/src/CurlException.php @@ -11,10 +11,6 @@ class CurlException extends RuntimeException { public function __construct(CurlHandle $ch) { - parent::__construct(sprintf( - 'curl request failed because of error: (%d)"%s"', - curl_errno($ch), - curl_error($ch), - )); + parent::__construct((string) new CurlErrorMessage($ch)); } } diff --git a/src/DatabaseConnectionPoolRepository.php b/src/DatabaseConnectionPoolRepository.php index 27389353..b4e9bacb 100644 --- a/src/DatabaseConnectionPoolRepository.php +++ b/src/DatabaseConnectionPoolRepository.php @@ -8,6 +8,7 @@ use Ds\Map; use OutOfBoundsException; use PDO; use RuntimeException; +use Swoole\Database\PDOPool; use Swoole\Database\PDOProxy; readonly class DatabaseConnectionPoolRepository diff --git a/src/LlamaCppClient.php b/src/LlamaCppClient.php index 09b7a3ef..a05ca2d4 100644 --- a/src/LlamaCppClient.php +++ b/src/LlamaCppClient.php @@ -9,7 +9,9 @@ use Distantmagic\Resonance\Attribute\RequiresPhpExtension; use Distantmagic\Resonance\Attribute\Singleton; use Generator; use JsonSerializable; +use Psr\Log\LoggerInterface; use RuntimeException; +use Swoole\Coroutine; use Swoole\Coroutine\Channel; #[RequiresPhpExtension('curl')] @@ -20,6 +22,7 @@ readonly class LlamaCppClient private JsonSerializer $jsonSerializer, private LlamaCppConfiguration $llamaCppConfiguration, private LlamaCppLinkBuilder $llamaCppLinkBuilder, + private LoggerInterface $logger, ) {} public function generateCompletion(LlamaCppCompletionRequest $request): LlamaCppCompletionIterator @@ -167,31 +170,34 @@ readonly class LlamaCppClient SwooleCoroutineHelper::mustGo(function () use ($channel, $path, $requestData): void { $curlHandle = $this->createCurlHandle(); - try { - curl_setopt($curlHandle, CURLOPT_POST, true); - curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $requestData); - curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, false); - curl_setopt($curlHandle, CURLOPT_URL, $this->llamaCppLinkBuilder->build($path)); - curl_setopt($curlHandle, CURLOPT_WRITEFUNCTION, function (CurlHandle $curlHandle, string $data) use ($channel): int { - if ($channel->push($data, $this->llamaCppConfiguration->completionTokenTimeout)) { - return strlen($data); - } - - return 0; - }); - if (false === curl_exec($curlHandle)) { - $curlErrno = curl_errno($curlHandle); - - if (CURLE_WRITE_ERROR !== $curlErrno) { - throw new CurlException($curlHandle); - } - } else { - $this->assertStatusCode($curlHandle, 200); - } - } finally { + Coroutine::defer(static function () use ($channel) { + $channel->close(); + }); + + Coroutine::defer(static function () use ($curlHandle) { curl_close($curlHandle); + }); + + curl_setopt($curlHandle, CURLOPT_TIMEOUT, 180); + curl_setopt($curlHandle, CURLOPT_POST, true); + curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $requestData); + curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, false); + curl_setopt($curlHandle, CURLOPT_URL, $this->llamaCppLinkBuilder->build($path)); + curl_setopt($curlHandle, CURLOPT_WRITEFUNCTION, function (CurlHandle $curlHandle, string $data) use ($channel): int { + if ($channel->push($data, $this->llamaCppConfiguration->completionTokenTimeout)) { + return strlen($data); + } - $channel->close(); + return 0; + }); + if (false === curl_exec($curlHandle)) { + $curlErrno = curl_errno($curlHandle); + + if (CURLE_WRITE_ERROR !== $curlErrno) { + $this->logger->error(new CurlErrorMessage($curlHandle)); + } + } else { + $this->assertStatusCode($curlHandle, 200); } }); diff --git a/src/ObservableTask.php b/src/ObservableTask.php index 3c763ee3..b3d5b5a1 100644 --- a/src/ObservableTask.php +++ b/src/ObservableTask.php @@ -6,21 +6,32 @@ namespace Distantmagic\Resonance; use Closure; use Generator; +use Throwable; -/** - * @template TTaskStatus of ObservableTaskStatusUpdate - * - * @template-implements ObservableTaskInterface<TTaskStatus> - */ readonly class ObservableTask implements ObservableTaskInterface { /** - * @param Closure():Generator<TTaskStatus> $iterableTask + * @var Closure():iterable<ObservableTaskStatusUpdate> */ - public function __construct(private Closure $iterableTask) {} + private Closure $iterableTask; + + /** + * @param callable():iterable<ObservableTaskStatusUpdate> $iterableTask + */ + public function __construct(callable $iterableTask) + { + $this->iterableTask = Closure::fromCallable($iterableTask); + } public function getIterator(): Generator { - yield from ($this->iterableTask)(); + try { + yield from ($this->iterableTask)(); + } catch (Throwable $throwable) { + yield new ObservableTaskStatusUpdate( + ObservableTaskStatus::Failed, + $throwable, + ); + } } } diff --git a/src/ObservableTaskInterface.php b/src/ObservableTaskInterface.php index 38fbd791..f862534c 100644 --- a/src/ObservableTaskInterface.php +++ b/src/ObservableTaskInterface.php @@ -7,8 +7,6 @@ namespace Distantmagic\Resonance; use IteratorAggregate; /** - * @template TTaskStatus of ObservableTaskStatusUpdate - * - * @template-extends IteratorAggregate<TTaskStatus> + * @template-extends IteratorAggregate<ObservableTaskStatusUpdate> */ interface ObservableTaskInterface extends IteratorAggregate {} diff --git a/src/ObservableTaskTable.php b/src/ObservableTaskTable.php index fe2432d7..dd327719 100644 --- a/src/ObservableTaskTable.php +++ b/src/ObservableTaskTable.php @@ -8,6 +8,8 @@ use Distantmagic\Resonance\Attribute\Singleton; use Ds\Set; use Generator; use IteratorAggregate; +use RuntimeException; +use Swoole\Coroutine; use Swoole\Coroutine\Channel; use Swoole\Table; @@ -41,11 +43,6 @@ readonly class ObservableTaskTable implements IteratorAggregate $this->table->create(); } - public function __destruct() - { - $this->table->destroy(); - } - /** * @return Generator<non-empty-string,?ObservableTaskStatusUpdate> */ @@ -76,30 +73,37 @@ readonly class ObservableTaskTable implements IteratorAggregate $slotId = $this->availableRowsPool->nextAvailableRow(); SwooleCoroutineHelper::mustGo(function () use ($slotId, $observableTask) { - try { - $this->table->set($slotId, [ + Coroutine::defer(function () use ($slotId) { + $this->availableRowsPool->freeAvailableRow($slotId); + }); + + if ( + !$this->table->set($slotId, [ 'status' => $this->serializedPendingStatus, - ]); + ]) + ) { + throw new RuntimeException('Unable to set an initial slot status'); + } - foreach ($observableTask as $statusUpdate) { - $this->table->set($slotId, [ + foreach ($observableTask as $statusUpdate) { + if (!$this->table->set($slotId, [ 'status' => $this->serializer->serialize($statusUpdate), - ]); + ]) + ) { + throw new RuntimeException('Unable to update a slot status.'); + } - if (!$this->observableChannels->isEmpty()) { - $slotStatusUpdate = new ObservableTaskSlotStatusUpdate($slotId, $statusUpdate); + if (!$this->observableChannels->isEmpty()) { + $slotStatusUpdate = new ObservableTaskSlotStatusUpdate($slotId, $statusUpdate); - foreach ($this->observableChannels as $observableChannel) { - $observableChannel->push($slotStatusUpdate); - } + foreach ($this->observableChannels as $observableChannel) { + $observableChannel->push($slotStatusUpdate); } + } - if (ObservableTaskStatus::Running !== $statusUpdate->status) { - break; - } + if (ObservableTaskStatus::Running !== $statusUpdate->status) { + break; } - } finally { - $this->availableRowsPool->freeAvailableRow($slotId); } }); diff --git a/src/ObservableTaskTableSlotStatusUpdateIteratorTest.php b/src/ObservableTaskTableSlotStatusUpdateIteratorTest.php index cb50155e..2ac33652 100644 --- a/src/ObservableTaskTableSlotStatusUpdateIteratorTest.php +++ b/src/ObservableTaskTableSlotStatusUpdateIteratorTest.php @@ -7,6 +7,7 @@ namespace Distantmagic\Resonance; use Distantmagic\Resonance\Serializer\Vanilla; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Swoole\Coroutine; use Swoole\Coroutine\WaitGroup; use Swoole\Event; @@ -59,23 +60,23 @@ final class ObservableTaskTableSlotStatusUpdateIteratorTest extends TestCase SwooleCoroutineHelper::mustGo(function () use ($wg) { self::assertNotNull($this->observableTaskTable); - try { - $iterator = new ObservableTaskTableSlotStatusUpdateIterator($this->observableTaskTable); + Coroutine::defer(static function () use ($wg) { + $wg->done(); + }); - foreach ($iterator as $statusUpdate) { - self::assertInstanceOf(ObservableTaskSlotStatusUpdate::class, $statusUpdate); - self::assertEquals('0', $statusUpdate->slotId); + $iterator = new ObservableTaskTableSlotStatusUpdateIterator($this->observableTaskTable); - if (ObservableTaskStatus::Finished === $statusUpdate->observableTaskStatusUpdate->status) { - self::assertEquals('test2', $statusUpdate->observableTaskStatusUpdate->data); + foreach ($iterator as $statusUpdate) { + self::assertInstanceOf(ObservableTaskSlotStatusUpdate::class, $statusUpdate); + self::assertEquals('0', $statusUpdate->slotId); - break; - } + if (ObservableTaskStatus::Finished === $statusUpdate->observableTaskStatusUpdate->status) { + self::assertEquals('test2', $statusUpdate->observableTaskStatusUpdate->data); - self::assertEquals('test1', $statusUpdate->observableTaskStatusUpdate->data); + break; } - } finally { - $wg->done(); + + self::assertEquals('test1', $statusUpdate->observableTaskStatusUpdate->data); } }); diff --git a/src/ObservableTaskTableTest.php b/src/ObservableTaskTableTest.php index 090ac1f2..c44043f3 100644 --- a/src/ObservableTaskTableTest.php +++ b/src/ObservableTaskTableTest.php @@ -7,6 +7,7 @@ namespace Distantmagic\Resonance; use Distantmagic\Resonance\Serializer\Vanilla; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Swoole\Coroutine; use Swoole\Coroutine\Channel; use Swoole\Coroutine\WaitGroup; use Swoole\Event; @@ -61,19 +62,19 @@ final class ObservableTaskTableTest extends TestCase $wg->add(); SwooleCoroutineHelper::mustGo(static function () use ($channel, $wg) { - try { - $status1 = $channel->pop(); + Coroutine::defer(static function () use ($wg) { + $wg->done(); + }); - self::assertInstanceOf(ObservableTaskSlotStatusUpdate::class, $status1); - self::assertSame(ObservableTaskStatus::Running, $status1->observableTaskStatusUpdate->status); + $status1 = $channel->pop(); - $status2 = $channel->pop(); + self::assertInstanceOf(ObservableTaskSlotStatusUpdate::class, $status1); + self::assertSame(ObservableTaskStatus::Running, $status1->observableTaskStatusUpdate->status); - self::assertInstanceOf(ObservableTaskSlotStatusUpdate::class, $status2); - self::assertSame(ObservableTaskStatus::Finished, $status2->observableTaskStatusUpdate->status); - } finally { - $wg->done(); - } + $status2 = $channel->pop(); + + self::assertInstanceOf(ObservableTaskSlotStatusUpdate::class, $status2); + self::assertSame(ObservableTaskStatus::Finished, $status2->observableTaskStatusUpdate->status); }); $this->observableTaskTable?->observe($observableTask); diff --git a/src/ObservableTaskTimeoutIterator.php b/src/ObservableTaskTimeoutIterator.php new file mode 100644 index 00000000..f72ba432 --- /dev/null +++ b/src/ObservableTaskTimeoutIterator.php @@ -0,0 +1,91 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use Closure; +use Generator; +use IteratorAggregate; +use Swoole\Coroutine; +use Swoole\Coroutine\Channel; + +/** + * @template-implements IteratorAggregate<ObservableTaskStatusUpdate> + */ +readonly class ObservableTaskTimeoutIterator implements IteratorAggregate +{ + /** + * @var Closure():Generator<ObservableTaskStatusUpdate> + */ + private Closure $iterableTask; + + /** + * @param callable():Generator<ObservableTaskStatusUpdate> $iterableTask + */ + public function __construct( + callable $iterableTask, + private float $inactivityTimeout, + ) { + $this->iterableTask = Closure::fromCallable($iterableTask); + } + + /** + * @return SwooleChannelIterator<ObservableTaskStatusUpdate> + */ + public function __invoke(): SwooleChannelIterator + { + return $this->getIterator(); + } + + /** + * @psalm-suppress UnusedVariable $generatorCoroutineId is used, just asynchronously + * + * @return SwooleChannelIterator<ObservableTaskStatusUpdate> + */ + public function getIterator(): SwooleChannelIterator + { + /** + * @var null|int $generatorCoroutineId + */ + $generatorCoroutineId = null; + + $channel = new Channel(1); + + $swooleTimeout = new SwooleTimeout(static function () use (&$generatorCoroutineId) { + if (is_int($generatorCoroutineId)) { + Coroutine::cancel($generatorCoroutineId); + } + }); + + $generatorCoroutineId = SwooleCoroutineHelper::mustGo(function () use ($channel, $swooleTimeout) { + $swooleTimeoutScheduled = $swooleTimeout->setTimeout($this->inactivityTimeout); + + Coroutine::defer(static function () use ($channel) { + $channel->close(); + }); + + Coroutine::defer(static function () use (&$swooleTimeoutScheduled) { + $swooleTimeoutScheduled->cancel(); + }); + + foreach (($this->iterableTask)() as $observableTaskStatusUpdate) { + if (Coroutine::isCanceled()) { + break; + } + + $swooleTimeoutScheduled = $swooleTimeoutScheduled->reschedule($this->inactivityTimeout); + + $channel->push($observableTaskStatusUpdate, $this->inactivityTimeout); + } + }); + + /** + * @var SwooleChannelIterator<ObservableTaskStatusUpdate> + */ + return new SwooleChannelIterator( + channel: $channel, + timeout: $this->inactivityTimeout, + ); + } +} diff --git a/src/PDOPool.php b/src/PDOPool.php deleted file mode 100644 index 79eb6d9a..00000000 --- a/src/PDOPool.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Distantmagic\Resonance; - -use Ds\Set; -use PDO; -use Swoole\ConnectionPool; -use Swoole\Database\PDOConfig; -use Swoole\Database\PDOProxy; - -/** - * @psalm-suppress PropertyNotSetInConstructor swoole internals - */ -class PDOPool extends ConnectionPool -{ - /** - * @param Set<PDOPoolConnectionBuilderInterface> $connectionBuilders - */ - public function __construct( - private Set $connectionBuilders, - private PDOConfig $config, - int $size, - ) { - parent::__construct( - $this->createConnection(...), - $size, - PDOProxy::class, - ); - } - - public function get(float $timeout = -1): PDOProxy - { - /** - * @var PDOProxy $pdo - */ - $pdo = parent::get($timeout); - $pdo->reset(); - - return $pdo; - } - - private function createConnection(): PDO - { - $pdo = $this->createPDO(); - - foreach ($this->connectionBuilders as $connectionBuilder) { - $pdo = $connectionBuilder->buildPDOConnection($pdo); - } - - return $pdo; - } - - private function createDSN(string $driver): string - { - return match ($driver) { - 'mariadb', 'mysql' => $this->config->hasUnixSocket() - ? sprintf( - 'mysql:unix_socket=%s;dbname=%s;charset=%s', - (string) $this->config->getUnixSocket(), - $this->config->getDbname(), - $this->config->getCharset() - ) - : sprintf( - 'mysql:host=%s;port=%d;dbname=%s;charset=%s', - $this->config->getHost(), - $this->config->getPort(), - $this->config->getDbname(), - $this->config->getCharset() - ), - 'pgsql' => sprintf( - 'pgsql:host=%s;port=%s;dbname=%s', - (string) ($this->config->hasUnixSocket() ? $this->config->getUnixSocket() : $this->config->getHost()), - $this->config->getPort(), - $this->config->getDbname(), - ), - 'oci' => sprintf( - 'oci:dbname=%s:%d/%s;charset=%s', - (string) ($this->config->hasUnixSocket() ? $this->config->getUnixSocket() : $this->config->getHost()), - $this->config->getPort(), - $this->config->getDbname(), - $this->config->getCharset() - ), - }; - } - - private function createPDO(): PDO - { - $driver = $this->config->getDriver(); - - if ('sqlite' !== $driver) { - return new PDO( - $this->createDSN($driver), - $this->config->getUsername(), - $this->config->getPassword(), - $this->config->getOptions() - ); - } - - return new PDO(sprintf( - 'sqlite:%s', - $this->config->getDbname() - )); - } -} diff --git a/src/PDOPoolConnectionBuilder.php b/src/PDOPoolConnectionBuilder.php deleted file mode 100644 index 10d63ec6..00000000 --- a/src/PDOPoolConnectionBuilder.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Distantmagic\Resonance; - -abstract readonly class PDOPoolConnectionBuilder implements PDOPoolConnectionBuilderInterface {} diff --git a/src/PDOPoolConnectionBuilderCollection.php b/src/PDOPoolConnectionBuilderCollection.php deleted file mode 100644 index f2a29644..00000000 --- a/src/PDOPoolConnectionBuilderCollection.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Distantmagic\Resonance; - -use Ds\Map; -use Ds\Set; - -readonly class PDOPoolConnectionBuilderCollection -{ - /** - * @var Map<non-empty-string,Set<PDOPoolConnectionBuilderInterface>> - */ - private Map $connectionBuilders; - - public function __construct() - { - $this->connectionBuilders = new Map(); - } - - /** - * @param non-empty-string $name - */ - public function addBuilder( - string $name, - PDOPoolConnectionBuilderInterface $pdoPoolConnectionBuilder, - ): void { - $this->getBuildersForConnection($name)->add($pdoPoolConnectionBuilder); - } - - /** - * @param non-empty-string $name - * - * @return Set<PDOPoolConnectionBuilderInterface> - */ - public function getBuildersForConnection(string $name): Set - { - if (!$this->connectionBuilders->hasKey($name)) { - $this->connectionBuilders->put($name, new Set()); - } - - return $this->connectionBuilders->get($name); - } -} diff --git a/src/PDOPoolConnectionBuilderInterface.php b/src/PDOPoolConnectionBuilderInterface.php deleted file mode 100644 index 1e4bdc21..00000000 --- a/src/PDOPoolConnectionBuilderInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Distantmagic\Resonance; - -use PDO; - -interface PDOPoolConnectionBuilderInterface -{ - public function buildPDOConnection(PDO $pdo): PDO; -} diff --git a/src/SingletonProvider/DatabaseConnectionPoolRepositoryProvider.php b/src/SingletonProvider/DatabaseConnectionPoolRepositoryProvider.php index dcfa7966..475116bb 100644 --- a/src/SingletonProvider/DatabaseConnectionPoolRepositoryProvider.php +++ b/src/SingletonProvider/DatabaseConnectionPoolRepositoryProvider.php @@ -8,12 +8,11 @@ use Distantmagic\Resonance\Attribute\RequiresPhpExtension; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\DatabaseConfiguration; use Distantmagic\Resonance\DatabaseConnectionPoolRepository; -use Distantmagic\Resonance\PDOPool; -use Distantmagic\Resonance\PDOPoolConnectionBuilderCollection; use Distantmagic\Resonance\PHPProjectFiles; use Distantmagic\Resonance\SingletonContainer; use Distantmagic\Resonance\SingletonProvider; use Swoole\Database\PDOConfig; +use Swoole\Database\PDOPool; /** * @template-extends SingletonProvider<DatabaseConnectionPoolRepository> @@ -24,7 +23,6 @@ final readonly class DatabaseConnectionPoolRepositoryProvider extends SingletonP { public function __construct( private DatabaseConfiguration $databaseConfiguration, - private PDOPoolConnectionBuilderCollection $pdoPoolConnectionBuilderCollection, ) {} public function provide(SingletonContainer $singletons, PHPProjectFiles $phpProjectFiles): DatabaseConnectionPoolRepository @@ -53,7 +51,6 @@ final readonly class DatabaseConnectionPoolRepositoryProvider extends SingletonP } $pdoPool = new PDOPool( - $this->pdoPoolConnectionBuilderCollection->getBuildersForConnection($name), $pdoConfig, $connectionPoolConfiguration->poolSize, ); diff --git a/src/SingletonProvider/PDOPoolConnectionBuilderCollectionProvider.php b/src/SingletonProvider/PDOPoolConnectionBuilderCollectionProvider.php deleted file mode 100644 index 1820af1f..00000000 --- a/src/SingletonProvider/PDOPoolConnectionBuilderCollectionProvider.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Distantmagic\Resonance\SingletonProvider; - -use Distantmagic\Resonance\Attribute\BuildsPDOPoolConnection; -use Distantmagic\Resonance\Attribute\RequiresPhpExtension; -use Distantmagic\Resonance\Attribute\RequiresSingletonCollection; -use Distantmagic\Resonance\Attribute\Singleton; -use Distantmagic\Resonance\HttpResponderCollection; -use Distantmagic\Resonance\PDOPoolConnectionBuilderCollection; -use Distantmagic\Resonance\PDOPoolConnectionBuilderInterface; -use Distantmagic\Resonance\PHPProjectFiles; -use Distantmagic\Resonance\SingletonAttribute; -use Distantmagic\Resonance\SingletonCollection; -use Distantmagic\Resonance\SingletonContainer; -use Distantmagic\Resonance\SingletonProvider; - -/** - * @template-extends SingletonProvider<HttpResponderCollection> - */ -#[RequiresPhpExtension('pdo')] -#[RequiresSingletonCollection(SingletonCollection::PDOPoolConnectionBuilder)] -#[Singleton(provides: PDOPoolConnectionBuilderCollection::class)] -final readonly class PDOPoolConnectionBuilderCollectionProvider extends SingletonProvider -{ - public function provide(SingletonContainer $singletons, PHPProjectFiles $phpProjectFiles): PDOPoolConnectionBuilderCollection - { - $pdoPoolConnectionBuilderCollection = new PDOPoolConnectionBuilderCollection(); - - foreach ($this->collectBuilders($singletons) as $builderAttribute) { - $pdoPoolConnectionBuilderCollection->addBuilder( - $builderAttribute->attribute->name, - $builderAttribute->singleton - ); - } - - return $pdoPoolConnectionBuilderCollection; - } - - /** - * @return iterable<SingletonAttribute<PDOPoolConnectionBuilderInterface,BuildsPDOPoolConnection>> - */ - private function collectBuilders(SingletonContainer $singletons): iterable - { - return $this->collectAttributes( - $singletons, - PDOPoolConnectionBuilderInterface::class, - BuildsPDOPoolConnection::class, - ); - } -} diff --git a/src/SwooleCoroutineHelper.php b/src/SwooleCoroutineHelper.php index 1190ac37..af825d52 100644 --- a/src/SwooleCoroutineHelper.php +++ b/src/SwooleCoroutineHelper.php @@ -15,7 +15,7 @@ final readonly class SwooleCoroutineHelper /** * @param callable() $callback */ - public static function mustGo(callable $callback): void + public static function mustGo(callable $callback): int { /** * @var false|int $cid @@ -25,6 +25,8 @@ final readonly class SwooleCoroutineHelper if (!is_int($cid)) { throw new RuntimeException('Unable to start a coroutine'); } + + return $cid; } /** diff --git a/src/SwooleServer.php b/src/SwooleServer.php index d2690f6a..aa1acdaf 100644 --- a/src/SwooleServer.php +++ b/src/SwooleServer.php @@ -13,6 +13,7 @@ use Swoole\Http\Request; use Swoole\Http\Response; use Swoole\Http\Server as HttpServer; use Swoole\Server; +use Swoole\Server\StatusInfo; use Swoole\WebSocket\Server as WebSocketServer; #[GrantsFeature(Feature::SwooleTaskServer)] @@ -77,11 +78,12 @@ readonly class SwooleServer ]); $this->server->on('beforeShutdown', $this->onBeforeShutdown(...)); - $this->server->on('pipeMessage', $this->serverPipeMessageDispatcher->onPipeMessage(...)); $this->server->on('finish', $this->serverTaskHandlerDispatcher->onFinish(...)); + $this->server->on('pipeMessage', $this->serverPipeMessageDispatcher->onPipeMessage(...)); $this->server->on('request', $this->httpResponderAggregate->respondToSwooleRequest(...)); $this->server->on('start', $this->onStart(...)); $this->server->on('task', $this->serverTaskHandlerDispatcher->onTask(...)); + $this->server->on('workerError', $this->onWorkerError(...)); if ($this->webSocketServerController) { $this->server->on('close', $this->onClose(...)); @@ -135,4 +137,12 @@ readonly class SwooleServer )); } } + + private function onWorkerError(Server $server, StatusInfo $statusInfo): void + { + $this->logger->error(sprintf( + 'swoole_worker_error(%s)', + print_r($statusInfo, true) + )); + } } diff --git a/src/SwooleTableAvailableRowsPool.php b/src/SwooleTableAvailableRowsPool.php index 0f9c3d93..8791e002 100644 --- a/src/SwooleTableAvailableRowsPool.php +++ b/src/SwooleTableAvailableRowsPool.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Distantmagic\Resonance; use OverflowException; +use RuntimeException; use Swoole\Atomic; use Swoole\Table; use UnderflowException; @@ -21,7 +22,10 @@ readonly class SwooleTableAvailableRowsPool $this->availableRows = new Table(2 * $size); $this->availableRows->column('index', Table::TYPE_INT); - $this->availableRows->create(); + + if (!$this->availableRows->create()) { + throw new RuntimeException('Unable to allocate table'); + } for ($i = 0; $i < $size; ++$i) { $this->availableRows->set((string) $i, [ @@ -30,11 +34,6 @@ readonly class SwooleTableAvailableRowsPool } } - public function __destruct() - { - $this->availableRows->destroy(); - } - /** * @param non-empty-string $index */ @@ -46,12 +45,15 @@ readonly class SwooleTableAvailableRowsPool throw new UnderflowException('No available rows'); } - $this - ->availableRows - ->set((string) $availableRowPointerValue, [ - 'index' => (int) $index, - ]) - ; + if ( + !$this + ->availableRows + ->set((string) $availableRowPointerValue, [ + 'index' => (int) $index, + ]) + ) { + throw new RuntimeException('Unable to free available row'); + } } /** diff --git a/src/SwooleTimeout.php b/src/SwooleTimeout.php new file mode 100644 index 00000000..978a27ff --- /dev/null +++ b/src/SwooleTimeout.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use Closure; + +readonly class SwooleTimeout +{ + private Closure $callback; + private SwooleTimeoutScheduler $swooleTimeoutScheduler; + + public function __construct(callable $callback) + { + $this->callback = Closure::fromCallable($callback); + $this->swooleTimeoutScheduler = new SwooleTimeoutScheduler(); + } + + public function setTimeout(float $timeout): SwooleTimeoutScheduled + { + return new SwooleTimeoutScheduled( + $this->callback, + $this->swooleTimeoutScheduler->scheduleTimeout($timeout, $this->callback), + $this->swooleTimeoutScheduler, + ); + } +} diff --git a/src/SwooleTimeoutScheduled.php b/src/SwooleTimeoutScheduled.php new file mode 100644 index 00000000..9e9faae4 --- /dev/null +++ b/src/SwooleTimeoutScheduled.php @@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use Closure; +use RuntimeException; +use Swoole\Coroutine; + +readonly class SwooleTimeoutScheduled +{ + private Closure $callback; + + public function __construct( + callable $callback, + private int $coroutineId, + private SwooleTimeoutScheduler $swooleTimeoutScheduler, + ) { + $this->callback = Closure::fromCallable($callback); + } + + public function cancel(): bool + { + if (!Coroutine::exists($this->coroutineId)) { + return true; + } + + /** + * @var bool + */ + return Coroutine::cancel($this->coroutineId); + } + + public function reschedule(float $timeout): self + { + if (!$this->cancel()) { + throw new RuntimeException('Unable to cancel a coroutine.'); + } + + return new self( + $this->callback, + $this->swooleTimeoutScheduler->scheduleTimeout($timeout, $this->callback), + $this->swooleTimeoutScheduler, + ); + } +} diff --git a/src/SwooleTimeoutScheduler.php b/src/SwooleTimeoutScheduler.php new file mode 100644 index 00000000..6eb5d180 --- /dev/null +++ b/src/SwooleTimeoutScheduler.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use Swoole\Coroutine; + +readonly class SwooleTimeoutScheduler +{ + public function scheduleTimeout( + float $timeout, + callable $callback, + ): int { + return SwooleCoroutineHelper::mustGo(static function () use ($callback, $timeout) { + Coroutine::sleep($timeout); + + if (!Coroutine::isCanceled()) { + $callback(); + } + }); + } +} diff --git a/src/SwooleTimeoutTest.php b/src/SwooleTimeoutTest.php new file mode 100644 index 00000000..9e1bc0ae --- /dev/null +++ b/src/SwooleTimeoutTest.php @@ -0,0 +1,55 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\TestCase; +use Swoole\Event; + +/** + * @internal + */ +#[CoversClass(SwooleTimeout::class)] +#[CoversClass(SwooleTimeoutScheduled::class)] +#[CoversClass(SwooleTimeoutScheduler::class)] +final class SwooleTimeoutTest extends TestCase +{ + protected function tearDown(): void + { + Event::wait(); + } + + public function test_code_executes_after_timeout(): void + { + SwooleCoroutineHelper::mustRun(static function () { + $before = microtime(true); + + $timeout = new SwooleTimeout(static function () use ($before) { + $after = microtime(true); + + self::assertGreaterThan(0.03, $after - $before); + self::assertLessThan(0.035, $after - $before); + }); + + $timeout->setTimeout(0.03); + }); + } + + public function test_task_is_rescheduled(): void + { + SwooleCoroutineHelper::mustRun(static function () { + $before = microtime(true); + + $timeout = new SwooleTimeout(static function () use ($before) { + $after = microtime(true); + + self::assertGreaterThan(0.03, $after - $before); + self::assertLessThan(0.035, $after - $before); + }); + + $timeout->setTimeout(0.02)->reschedule(0.03); + }); + } +} diff --git a/src/TwigResonanceFilesystemLoader.php b/src/TwigResonanceFilesystemLoader.php new file mode 100644 index 00000000..ac23fbe8 --- /dev/null +++ b/src/TwigResonanceFilesystemLoader.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace Distantmagic\Resonance; + +use Distantmagic\Resonance\Attribute\Singleton; +use Distantmagic\Resonance\Attribute\TwigLoader; +use Twig\Loader\FilesystemLoader; + +#[Singleton(collection: SingletonCollection::TwigLoader)] +#[TwigLoader] +class TwigResonanceFilesystemLoader extends FilesystemLoader implements TwigOptionalLoaderInterface +{ + public function __construct() + { + parent::__construct(); + } + + public function beforeRegister(): void + { + $this->addPath(DM_RESONANCE_ROOT.'/views', 'resonance'); + } + + public function shouldRegister(): bool + { + return is_dir(DM_RESONANCE_ROOT.'/views'); + } +} diff --git a/src/WebSocketRPCResponder/LlamaCppSubjectActionPromptResponder.php b/src/WebSocketRPCResponder/LlamaCppSubjectActionPromptResponder.php index 7d996fd0..188961df 100644 --- a/src/WebSocketRPCResponder/LlamaCppSubjectActionPromptResponder.php +++ b/src/WebSocketRPCResponder/LlamaCppSubjectActionPromptResponder.php @@ -15,6 +15,7 @@ use Distantmagic\Resonance\ObservableTask; use Distantmagic\Resonance\ObservableTaskStatus; use Distantmagic\Resonance\ObservableTaskStatusUpdate; use Distantmagic\Resonance\ObservableTaskTable; +use Distantmagic\Resonance\ObservableTaskTimeoutIterator; use Distantmagic\Resonance\PromptSubjectResponderAggregate; use Distantmagic\Resonance\RPCRequest; use Distantmagic\Resonance\WebSocketAuthResolution; @@ -80,26 +81,26 @@ abstract readonly class LlamaCppSubjectActionPromptResponder extends WebSocketRP RPCRequest $rpcRequest, ): void { $this->observableTaskTable->observe(new ObservableTask( - /** - * @return Generator<ObservableTaskStatusUpdate> - */ - function () use ( - $webSocketAuthResolution, - $webSocketConnection, - $rpcRequest, - ): Generator { - yield new ObservableTaskStatusUpdate(ObservableTaskStatus::Running, null); - - try { - $this->onObservableRequest( - $webSocketAuthResolution, - $webSocketConnection, - $rpcRequest, - ); - } finally { - yield new ObservableTaskStatusUpdate(ObservableTaskStatus::Finished, null); - } - } + new ObservableTaskTimeoutIterator( + iterableTask: function () use ( + $webSocketAuthResolution, + $webSocketConnection, + $rpcRequest, + ): Generator { + yield new ObservableTaskStatusUpdate(ObservableTaskStatus::Running, null); + + try { + $this->onObservableRequest( + $webSocketAuthResolution, + $webSocketConnection, + $rpcRequest, + ); + } finally { + yield new ObservableTaskStatusUpdate(ObservableTaskStatus::Finished, null); + } + }, + inactivityTimeout: 1.0, + ) )); } @@ -123,7 +124,8 @@ abstract readonly class LlamaCppSubjectActionPromptResponder extends WebSocketRP $this->runningCompletions->offsetSet($webSocketConnection, $completion); - $response = $this->promptSubjectResponderAggregate + $response = $this + ->promptSubjectResponderAggregate ->createResponseFromTokens( authenticatedUser: $webSocketAuthResolution->authenticatedUser, completion: $completion, diff --git a/src/views/observable_tasks_dashboard.twig b/src/views/observable_tasks_dashboard.twig new file mode 100644 index 00000000..714c401c --- /dev/null +++ b/src/views/observable_tasks_dashboard.twig @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title></title> +</head> +<body> + <table> + <thead> + <tr> + </tr> + </thead> + <tbody> + {% for slotId, observableTask in observableTaskTable %} + <tr> + <td>{{ slotId }}</td> + <td>{{ observableTask.status.value }}</td> + </tr> + {% endfor %} + </tbody> + </table> +</body> +</html> -- GitLab