diff --git a/Dockerfile b/Dockerfile index 3a2272b9..b4f79bf1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,4 +26,4 @@ RUN bash docker/build.sh \ #CMD ["php-fpm"] -EXPOSE 9000 \ No newline at end of file +EXPOSE 9001 \ No newline at end of file diff --git a/composer.json b/composer.json index b13ada0a..e0f068ae 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,6 @@ "symfony/finder": "^4.0", "zendframework/zend-db": "^2.8", "dragonmantank/cron-expression": "^2.0", - "ocramius/proxy-manager": "^2.1", "neighborhoods/pylon": "^1.0", "doctrine/dbal": "^2.7" }, @@ -47,8 +46,7 @@ }, "autoload-dev": { "psr-4": { - "Neighborhoods\\KojoTest\\": "tests", - "Neighborhoods\\KojoExample\\": "example" + "Neighborhoods\\KojoTest\\": "tests" } } } diff --git a/composer.lock b/composer.lock index 3c069de3..22506f5d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "ad76a5b871bb8e08602cd4d6bd8e70e0", + "content-hash": "3382a0a8f83c6ac1ba27f686535d85bd", "packages": [ { "name": "doctrine/annotations", @@ -571,124 +571,6 @@ "description": "Neighborhoods Pylon is a collection of useful, but most importantly, generic objects.", "time": "2018-04-18T19:29:35+00:00" }, - { - "name": "ocramius/package-versions", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f", - "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0.0", - "php": "^7.1.0" - }, - "require-dev": { - "composer/composer": "^1.6.3", - "ext-zip": "*", - "infection/infection": "^0.7.1", - "phpunit/phpunit": "^7.0.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2018-02-05T13:05:30+00:00" - }, - { - "name": "ocramius/proxy-manager", - "version": "2.1.1", - "source": { - "type": "git", - "url": "https://github.com/Ocramius/ProxyManager.git", - "reference": "e18ac876b2e4819c76349de8f78ccc8ef1554cd7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/e18ac876b2e4819c76349de8f78ccc8ef1554cd7", - "reference": "e18ac876b2e4819c76349de8f78ccc8ef1554cd7", - "shasum": "" - }, - "require": { - "ocramius/package-versions": "^1.1.1", - "php": "^7.1.0", - "zendframework/zend-code": "^3.1.0" - }, - "require-dev": { - "couscous/couscous": "^1.5.2", - "ext-phar": "*", - "humbug/humbug": "dev-master@DEV", - "nikic/php-parser": "^3.0.4", - "phpbench/phpbench": "^0.12.2", - "phpstan/phpstan": "^0.6.4", - "phpunit/phpunit": "^5.6.4", - "phpunit/phpunit-mock-objects": "^3.4.1", - "squizlabs/php_codesniffer": "^2.7.0" - }, - "suggest": { - "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects", - "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)", - "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)", - "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "ProxyManager\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.io/" - } - ], - "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", - "homepage": "https://github.com/Ocramius/ProxyManager", - "keywords": [ - "aop", - "lazy loading", - "proxy", - "proxy pattern", - "service proxies" - ], - "time": "2017-05-04T11:12:50+00:00" - }, { "name": "psr/cache", "version": "1.0.1", @@ -881,16 +763,16 @@ }, { "name": "symfony/cache", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "ff96ef34437ccc2c0737677c1bf14904a2b9482d" + "reference": "bd6d0a969c80b00630e9e2f0ab14ad4518712ec8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/ff96ef34437ccc2c0737677c1bf14904a2b9482d", - "reference": "ff96ef34437ccc2c0737677c1bf14904a2b9482d", + "url": "https://api.github.com/repos/symfony/cache/zipball/bd6d0a969c80b00630e9e2f0ab14ad4518712ec8", + "reference": "bd6d0a969c80b00630e9e2f0ab14ad4518712ec8", "shasum": "" }, "require": { @@ -946,25 +828,26 @@ "caching", "psr6" ], - "time": "2018-04-30T01:05:59+00:00" + "time": "2018-05-16T09:05:32+00:00" }, { "name": "symfony/config", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "7c19370ab04e9ac05b74a504198e165f5ccf6dd8" + "reference": "aaef656e99c5396d6118970abd1ceb11fa74551d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/7c19370ab04e9ac05b74a504198e165f5ccf6dd8", - "reference": "7c19370ab04e9ac05b74a504198e165f5ccf6dd8", + "url": "https://api.github.com/repos/symfony/config/zipball/aaef656e99c5396d6118970abd1ceb11fa74551d", + "reference": "aaef656e99c5396d6118970abd1ceb11fa74551d", "shasum": "" }, "require": { "php": "^7.1.3", - "symfony/filesystem": "~3.4|~4.0" + "symfony/filesystem": "~3.4|~4.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/finder": "<3.4" @@ -1008,20 +891,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:35:49+00:00" + "time": "2018-05-16T09:05:32+00:00" }, { "name": "symfony/console", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae" + "reference": "058f120b8e06ebcd7b211de5ffae07b2db00fbdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae", - "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae", + "url": "https://api.github.com/repos/symfony/console/zipball/058f120b8e06ebcd7b211de5ffae07b2db00fbdd", + "reference": "058f120b8e06ebcd7b211de5ffae07b2db00fbdd", "shasum": "" }, "require": { @@ -1076,20 +959,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-04-30T01:23:47+00:00" + "time": "2018-05-16T09:05:32+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "1f99622d8a63b160bfdd0ad7b2da56ee413cba64" + "reference": "4b272d65e9c0d2d40e2d23bab3c7a184ad4a3a18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/1f99622d8a63b160bfdd0ad7b2da56ee413cba64", - "reference": "1f99622d8a63b160bfdd0ad7b2da56ee413cba64", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4b272d65e9c0d2d40e2d23bab3c7a184ad4a3a18", + "reference": "4b272d65e9c0d2d40e2d23bab3c7a184ad4a3a18", "shasum": "" }, "require": { @@ -1147,11 +1030,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2018-04-30T01:05:59+00:00" + "time": "2018-05-25T11:57:52+00:00" }, { "name": "symfony/expression-language", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", @@ -1201,20 +1084,21 @@ }, { "name": "symfony/filesystem", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21" + "reference": "7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21", - "reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04", + "reference": "7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { @@ -1246,20 +1130,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-02-22T10:50:29+00:00" + "time": "2018-05-16T09:05:32+00:00" }, { "name": "symfony/finder", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49" + "reference": "8c633f5a815903a1fe6e3fc135f207267a8a79af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49", - "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49", + "url": "https://api.github.com/repos/symfony/finder/zipball/8c633f5a815903a1fe6e3fc135f207267a8a79af", + "reference": "8c633f5a815903a1fe6e3fc135f207267a8a79af", "shasum": "" }, "require": { @@ -1295,7 +1179,62 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-04-04T05:10:37+00:00" + "time": "2018-05-16T09:05:32+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -1358,20 +1297,21 @@ }, { "name": "symfony/yaml", - "version": "v4.0.9", + "version": "v4.0.11", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "275ad099e4cbe612a2acbca14a16dd1c5311324d" + "reference": "048b1be5fb96e73ff1d065f5e7e23f84415ac907" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/275ad099e4cbe612a2acbca14a16dd1c5311324d", - "reference": "275ad099e4cbe612a2acbca14a16dd1c5311324d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/048b1be5fb96e73ff1d065f5e7e23f84415ac907", + "reference": "048b1be5fb96e73ff1d065f5e7e23f84415ac907", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/console": "<3.4" @@ -1412,60 +1352,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-04-08T08:49:08+00:00" - }, - { - "name": "zendframework/zend-code", - "version": "3.3.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-code.git", - "reference": "6b1059db5b368db769e4392c6cb6cc139e56640d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-code/zipball/6b1059db5b368db769e4392c6cb6cc139e56640d", - "reference": "6b1059db5b368db769e4392c6cb6cc139e56640d", - "shasum": "" - }, - "require": { - "php": "^7.1", - "zendframework/zend-eventmanager": "^2.6 || ^3.0" - }, - "require-dev": { - "doctrine/annotations": "~1.0", - "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "zendframework/zend-coding-standard": "^1.0.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0" - }, - "suggest": { - "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", - "zendframework/zend-stdlib": "Zend\\Stdlib component" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev", - "dev-develop": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Code\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "provides facilities to generate arbitrary code using an object oriented interface", - "homepage": "https://github.com/zendframework/zend-code", - "keywords": [ - "code", - "zf2" - ], - "time": "2017-10-20T15:21:32+00:00" + "time": "2018-05-07T07:12:24+00:00" }, { "name": "zendframework/zend-db", @@ -1525,60 +1412,6 @@ ], "time": "2018-04-09T13:21:36+00:00" }, - { - "name": "zendframework/zend-eventmanager", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-eventmanager.git", - "reference": "a5e2583a211f73604691586b8406ff7296a946dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/a5e2583a211f73604691586b8406ff7296a946dd", - "reference": "a5e2583a211f73604691586b8406ff7296a946dd", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "athletic/athletic": "^0.1", - "container-interop/container-interop": "^1.1.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", - "zendframework/zend-coding-standard": "~1.0.0", - "zendframework/zend-stdlib": "^2.7.3 || ^3.0" - }, - "suggest": { - "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", - "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev", - "dev-develop": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\EventManager\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Trigger and listen to events within a PHP application", - "homepage": "https://github.com/zendframework/zend-eventmanager", - "keywords": [ - "event", - "eventmanager", - "events", - "zf2" - ], - "time": "2018-04-25T15:33:34+00:00" - }, { "name": "zendframework/zend-stdlib", "version": "3.2.0", @@ -1728,17 +1561,17 @@ }, { "name": "neighborhoods/scaffolding", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "git@github.com:neighborhoods/Scaffolding.git", - "reference": "65773e310df05b1843d554729bbfd99c6f51313e" + "reference": "b054606cbc696cbe369b9b0de217076da3fba6e5" }, "dist": { "type": "tar", - "url": "https://satis.neighborhoods.com/dist/neighborhoods/scaffolding/neighborhoods-scaffolding-65773e310df05b1843d554729bbfd99c6f51313e-zip-134796.tar", - "reference": "65773e310df05b1843d554729bbfd99c6f51313e", - "shasum": "8a8577ab48c9ddb542e1bb8a611629382305b351" + "url": "https://satis.neighborhoods.com/dist/neighborhoods/scaffolding/neighborhoods-scaffolding-b054606cbc696cbe369b9b0de217076da3fba6e5-zip-990c14.tar", + "reference": "b054606cbc696cbe369b9b0de217076da3fba6e5", + "shasum": "71f21e3c52bf74c7acf2d222962ae14fcf876ade" }, "require": { "neighborhoods/pylon": "^1.0.0", @@ -1771,7 +1604,7 @@ } ], "description": "Neighborhoods Scaffolding is meant to make the creation of contract testing easy and fast.", - "time": "2018-05-02T22:49:38+00:00" + "time": "2018-05-22T21:18:48+00:00" }, { "name": "phar-io/manifest", @@ -2144,16 +1977,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.0.4", + "version": "6.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca" + "reference": "4cab20a326d14de7575a8e235c70d879b569a57a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/52187754b0eed0b8159f62a6fa30073327e8c2ca", - "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4cab20a326d14de7575a8e235c70d879b569a57a", + "reference": "4cab20a326d14de7575a8e235c70d879b569a57a", "shasum": "" }, "require": { @@ -2203,7 +2036,7 @@ "testing", "xunit" ], - "time": "2018-04-29T14:59:09+00:00" + "time": "2018-05-28T11:49:20+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2473,16 +2306,16 @@ }, { "name": "phpunit/phpunit-mock-objects", - "version": "6.1.1", + "version": "6.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157" + "reference": "f9756fd4f43f014cb2dca98deeaaa8ce5500a36e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/70c740bde8fd9ea9ea295be1cd875dd7b267e157", - "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/f9756fd4f43f014cb2dca98deeaaa8ce5500a36e", + "reference": "f9756fd4f43f014cb2dca98deeaaa8ce5500a36e", "shasum": "" }, "require": { @@ -2525,7 +2358,7 @@ "mock", "xunit" ], - "time": "2018-04-11T04:50:36+00:00" + "time": "2018-05-29T13:54:20+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", diff --git a/docker/xdebug.ini b/docker/xdebug.ini index 976bd78b..10bc73eb 100644 --- a/docker/xdebug.ini +++ b/docker/xdebug.ini @@ -7,5 +7,5 @@ xdebug.remote_enable=1 xdebug.remote_autostart=1 xdebug.remote_connect_back=0 xdebug.remote_mode=req -xdebug.remote_port=9000 +xdebug.remote_port=9001 xdebug.remote_host=docker.for.mac.localhost \ No newline at end of file diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..444c4479 --- /dev/null +++ b/example/README.md @@ -0,0 +1,24 @@ +# Example Protean Compliant Kōjō DLC Pattern + +SQS Queue Name: `local-bwilson` + +`bin/worker-facade.php` +```php +start(); +} catch (\Throwable $throwable) { + echo $throwable->getMessage(); +} + +return; +``` \ No newline at end of file diff --git a/example/Worker.php b/example/Worker.php deleted file mode 100644 index ee8e319a..00000000 --- a/example/Worker.php +++ /dev/null @@ -1,58 +0,0 @@ -_getWorkerQueue()->waitForNextMessage(); - - // Schedule another job of the same type. -// $this->_scheduleNextJob(); - - // Delegate the work for the first message. -// $this->_delegateWork(); -// -// // Delegate the work until the observed Queue is empty. -// while ($this->_getWorkerQueue()->hasNextMessage()) { -// $this->_delegateWork(); -// } -// - // Tell Kōjō that we are done and all is well. - $this->_getApiV1WorkerService()->requestCompleteSuccess()->applyRequest(); - - // Fluent interfaces for the love of Pete. - return $this; - } - - protected function _delegateWork(): WorkerInterface - { - $workerDelegate = $this->_getWorkerDelegateRepository()->getNewWorkerDelegate(); - $workerDelegate->setWorkerQueueMessage($this->_getWorkerQueue()->getNextMessage()); - $workerDelegate->businessLogic(); - - return $this; - } - - protected function _scheduleNextJob(): WorkerInterface - { - $newJobScheduler = $this->_getApiV1WorkerService()->getNewJobScheduler(); - $newJobScheduler->setJobTypeCode(self::JOB_TYPE_CODE) - ->setWorkAtDateTime(new \DateTime('now')) - ->save(); - - return $this; - } -} \ No newline at end of file diff --git a/example/Worker/Delegate/AwareTrait.php b/example/Worker/Delegate/AwareTrait.php deleted file mode 100644 index f4bcc1b5..00000000 --- a/example/Worker/Delegate/AwareTrait.php +++ /dev/null @@ -1,38 +0,0 @@ -_create(DelegateInterface::class, $workerDelegate); - - return $this; - } - - protected function _getWorkerDelegate(): DelegateInterface - { - return $this->_read(DelegateInterface::class); - } - - protected function _getWorkerDelegateClone(): DelegateInterface - { - return clone $this->_getWorkerDelegate(); - } - - protected function _hasWorkerDelegate(): bool - { - return $this->_exists(DelegateInterface::class); - } - - protected function _unsetWorkerDelegate(): self - { - $this->_delete(DelegateInterface::class); - - return $this; - } -} \ No newline at end of file diff --git a/example/Worker/Delegate/Factory.php b/example/Worker/Delegate/Factory.php deleted file mode 100644 index a09a1a9e..00000000 --- a/example/Worker/Delegate/Factory.php +++ /dev/null @@ -1,18 +0,0 @@ -_getWorkerDelegateClone(); - - return $workerDelegate; - } -} \ No newline at end of file diff --git a/example/Worker/Delegate/Factory/AwareTrait.php b/example/Worker/Delegate/Factory/AwareTrait.php deleted file mode 100644 index eadce7a8..00000000 --- a/example/Worker/Delegate/Factory/AwareTrait.php +++ /dev/null @@ -1,38 +0,0 @@ -_create(FactoryInterface::class, $workerDelegateFactory); - - return $this; - } - - protected function _getWorkerDelegateFactory(): FactoryInterface - { - return $this->_read(FactoryInterface::class); - } - - protected function _getWorkerDelegateFactoryClone(): FactoryInterface - { - return clone $this->_getWorkerDelegateFactory(); - } - - protected function _hasWorkerDelegateFactory(): bool - { - return $this->_exists(FactoryInterface::class); - } - - protected function _unsetWorkerDelegateFactory(): self - { - $this->_delete(FactoryInterface::class); - - return $this; - } -} \ No newline at end of file diff --git a/example/Worker/Delegate/FactoryInterface.php b/example/Worker/Delegate/FactoryInterface.php deleted file mode 100644 index 0bbcf684..00000000 --- a/example/Worker/Delegate/FactoryInterface.php +++ /dev/null @@ -1,11 +0,0 @@ -_getWorkerDelegateFactory()->create(); - } -} \ No newline at end of file diff --git a/example/Worker/Delegate/Repository/AwareTrait.php b/example/Worker/Delegate/Repository/AwareTrait.php deleted file mode 100644 index bf9269ec..00000000 --- a/example/Worker/Delegate/Repository/AwareTrait.php +++ /dev/null @@ -1,38 +0,0 @@ -_create(RepositoryInterface::class, $workerDelegateRepository); - - return $this; - } - - protected function _getWorkerDelegateRepository(): RepositoryInterface - { - return $this->_read(RepositoryInterface::class); - } - - protected function _getWorkerDelegateRepositoryClone(): RepositoryInterface - { - return clone $this->_getWorkerDelegateRepository(); - } - - protected function _hasWorkerDelegateRepository(): bool - { - return $this->_exists(RepositoryInterface::class); - } - - protected function _unsetWorkerDelegateRepository(): self - { - $this->_delete(RepositoryInterface::class); - - return $this; - } -} \ No newline at end of file diff --git a/example/Worker/Delegate/RepositoryInterface.php b/example/Worker/Delegate/RepositoryInterface.php deleted file mode 100644 index fea46b52..00000000 --- a/example/Worker/Delegate/RepositoryInterface.php +++ /dev/null @@ -1,11 +0,0 @@ -_getWorkerQueueMessageClone(); - } - - public function waitForNextMessage(): QueueInterface - { - sleep(random_int(0, 10)); - - return $this; - } - - public function hasNextMessage(): bool - { - return (random_int(0, 5) === 5); - } -} \ No newline at end of file diff --git a/example/Worker/Queue/AwareTrait.php b/example/Worker/Queue/AwareTrait.php deleted file mode 100644 index b1febb18..00000000 --- a/example/Worker/Queue/AwareTrait.php +++ /dev/null @@ -1,40 +0,0 @@ -hasWorkerQueue(), new \LogicException('NeighborhoodsKojoExampleWorkerQueue is already set.')); - $this->NeighborhoodsKojoExampleWorkerQueue = $workerQueue; - - return $this; - } - - protected function getWorkerQueue(): QueueInterface - { - assert($this->hasWorkerQueue(), new \LogicException('NeighborhoodsKojoExampleWorkerQueue is not set.')); - - return $this->NeighborhoodsKojoExampleWorkerQueue; - } - - protected function hasWorkerQueue(): bool - { - return isset($this->NeighborhoodsKojoExampleWorkerQueue); - } - - protected function unsetWorkerQueue(): self - { - assert($this->hasWorkerQueue(), new \LogicException('NeighborhoodsKojoExampleWorkerQueue is not set.')); - unset($this->NeighborhoodsKojoExampleWorkerQueue); - - return $this; - } -} diff --git a/example/Worker/Queue/Message.php b/example/Worker/Queue/Message.php deleted file mode 100644 index 20378efa..00000000 --- a/example/Worker/Queue/Message.php +++ /dev/null @@ -1,8 +0,0 @@ -_create(MessageInterface::class, $workerQueueMessage); - - return $this; - } - - protected function getWorkerQueueMessage(): MessageInterface - { - return $this->_read(MessageInterface::class); - } - - protected function hasWorkerQueueMessage(): bool - { - return $this->_exists(MessageInterface::class); - } - - protected function unsetWorkerQueueMessage(): self - { - $this->_delete(MessageInterface::class); - - return $this; - } -} diff --git a/example/Worker/Queue/Message/Factory.php b/example/Worker/Queue/Message/Factory.php deleted file mode 100644 index cff8881f..00000000 --- a/example/Worker/Queue/Message/Factory.php +++ /dev/null @@ -1,19 +0,0 @@ -getWorkerQueueMessage(); - } -} diff --git a/example/Worker/Queue/MessageInterface.php b/example/Worker/Queue/MessageInterface.php deleted file mode 100644 index 7ed9d952..00000000 --- a/example/Worker/Queue/MessageInterface.php +++ /dev/null @@ -1,9 +0,0 @@ - 'us-east-1'] +); + +$totalNumberOfMessagesToSend = 12000; +$messageCount = 0; +while ($messageCount !== $totalNumberOfMessagesToSend) { + $client->sendMessage(array( + 'QueueUrl' => 'https://sqs.us-east-1.amazonaws.com/272157948465/local-bwilson', + 'MessageBody' => 'MESSAGE BODY', + )); + + ++$messageCount; +} + +return; \ No newline at end of file diff --git a/example/bin/worker-facade.php b/example/bin/worker-facade.php new file mode 100644 index 00000000..87814255 --- /dev/null +++ b/example/bin/worker-facade.php @@ -0,0 +1,17 @@ +start(); +} catch (\Throwable $throwable) { + echo $throwable->getMessage(); +} + +return; \ No newline at end of file diff --git a/example/composer.json b/example/composer.json new file mode 100644 index 00000000..4194cd66 --- /dev/null +++ b/example/composer.json @@ -0,0 +1,35 @@ +{ + "name": "neighborhoods/kojo_example", + "type": "library", + "description": "Neighborhoods Kōjō Example provides an example of using kōjō and protean.", + "license": "proprietary", + "keywords": [], + "authors": [ + { + "name": "Brad Wilson", + "email": "brad.wilson@neighborhoods.com" + } + ], + "repositories": [ + { + "type": "composer", + "url": "https://satis.neighborhoods.com" + } + ], + "require": { + "php": ">=7.1", + "neighborhoods/kojo": "^2.0.0", + "neighborhoods/pylon": "^1.0.0", + "aws/aws-sdk-php": "2.*" + }, + "require-dev": { + "php": ">=7.1", + "neighborhoods/scaffolding": "^1.0.0" + }, + "autoload": { + "psr-4": { + "Neighborhoods\\KojoExample\\": "src", + "Neighborhoods\\KojoExampleTest\\": "tests" + } + } +} \ No newline at end of file diff --git a/example/src/V1/Aws/Sqs/SqsClient.yml b/example/src/V1/Aws/Sqs/SqsClient.yml new file mode 100644 index 00000000..92830f07 --- /dev/null +++ b/example/src/V1/Aws/Sqs/SqsClient.yml @@ -0,0 +1,14 @@ +parameters: + neighborhoods.kojo_example.v1.aws.sqs.sqs_client.region: '%env(SQS_REGION)%' +services: + neighborhoods.kojo_example.v1.aws.sqs.sqs_client: + class: Aws\Sqs\SqsClient + public: false + shared: false + factory: [Aws\Sqs\SqsClient, factory] + arguments: + - + region: '%neighborhoods.kojo_example.v1.aws.sqs.sqs_client.region%' + v1.aws.sqs.sqs_client: + alias: neighborhoods.kojo_example.v1.aws.sqs.sqs_client + public: false \ No newline at end of file diff --git a/example/src/V1/Aws/Sqs/SqsClient/AwareTrait.php b/example/src/V1/Aws/Sqs/SqsClient/AwareTrait.php new file mode 100644 index 00000000..0dbc8a15 --- /dev/null +++ b/example/src/V1/Aws/Sqs/SqsClient/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1AwsSqsSqsClient(), + new \LogicException('NeighborhoodsKojoExampleV1AwsSqsSqsClient is already set.')); + $this->NeighborhoodsKojoExampleV1AwsSqsSqsClient = $v1AwsSqsSqsClient; + + return $this; + } + + protected function getV1AwsSqsSqsClient(): SqsClient + { + assert($this->hasV1AwsSqsSqsClient(), + new \LogicException('NeighborhoodsKojoExampleV1AwsSqsSqsClient is not set.')); + + return $this->NeighborhoodsKojoExampleV1AwsSqsSqsClient; + } + + protected function hasV1AwsSqsSqsClient(): bool + { + return isset($this->NeighborhoodsKojoExampleV1AwsSqsSqsClient); + } + + protected function unsetV1AwsSqsSqsClient(): self + { + assert($this->hasV1AwsSqsSqsClient(), + new \LogicException('NeighborhoodsKojoExampleV1AwsSqsSqsClient is not set.')); + unset($this->NeighborhoodsKojoExampleV1AwsSqsSqsClient); + + return $this; + } +} diff --git a/example/src/V1/Environment/Parameters.yml b/example/src/V1/Environment/Parameters.yml new file mode 100644 index 00000000..ede295d8 --- /dev/null +++ b/example/src/V1/Environment/Parameters.yml @@ -0,0 +1,16 @@ +parameters: +# Redis. + neighborhoods.kojo.environment.parameters.redis_port: '%env(REDIS_PORT)%' + neighborhoods.kojo.environment.parameters.redis_host: '%env(REDIS_HOST)%' +# MySQL. +# neighborhoods.kojo.environment.parameters.database_user_name: '%env(DATABASE_USERNAME)%' +# neighborhoods.kojo.environment.parameters.database_password: '%env(DATABASE_PASSWORD)%' +# neighborhoods.kojo.environment.parameters.database_adapter: '%env(DATABASE_ADAPTER)%' +# neighborhoods.kojo.environment.parameters.database_host: '%env(DATABASE_HOST)%' +# neighborhoods.kojo.environment.parameters.database_name: '%env(DATABASE_NAME)%' +# Postgres. + neighborhoods.kojo.environment.parameters.database_user_name: 'nhds' + neighborhoods.kojo.environment.parameters.database_password: 'nhds2016' + neighborhoods.kojo.environment.parameters.database_adapter: 'pgsql' + neighborhoods.kojo.environment.parameters.database_host: 'pgsql' + neighborhoods.kojo.environment.parameters.database_name: 'kojo' \ No newline at end of file diff --git a/example/src/V1/Guzzle/Service/Resource/Model/AwareTrait.php b/example/src/V1/Guzzle/Service/Resource/Model/AwareTrait.php new file mode 100644 index 00000000..b3f6d5da --- /dev/null +++ b/example/src/V1/Guzzle/Service/Resource/Model/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1GuzzleServiceResourceModel(), + new \LogicException('NeighborhoodsKojoExampleV1GuzzleServiceResourceModel is already set.')); + $this->NeighborhoodsKojoExampleV1GuzzleServiceResourceModel = $v1GuzzleServiceResourceModel; + + return $this; + } + + protected function getV1GuzzleServiceResourceModel(): Model + { + assert($this->hasV1GuzzleServiceResourceModel(), + new \LogicException('NeighborhoodsKojoExampleV1GuzzleServiceResourceModel is not set.')); + + return $this->NeighborhoodsKojoExampleV1GuzzleServiceResourceModel; + } + + protected function hasV1GuzzleServiceResourceModel(): bool + { + return isset($this->NeighborhoodsKojoExampleV1GuzzleServiceResourceModel); + } + + protected function unsetV1GuzzleServiceResourceModel(): self + { + assert($this->hasV1GuzzleServiceResourceModel(), + new \LogicException('NeighborhoodsKojoExampleV1GuzzleServiceResourceModel is not set.')); + unset($this->NeighborhoodsKojoExampleV1GuzzleServiceResourceModel); + + return $this; + } +} diff --git a/example/src/V1/Worker.php b/example/src/V1/Worker.php new file mode 100644 index 00000000..2288a678 --- /dev/null +++ b/example/src/V1/Worker.php @@ -0,0 +1,58 @@ +getApiV1WorkerService()->getTimesCrashed() === 0) { + // Wait for one message to become available. + if($this->getV1WorkerQueue()->hasNextMessage()){ + // Schedule another kōjō job of the same type. + $this->_scheduleNextJob(); + + // Delegate the work for the first message. + $this->_delegateWork(); + + // Delegate the work until the observed Queue is empty. + while ($this->getV1WorkerQueue()->hasNextMessage()) { + $this->_delegateWork(); + } + } + } + + // Tell Kōjō that we are done and all is well. + $this->getApiV1WorkerService()->requestCompleteSuccess()->applyRequest(); + + // Fluent interfaces for the love of Pete. + return $this; + } + + protected function _delegateWork(): WorkerInterface + { + $workerDelegate = $this->getV1WorkerDelegateRepository()->getV1NewWorkerDelegate(); + $workerDelegate->setV1WorkerQueueMessage($this->getV1WorkerQueue()->getNextMessage()); + $workerDelegate->businessLogic(); + + return $this; + } + + protected function _scheduleNextJob(): WorkerInterface + { + $newJobScheduler = $this->getApiV1WorkerService()->getNewJobScheduler(); + $newJobScheduler->setJobTypeCode(self::JOB_TYPE_CODE) + ->setWorkAtDateTime(new \DateTime('now')) + ->save(); + + return $this; + } +} \ No newline at end of file diff --git a/example/src/V1/Worker.yml b/example/src/V1/Worker.yml new file mode 100644 index 00000000..63878827 --- /dev/null +++ b/example/src/V1/Worker.yml @@ -0,0 +1,8 @@ +services: + neighborhoods.kojo_example.v1.worker: + class: Neighborhoods\KojoExample\V1\Worker + public: true + shared: false + calls: + - [setV1WorkerDelegateRepository, ['@neighborhoods.kojo_example.v1.worker.delegate.repository']] + - [setV1WorkerQueue, ['@neighborhoods.kojo_example.v1.worker.queue']] \ No newline at end of file diff --git a/example/Worker/Delegate.php b/example/src/V1/Worker/Delegate.php similarity index 57% rename from example/Worker/Delegate.php rename to example/src/V1/Worker/Delegate.php index 21791e0d..25b874ef 100644 --- a/example/Worker/Delegate.php +++ b/example/src/V1/Worker/Delegate.php @@ -1,18 +1,18 @@ getV1WorkerQueueMessage()->delete(); + return $this; } } \ No newline at end of file diff --git a/example/src/V1/Worker/Delegate.yml b/example/src/V1/Worker/Delegate.yml new file mode 100644 index 00000000..f08d63fa --- /dev/null +++ b/example/src/V1/Worker/Delegate.yml @@ -0,0 +1,5 @@ +services: + neighborhoods.kojo_example.v1.worker.delegate: + class: Neighborhoods\KojoExample\V1\Worker\Delegate + public: false + shared: false \ No newline at end of file diff --git a/example/src/V1/Worker/Delegate/AwareTrait.php b/example/src/V1/Worker/Delegate/AwareTrait.php new file mode 100644 index 00000000..23826c9c --- /dev/null +++ b/example/src/V1/Worker/Delegate/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1WorkerDelegate(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegate is already set.')); + $this->NeighborhoodsKojoExampleV1WorkerDelegate = $v1WorkerDelegate; + + return $this; + } + + protected function getV1WorkerDelegate(): DelegateInterface + { + assert($this->hasV1WorkerDelegate(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegate is not set.')); + + return $this->NeighborhoodsKojoExampleV1WorkerDelegate; + } + + protected function hasV1WorkerDelegate(): bool + { + return isset($this->NeighborhoodsKojoExampleV1WorkerDelegate); + } + + protected function unsetV1WorkerDelegate(): self + { + assert($this->hasV1WorkerDelegate(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegate is not set.')); + unset($this->NeighborhoodsKojoExampleV1WorkerDelegate); + + return $this; + } +} diff --git a/example/src/V1/Worker/Delegate/Factory.php b/example/src/V1/Worker/Delegate/Factory.php new file mode 100644 index 00000000..5adcc8cd --- /dev/null +++ b/example/src/V1/Worker/Delegate/Factory.php @@ -0,0 +1,17 @@ +getV1WorkerDelegate(); + } +} diff --git a/example/src/V1/Worker/Delegate/Factory.yml b/example/src/V1/Worker/Delegate/Factory.yml new file mode 100644 index 00000000..3b2fc298 --- /dev/null +++ b/example/src/V1/Worker/Delegate/Factory.yml @@ -0,0 +1,7 @@ +services: + neighborhoods.kojo_example.v1.worker.delegate.factory: + class: Neighborhoods\KojoExample\V1\Worker\Delegate\Factory + public: false + shared: true + calls: + - [setV1WorkerDelegate, ['@neighborhoods.kojo_example.v1.worker.delegate']] \ No newline at end of file diff --git a/example/src/V1/Worker/Delegate/Factory/AwareTrait.php b/example/src/V1/Worker/Delegate/Factory/AwareTrait.php new file mode 100644 index 00000000..8266cb66 --- /dev/null +++ b/example/src/V1/Worker/Delegate/Factory/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1WorkerDelegateFactory(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegateFactory is already set.')); + $this->NeighborhoodsKojoExampleV1WorkerDelegateFactory = $v1WorkerDelegateFactory; + + return $this; + } + + protected function getV1WorkerDelegateFactory(): FactoryInterface + { + assert($this->hasV1WorkerDelegateFactory(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegateFactory is not set.')); + + return $this->NeighborhoodsKojoExampleV1WorkerDelegateFactory; + } + + protected function hasV1WorkerDelegateFactory(): bool + { + return isset($this->NeighborhoodsKojoExampleV1WorkerDelegateFactory); + } + + protected function unsetV1WorkerDelegateFactory(): self + { + assert($this->hasV1WorkerDelegateFactory(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegateFactory is not set.')); + unset($this->NeighborhoodsKojoExampleV1WorkerDelegateFactory); + + return $this; + } +} diff --git a/example/src/V1/Worker/Delegate/FactoryInterface.php b/example/src/V1/Worker/Delegate/FactoryInterface.php new file mode 100644 index 00000000..b3923c18 --- /dev/null +++ b/example/src/V1/Worker/Delegate/FactoryInterface.php @@ -0,0 +1,11 @@ +getV1WorkerDelegateFactory()->create(); + } +} \ No newline at end of file diff --git a/example/src/V1/Worker/Delegate/Repository.yml b/example/src/V1/Worker/Delegate/Repository.yml new file mode 100644 index 00000000..a79f5be0 --- /dev/null +++ b/example/src/V1/Worker/Delegate/Repository.yml @@ -0,0 +1,7 @@ +services: + neighborhoods.kojo_example.v1.worker.delegate.repository: + class: Neighborhoods\KojoExample\V1\Worker\Delegate\Repository + public: false + shared: true + calls: + - [setV1WorkerDelegateFactory, ['@neighborhoods.kojo_example.v1.worker.delegate.factory']] \ No newline at end of file diff --git a/example/src/V1/Worker/Delegate/Repository/AwareTrait.php b/example/src/V1/Worker/Delegate/Repository/AwareTrait.php new file mode 100644 index 00000000..4661861b --- /dev/null +++ b/example/src/V1/Worker/Delegate/Repository/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1WorkerDelegateRepository(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegateRepository is already set.')); + $this->NeighborhoodsKojoExampleV1WorkerDelegateRepository = $v1WorkerDelegateRepository; + + return $this; + } + + protected function getV1WorkerDelegateRepository(): RepositoryInterface + { + assert($this->hasV1WorkerDelegateRepository(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegateRepository is not set.')); + + return $this->NeighborhoodsKojoExampleV1WorkerDelegateRepository; + } + + protected function hasV1WorkerDelegateRepository(): bool + { + return isset($this->NeighborhoodsKojoExampleV1WorkerDelegateRepository); + } + + protected function unsetV1WorkerDelegateRepository(): self + { + assert($this->hasV1WorkerDelegateRepository(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerDelegateRepository is not set.')); + unset($this->NeighborhoodsKojoExampleV1WorkerDelegateRepository); + + return $this; + } +} diff --git a/example/src/V1/Worker/Delegate/RepositoryInterface.php b/example/src/V1/Worker/Delegate/RepositoryInterface.php new file mode 100644 index 00000000..cd841796 --- /dev/null +++ b/example/src/V1/Worker/Delegate/RepositoryInterface.php @@ -0,0 +1,11 @@ +bootstrap(); + $this->getWorker()->work(); + + return $this; + } + + protected function bootstrap(): FacadeInterface + { + if ($this->isBootStrapped !== false) { + throw new \LogicException('Worker facade is already bootstrapped.'); + } + $containerBuilderFacade = $this->getContainerBuilderFacade(); + $discoverableDirectories[] = __DIR__ . '/../../../src'; + $finder = new Finder(); + $finder->name('*.yml'); + $finder->files()->in($discoverableDirectories); + $containerBuilderFacade->addFinder($finder); + $containerBuilder = $containerBuilderFacade->getContainerBuilder(); + $this->setWorker($containerBuilder->get('neighborhoods.kojo_example.v1.worker')); + $this->isBootStrapped = true; + + return $this; + } + + public function getContainerBuilderFacade(): DependencyInjection\ContainerBuilder\FacadeInterface + { + if ($this->containerBuilderFacade === null) { + $this->containerBuilderFacade = new DependencyInjection\ContainerBuilder\Facade(); + } + + return $this->containerBuilderFacade; + } + + protected function getWorker(): WorkerInterface + { + if ($this->worker === null) { + throw new \LogicException('Worker is not set.'); + } + + return $this->worker; + } + + protected function setWorker(WorkerInterface $worker): FacadeInterface + { + if ($this->worker !== null) { + throw new \LogicException('Worker is already set.'); + } + $this->worker = $worker->setApiV1WorkerService($this->getApiV1WorkerService()); + + return $this; + } +} \ No newline at end of file diff --git a/example/src/V1/Worker/FacadeInterface.php b/example/src/V1/Worker/FacadeInterface.php new file mode 100644 index 00000000..f295e348 --- /dev/null +++ b/example/src/V1/Worker/FacadeInterface.php @@ -0,0 +1,9 @@ +getV1WorkerQueueMessage(); + $this->unsetV1WorkerQueueMessage(); + + return $v1WorkerQueueMessage; + } + + public function waitForNextMessage(): QueueInterface + { + $guzzleServiceResourceModel = $this->receiveMessage(); + while ($guzzleServiceResourceModel->get(self::MESSAGES) === null) { + $guzzleServiceResourceModel = $this->receiveMessage(); + } + $this->createNextMessage($guzzleServiceResourceModel); + + return $this; + } + + public function hasNextMessage(): bool + { + if (!$this->hasV1WorkerQueueMessage()) { + $guzzleServiceResourceModel = $this->receiveMessage(); + if ($guzzleServiceResourceModel->get(self::MESSAGES) !== null) { + $this->createNextMessage($guzzleServiceResourceModel); + } + } + + return $this->hasV1WorkerQueueMessage(); + } + + protected function createNextMessage(Model $guzzleServiceResourceModel): QueueInterface + { + $v1WorkerQueueMessage = $this->getV1WorkerQueueMessageFactory()->create(); + $v1WorkerQueueMessage->setV1GuzzleServiceResourceModel($guzzleServiceResourceModel); + $this->setV1WorkerQueueMessage($v1WorkerQueueMessage); + + return $this; + } + + protected function receiveMessage(): Model + { + return $this->getV1AwsSqsSqsClient()->receiveMessage( + [ + self::QUEUE_URL => $this->getQueueUrl(), + self::WAIT_TIME_SECONDS => 20, + ] + ); + } + + public function setQueueUrl(string $queueUrl): QueueInterface + { + if ($this->queueUrl === null) { + $this->queueUrl = $queueUrl; + } else { + throw new \LogicException('Queue URL is already set.'); + } + + return $this; + } + + protected function getQueueUrl(): string + { + if ($this->queueUrl === null) { + throw new \LogicException('Queue URL is not set.'); + } + + return $this->queueUrl; + } + + public function setNumberOfPollCycles(int $numberOfPollCycles): QueueInterface + { + // TODO: Implement setNumberOfPollCycles() method. + } +} \ No newline at end of file diff --git a/example/src/V1/Worker/Queue.yml b/example/src/V1/Worker/Queue.yml new file mode 100644 index 00000000..1c3dd238 --- /dev/null +++ b/example/src/V1/Worker/Queue.yml @@ -0,0 +1,14 @@ +parameters: + neighborhoods.kojo_example.v1.worker.queue.queue_url: 'https://sqs.us-east-1.amazonaws.com/272157948465/local-bwilson' +services: + neighborhoods.kojo_example.v1.worker.queue: + class: Neighborhoods\KojoExample\V1\Worker\Queue + public: true + shared: false + calls: + - [setV1WorkerQueueMessageFactory, ['@v1.worker.queue.message.factory']] + - [setV1AwsSqsSqsClient, ['@v1.aws.sqs.sqs_client']] + - [setQueueUrl, ['%neighborhoods.kojo_example.v1.worker.queue.queue_url%']] + v1.worker.queue: + alias: neighborhoods.kojo_example.v1.worker.queue + public: true \ No newline at end of file diff --git a/example/src/V1/Worker/Queue/AwareTrait.php b/example/src/V1/Worker/Queue/AwareTrait.php new file mode 100644 index 00000000..718def0b --- /dev/null +++ b/example/src/V1/Worker/Queue/AwareTrait.php @@ -0,0 +1,41 @@ +hasV1WorkerQueue(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueue is already set.')); + $this->NeighborhoodsKojoExampleV1WorkerQueue = $v1WorkerQueue; + + return $this; + } + + protected function getV1WorkerQueue(): QueueInterface + { + assert($this->hasV1WorkerQueue(), new \LogicException('NeighborhoodsKojoExampleV1WorkerQueue is not set.')); + + return $this->NeighborhoodsKojoExampleV1WorkerQueue; + } + + protected function hasV1WorkerQueue(): bool + { + return isset($this->NeighborhoodsKojoExampleV1WorkerQueue); + } + + protected function unsetV1WorkerQueue(): self + { + assert($this->hasV1WorkerQueue(), new \LogicException('NeighborhoodsKojoExampleV1WorkerQueue is not set.')); + unset($this->NeighborhoodsKojoExampleV1WorkerQueue); + + return $this; + } +} diff --git a/example/src/V1/Worker/Queue/Message.php b/example/src/V1/Worker/Queue/Message.php new file mode 100644 index 00000000..46555af0 --- /dev/null +++ b/example/src/V1/Worker/Queue/Message.php @@ -0,0 +1,52 @@ +isDeleted !== false) { + throw new \LogicException('Message is already deleted.'); + } + $messages = $this->getV1GuzzleServiceResourceModel()->get('Messages'); + $receiptHandle = $messages[0][self::SQS_CLIENT_RECEIPT_HANDLE]; + $this->getV1AwsSqsSqsClient()->deleteMessage([ + self::SQS_CLIENT_QUEUE_URL => $this->getQueueUrl(), + self::SQS_CLIENT_RECEIPT_HANDLE => $receiptHandle, + ]); + $this->isDeleted = true; + + return $this; + } + + protected function getQueueUrl() + { + if ($this->queueUrl === null) { + throw new \LogicException('Queue URL has not been set.'); + } + + return $this->queueUrl; + } + + public function setQueueUrl($queueUrl): MessageInterface + { + if ($this->queueUrl !== null) { + throw new \LogicException('Queue URL already set.'); + } + $this->queueUrl = $queueUrl; + + return $this; + } +} \ No newline at end of file diff --git a/example/src/V1/Worker/Queue/Message.yml b/example/src/V1/Worker/Queue/Message.yml new file mode 100644 index 00000000..76ee5215 --- /dev/null +++ b/example/src/V1/Worker/Queue/Message.yml @@ -0,0 +1,11 @@ +services: + neighborhoods.kojo_example.v1.worker.queue.message: + class: Neighborhoods\KojoExample\V1\Worker\Queue\Message + public: false + shared: false + calls: + - [setV1AwsSqsSqsClient, ['@v1.aws.sqs.sqs_client']] + - [setQueueUrl, ['%neighborhoods.kojo_example.v1.worker.queue.queue_url%']] + v1.worker.queue.message: + alias: neighborhoods.kojo_example.v1.worker.queue.message + public: true \ No newline at end of file diff --git a/example/src/V1/Worker/Queue/Message/AwareTrait.php b/example/src/V1/Worker/Queue/Message/AwareTrait.php new file mode 100644 index 00000000..f375d4db --- /dev/null +++ b/example/src/V1/Worker/Queue/Message/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1WorkerQueueMessage(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueueMessage is already set.')); + $this->NeighborhoodsKojoExampleV1WorkerQueueMessage = $v1WorkerQueueMessage; + + return $this; + } + + protected function getV1WorkerQueueMessage(): MessageInterface + { + assert($this->hasV1WorkerQueueMessage(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueueMessage is not set.')); + + return $this->NeighborhoodsKojoExampleV1WorkerQueueMessage; + } + + protected function hasV1WorkerQueueMessage(): bool + { + return isset($this->NeighborhoodsKojoExampleV1WorkerQueueMessage); + } + + protected function unsetV1WorkerQueueMessage(): self + { + assert($this->hasV1WorkerQueueMessage(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueueMessage is not set.')); + unset($this->NeighborhoodsKojoExampleV1WorkerQueueMessage); + + return $this; + } +} diff --git a/example/src/V1/Worker/Queue/Message/Factory.php b/example/src/V1/Worker/Queue/Message/Factory.php new file mode 100644 index 00000000..24705e2b --- /dev/null +++ b/example/src/V1/Worker/Queue/Message/Factory.php @@ -0,0 +1,19 @@ +getV1WorkerQueueMessage(); + } +} diff --git a/example/src/V1/Worker/Queue/Message/Factory.yml b/example/src/V1/Worker/Queue/Message/Factory.yml new file mode 100644 index 00000000..f114f523 --- /dev/null +++ b/example/src/V1/Worker/Queue/Message/Factory.yml @@ -0,0 +1,10 @@ +services: + neighborhoods.kojo_example.v1.worker.queue.message.factory: + class: Neighborhoods\KojoExample\V1\Worker\Queue\Message\Factory + public: false + shared: true + calls: + - [setV1WorkerQueueMessage, ['@v1.worker.queue.message']] + v1.worker.queue.message.factory: + alias: neighborhoods.kojo_example.v1.worker.queue.message.factory + public: true \ No newline at end of file diff --git a/example/src/V1/Worker/Queue/Message/Factory/AwareTrait.php b/example/src/V1/Worker/Queue/Message/Factory/AwareTrait.php new file mode 100644 index 00000000..a25f71f6 --- /dev/null +++ b/example/src/V1/Worker/Queue/Message/Factory/AwareTrait.php @@ -0,0 +1,43 @@ +hasV1WorkerQueueMessageFactory(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueueMessageFactory is already set.')); + $this->NeighborhoodsKojoExampleV1WorkerQueueMessageFactory = $v1WorkerQueueMessageFactory; + + return $this; + } + + protected function getV1WorkerQueueMessageFactory(): FactoryInterface + { + assert($this->hasV1WorkerQueueMessageFactory(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueueMessageFactory is not set.')); + + return $this->NeighborhoodsKojoExampleV1WorkerQueueMessageFactory; + } + + protected function hasV1WorkerQueueMessageFactory(): bool + { + return isset($this->NeighborhoodsKojoExampleV1WorkerQueueMessageFactory); + } + + protected function unsetV1WorkerQueueMessageFactory(): self + { + assert($this->hasV1WorkerQueueMessageFactory(), + new \LogicException('NeighborhoodsKojoExampleV1WorkerQueueMessageFactory is not set.')); + unset($this->NeighborhoodsKojoExampleV1WorkerQueueMessageFactory); + + return $this; + } +} diff --git a/example/Worker/Queue/Message/FactoryInterface.php b/example/src/V1/Worker/Queue/Message/FactoryInterface.php similarity index 52% rename from example/Worker/Queue/Message/FactoryInterface.php rename to example/src/V1/Worker/Queue/Message/FactoryInterface.php index c7cd3d80..87f58787 100644 --- a/example/Worker/Queue/Message/FactoryInterface.php +++ b/example/src/V1/Worker/Queue/Message/FactoryInterface.php @@ -1,9 +1,9 @@ _create(SchedulerInterface::class, $apiV1JobScheduler); + assert(!$this->hasApiV1JobScheduler(), + new \LogicException('NeighborhoodsKojoApiV1JobScheduler is already set.')); + $this->NeighborhoodsKojoApiV1JobScheduler = $apiV1JobScheduler; return $this; } - protected function _getApiV1JobScheduler(): SchedulerInterface + protected function getApiV1JobScheduler(): SchedulerInterface { - return $this->_read(SchedulerInterface::class); - } + assert($this->hasApiV1JobScheduler(), new \LogicException('NeighborhoodsKojoApiV1JobScheduler is not set.')); - protected function _getApiV1JobSchedulerClone(): SchedulerInterface - { - return clone $this->_getApiV1JobScheduler(); + return $this->NeighborhoodsKojoApiV1JobScheduler; } - protected function _hasApiV1JobScheduler(): bool + protected function hasApiV1JobScheduler(): bool { - return $this->_exists(SchedulerInterface::class); + return isset($this->NeighborhoodsKojoApiV1JobScheduler); } - protected function _unsetApiV1JobScheduler(): self + protected function unsetApiV1JobScheduler(): self { - $this->_delete(SchedulerInterface::class); + assert($this->hasApiV1JobScheduler(), new \LogicException('NeighborhoodsKojoApiV1JobScheduler is not set.')); + unset($this->NeighborhoodsKojoApiV1JobScheduler); return $this; } -} \ No newline at end of file +} diff --git a/src/Api/V1/Job/Scheduler/Factory.php b/src/Api/V1/Job/Scheduler/Factory.php index acbd2528..e43157ea 100644 --- a/src/Api/V1/Job/Scheduler/Factory.php +++ b/src/Api/V1/Job/Scheduler/Factory.php @@ -15,7 +15,7 @@ class Factory extends FactoryAbstract implements FactoryInterface public function create(): SchedulerInterface { - $apiV1JobScheduler = $this->_getApiV1JobSchedulerClone(); + $apiV1JobScheduler = clone $this->getApiV1JobScheduler(); $apiV1JobScheduler->setServiceCreate($this->_getServiceCreateFactory()->create()); return $apiV1JobScheduler; diff --git a/src/Api/V1/Job/Scheduler/Factory/AwareTrait.php b/src/Api/V1/Job/Scheduler/Factory/AwareTrait.php index b74c6095..cb6ee0c2 100644 --- a/src/Api/V1/Job/Scheduler/Factory/AwareTrait.php +++ b/src/Api/V1/Job/Scheduler/Factory/AwareTrait.php @@ -5,34 +5,39 @@ use Neighborhoods\Kojo\Api\V1\Job\Scheduler\FactoryInterface; +/** @codeCoverageIgnore */ trait AwareTrait { + protected $NeighborhoodsKojoApiV1JobSchedulerFactory; + public function setApiV1JobSchedulerFactory(FactoryInterface $apiV1JobSchedulerFactory): self { - $this->_create(FactoryInterface::class, $apiV1JobSchedulerFactory); + assert(!$this->hasApiV1JobSchedulerFactory(), + new \LogicException('NeighborhoodsKojoApiV1JobSchedulerFactory is already set.')); + $this->NeighborhoodsKojoApiV1JobSchedulerFactory = $apiV1JobSchedulerFactory; return $this; } - protected function _getApiV1JobSchedulerFactoryClone(): FactoryInterface + protected function getApiV1JobSchedulerFactory(): FactoryInterface { - return clone $this->_getApiV1JobSchedulerFactory(); - } + assert($this->hasApiV1JobSchedulerFactory(), + new \LogicException('NeighborhoodsKojoApiV1JobSchedulerFactory is not set.')); - protected function _getApiV1JobSchedulerFactory(): FactoryInterface - { - return $this->_read(FactoryInterface::class); + return $this->NeighborhoodsKojoApiV1JobSchedulerFactory; } - protected function _hasApiV1JobSchedulerFactory(): bool + protected function hasApiV1JobSchedulerFactory(): bool { - return $this->_exists(FactoryInterface::class); + return isset($this->NeighborhoodsKojoApiV1JobSchedulerFactory); } - protected function _unsetApiV1JobSchedulerFactory(): self + protected function unsetApiV1JobSchedulerFactory(): self { - $this->_delete(FactoryInterface::class); + assert($this->hasApiV1JobSchedulerFactory(), + new \LogicException('NeighborhoodsKojoApiV1JobSchedulerFactory is not set.')); + unset($this->NeighborhoodsKojoApiV1JobSchedulerFactory); return $this; } -} \ No newline at end of file +} diff --git a/src/Api/V1/Job/Type/Registrar/AwareTrait.php b/src/Api/V1/Job/Type/Registrar/AwareTrait.php index 62074c44..510238fa 100644 --- a/src/Api/V1/Job/Type/Registrar/AwareTrait.php +++ b/src/Api/V1/Job/Type/Registrar/AwareTrait.php @@ -5,34 +5,39 @@ use Neighborhoods\Kojo\Api\V1\Job\Type\RegistrarInterface; +/** @codeCoverageIgnore */ trait AwareTrait { - public function setApiV1JobTypeRegistrar(RegistrarInterface $ApiV1JobTypeRegistrar): self + protected $NeighborhoodsKojoApiV1JobTypeRegistrar; + + public function setApiV1JobTypeRegistrar(RegistrarInterface $apiV1JobTypeRegistrar): self { - $this->_create(RegistrarInterface::class, $ApiV1JobTypeRegistrar); + assert(!$this->hasApiV1JobTypeRegistrar(), + new \LogicException('NeighborhoodsKojoApiV1JobTypeRegistrar is already set.')); + $this->NeighborhoodsKojoApiV1JobTypeRegistrar = $apiV1JobTypeRegistrar; return $this; } - protected function _getApiV1JobTypeRegistrar(): RegistrarInterface + protected function getApiV1JobTypeRegistrar(): RegistrarInterface { - return $this->_read(RegistrarInterface::class); - } + assert($this->hasApiV1JobTypeRegistrar(), + new \LogicException('NeighborhoodsKojoApiV1JobTypeRegistrar is not set.')); - protected function _getApiV1JobTypeRegistrarClone(): RegistrarInterface - { - return clone $this->_getApiV1JobTypeRegistrar(); + return $this->NeighborhoodsKojoApiV1JobTypeRegistrar; } - protected function _hasApiV1JobTypeRegistrar(): bool + protected function hasApiV1JobTypeRegistrar(): bool { - return $this->_exists(RegistrarInterface::class); + return isset($this->NeighborhoodsKojoApiV1JobTypeRegistrar); } - protected function _unsetApiV1JobTypeRegistrar(): self + protected function unsetApiV1JobTypeRegistrar(): self { - $this->_delete(RegistrarInterface::class); + assert($this->hasApiV1JobTypeRegistrar(), + new \LogicException('NeighborhoodsKojoApiV1JobTypeRegistrar is not set.')); + unset($this->NeighborhoodsKojoApiV1JobTypeRegistrar); return $this; } -} \ No newline at end of file +} diff --git a/src/Api/V1/Job/Type/Registrar/Factory.php b/src/Api/V1/Job/Type/Registrar/Factory.php index 280d9ba8..d8f84bc0 100644 --- a/src/Api/V1/Job/Type/Registrar/Factory.php +++ b/src/Api/V1/Job/Type/Registrar/Factory.php @@ -12,7 +12,7 @@ class Factory extends FactoryAbstract implements FactoryInterface public function create(): RegistrarInterface { - $apiV1JobTypeRegistrar = $this->_getApiV1JobTypeRegistrarClone(); + $apiV1JobTypeRegistrar = clone $this->getApiV1JobTypeRegistrar(); return $apiV1JobTypeRegistrar; } diff --git a/src/Api/V1/Job/Type/Registrar/Factory/AwareTrait.php b/src/Api/V1/Job/Type/Registrar/Factory/AwareTrait.php index c476dd8d..3bac41ea 100644 --- a/src/Api/V1/Job/Type/Registrar/Factory/AwareTrait.php +++ b/src/Api/V1/Job/Type/Registrar/Factory/AwareTrait.php @@ -5,34 +5,39 @@ use Neighborhoods\Kojo\Api\V1\Job\Type\Registrar\FactoryInterface; +/** @codeCoverageIgnore */ trait AwareTrait { + protected $NeighborhoodsKojoApiV1JobTypeRegistrarFactory; + public function setApiV1JobTypeRegistrarFactory(FactoryInterface $apiV1JobTypeRegistrarFactory): self { - $this->_create(FactoryInterface::class, $apiV1JobTypeRegistrarFactory); + assert(!$this->hasApiV1JobTypeRegistrarFactory(), + new \LogicException('NeighborhoodsKojoApiV1JobTypeRegistrarFactory is already set.')); + $this->NeighborhoodsKojoApiV1JobTypeRegistrarFactory = $apiV1JobTypeRegistrarFactory; return $this; } - protected function _getApiV1JobTypeRegistrarFactory(): FactoryInterface + protected function getApiV1JobTypeRegistrarFactory(): FactoryInterface { - return $this->_read(FactoryInterface::class); - } + assert($this->hasApiV1JobTypeRegistrarFactory(), + new \LogicException('NeighborhoodsKojoApiV1JobTypeRegistrarFactory is not set.')); - protected function _getApiV1JobTypeRegistrarFactoryClone(): FactoryInterface - { - return clone $this->_getApiV1JobTypeRegistrarFactory(); + return $this->NeighborhoodsKojoApiV1JobTypeRegistrarFactory; } - protected function _hasApiV1JobTypeRegistrarFactory(): bool + protected function hasApiV1JobTypeRegistrarFactory(): bool { - return $this->_exists(FactoryInterface::class); + return isset($this->NeighborhoodsKojoApiV1JobTypeRegistrarFactory); } - protected function _unsetApiV1JobTypeRegistrarFactory(): self + protected function unsetApiV1JobTypeRegistrarFactory(): self { - $this->_delete(FactoryInterface::class); + assert($this->hasApiV1JobTypeRegistrarFactory(), + new \LogicException('NeighborhoodsKojoApiV1JobTypeRegistrarFactory is not set.')); + unset($this->NeighborhoodsKojoApiV1JobTypeRegistrarFactory); return $this; } -} \ No newline at end of file +} diff --git a/src/Api/V1/Logger/AwareTrait.php b/src/Api/V1/Logger/AwareTrait.php index 9714ed44..46b46c2c 100644 --- a/src/Api/V1/Logger/AwareTrait.php +++ b/src/Api/V1/Logger/AwareTrait.php @@ -5,34 +5,36 @@ use Neighborhoods\Kojo\Api\V1\LoggerInterface; +/** @codeCoverageIgnore */ trait AwareTrait { + protected $NeighborhoodsKojoApiV1Logger; + public function setApiV1Logger(LoggerInterface $apiV1Logger): self { - $this->_create(LoggerInterface::class, $apiV1Logger); + assert(!$this->hasApiV1Logger(), new \LogicException('NeighborhoodsKojoApiV1Logger is already set.')); + $this->NeighborhoodsKojoApiV1Logger = $apiV1Logger; return $this; } - protected function _getApiV1Logger(): LoggerInterface + protected function getApiV1Logger(): LoggerInterface { - return $this->_read(LoggerInterface::class); - } + assert($this->hasApiV1Logger(), new \LogicException('NeighborhoodsKojoApiV1Logger is not set.')); - protected function _getApiV1LoggerClone(): LoggerInterface - { - return clone $this->_getApiV1Logger(); + return $this->NeighborhoodsKojoApiV1Logger; } - protected function _hasApiV1Logger(): bool + protected function hasApiV1Logger(): bool { - return $this->_exists(LoggerInterface::class); + return isset($this->NeighborhoodsKojoApiV1Logger); } - protected function _unsetApiV1Logger(): self + protected function unsetApiV1Logger(): self { - $this->_delete(LoggerInterface::class); + assert($this->hasApiV1Logger(), new \LogicException('NeighborhoodsKojoApiV1Logger is not set.')); + unset($this->NeighborhoodsKojoApiV1Logger); return $this; } -} \ No newline at end of file +} diff --git a/src/Api/V1/Worker/Service.php b/src/Api/V1/Worker/Service.php index 9caa07ca..88847cb6 100644 --- a/src/Api/V1/Worker/Service.php +++ b/src/Api/V1/Worker/Service.php @@ -22,13 +22,13 @@ class Service implements ServiceInterface use Update\Complete\Failed\Factory\AwareTrait; use Create\Factory\AwareTrait; use Defensive\AwareTrait; - protected const PROP_REQUEST = 'request'; - protected const PROP_RETRY_DATE_TIME = 'retry_date_time'; - protected const REQUEST_RETRY = 'retry'; - protected const REQUEST_HOLD = 'hold'; + protected const PROP_REQUEST = 'request'; + protected const PROP_RETRY_DATE_TIME = 'retry_date_time'; + protected const REQUEST_RETRY = 'retry'; + protected const REQUEST_HOLD = 'hold'; protected const REQUEST_COMPLETE_SUCCESS = 'complete_success'; - protected const REQUEST_COMPLETE_FAILED = 'complete_failed'; - protected const PROP_REQUEST_APPLIED = 'request_applied'; + protected const REQUEST_COMPLETE_FAILED = 'complete_failed'; + protected const PROP_REQUEST_APPLIED = 'request_applied'; public function requestRetry(\DateTime $retryDateTime): ServiceInterface { @@ -109,9 +109,14 @@ public function isRequestApplied(): bool return $this->_exists(self::PROP_REQUEST_APPLIED); } + public function getTimesCrashed(): int + { + return $this->_getJob()->getTimesCrashed(); + } + public function getLogger(): LoggerInterface { - return $this->_getApiV1Logger(); + return $this->getApiV1Logger(); } public function reload(): ServiceInterface @@ -121,6 +126,6 @@ public function reload(): ServiceInterface public function getNewJobScheduler(): SchedulerInterface { - return $this->_getApiV1JobSchedulerFactory()->create(); + return $this->getApiV1JobSchedulerFactory()->create(); } } \ No newline at end of file diff --git a/src/Api/V1/Worker/Service/AwareTrait.php b/src/Api/V1/Worker/Service/AwareTrait.php index d20bdd8a..b1a2b90b 100644 --- a/src/Api/V1/Worker/Service/AwareTrait.php +++ b/src/Api/V1/Worker/Service/AwareTrait.php @@ -5,29 +5,37 @@ use Neighborhoods\Kojo\Api\V1\Worker\ServiceInterface; +/** @codeCoverageIgnore */ trait AwareTrait { - public function setApiV1WorkerService(ServiceInterface $workerService) + protected $NeighborhoodsKojoApiV1WorkerService; + + public function setApiV1WorkerService(ServiceInterface $apiV1WorkerService): self { - $this->_create(ServiceInterface::class, $workerService); + assert(!$this->hasApiV1WorkerService(), + new \LogicException('NeighborhoodsKojoApiV1WorkerService is already set.')); + $this->NeighborhoodsKojoApiV1WorkerService = $apiV1WorkerService; return $this; } - protected function _getApiV1WorkerService(): ServiceInterface + protected function getApiV1WorkerService(): ServiceInterface { - return $this->_read(ServiceInterface::class); + assert($this->hasApiV1WorkerService(), new \LogicException('NeighborhoodsKojoApiV1WorkerService is not set.')); + + return $this->NeighborhoodsKojoApiV1WorkerService; } - protected function _hasApiV1WorkerService(): bool + protected function hasApiV1WorkerService(): bool { - return $this->_exists(ServiceInterface::class); + return isset($this->NeighborhoodsKojoApiV1WorkerService); } - protected function _unsetApiV1WorkerService(): self + protected function unsetApiV1WorkerService(): self { - $this->_delete(ServiceInterface::class); + assert($this->hasApiV1WorkerService(), new \LogicException('NeighborhoodsKojoApiV1WorkerService is not set.')); + unset($this->NeighborhoodsKojoApiV1WorkerService); return $this; } -} \ No newline at end of file +} diff --git a/src/Api/V1/Worker/ServiceInterface.php b/src/Api/V1/Worker/ServiceInterface.php index 2b16760b..274e4eab 100644 --- a/src/Api/V1/Worker/ServiceInterface.php +++ b/src/Api/V1/Worker/ServiceInterface.php @@ -31,6 +31,8 @@ public function getNewJobScheduler(): SchedulerInterface; public function reload(): ServiceInterface; + public function getTimesCrashed(): int; + /** @injected:configuration */ public function setServiceUpdateRetryFactory(Retry\FactoryInterface $updateRetryFactory); diff --git a/src/Data/Job/Collection/Schedule/LimitCheck.php b/src/Data/Job/Collection/Schedule/LimitCheck.php index 3f2c6480..7e224bd1 100644 --- a/src/Data/Job/Collection/Schedule/LimitCheck.php +++ b/src/Data/Job/Collection/Schedule/LimitCheck.php @@ -18,6 +18,7 @@ protected function _prepareCollection(): Db\Model\CollectionAbstract JobInterface::FIELD_NAME_ID, JobInterface::FIELD_NAME_TYPE_CODE, JobInterface::FIELD_NAME_PRIORITY, + JobInterface::FIELD_NAME_WORK_AT_DATE_TIME, JobInterface::FIELD_NAME_CAN_WORK_IN_PARALLEL, JobInterface::FIELD_NAME_ASSIGNED_STATE, JobInterface::FIELD_NAME_NEXT_STATE_REQUEST, diff --git a/src/Data/Job/Collection/ScheduleLimit.php b/src/Data/Job/Collection/ScheduleLimit.php index a9dd3405..c32eb492 100644 --- a/src/Data/Job/Collection/ScheduleLimit.php +++ b/src/Data/Job/Collection/ScheduleLimit.php @@ -19,9 +19,9 @@ public function getNumberOfCurrentlyScheduledJobs(): int return $this->_getRecords()[self::ALIAS_NUMBER_OF_SCHEDULED_JOBS]; } - public function decrementNumberOfCurrentlyScheduledJobs(): ScheduleLimitInterface + public function incrementNumberOfCurrentlyScheduledJobs(): ScheduleLimitInterface { - --$this->_getRecords()[self::ALIAS_NUMBER_OF_SCHEDULED_JOBS]; + ++$this->_getRecords()[self::ALIAS_NUMBER_OF_SCHEDULED_JOBS]; return $this; } diff --git a/src/Data/Job/Collection/ScheduleLimitInterface.php b/src/Data/Job/Collection/ScheduleLimitInterface.php index 06a4e592..04d7ff6c 100644 --- a/src/Data/Job/Collection/ScheduleLimitInterface.php +++ b/src/Data/Job/Collection/ScheduleLimitInterface.php @@ -12,5 +12,5 @@ public function setJobType(TypeInterface $job); public function getNumberOfCurrentlyScheduledJobs(): int; - public function decrementNumberOfCurrentlyScheduledJobs(): ScheduleLimitInterface; + public function incrementNumberOfCurrentlyScheduledJobs(): ScheduleLimitInterface; } \ No newline at end of file diff --git a/src/Data/Status/MessageInterface.php b/src/Data/Status/MessageInterface.php new file mode 100644 index 00000000..528a93cb --- /dev/null +++ b/src/Data/Status/MessageInterface.php @@ -0,0 +1,18 @@ + $pdoBuilder->getPdo()]); } - $connection->getConfiguration()->setSQLLogger(new EchoSQLLogger()); +// $connection->getConfiguration()->setSQLLogger(new EchoSQLLogger()); $this->_create(Connection::class, $connection); } diff --git a/src/Foreman.php b/src/Foreman.php index c501005f..29623977 100644 --- a/src/Foreman.php +++ b/src/Foreman.php @@ -43,12 +43,11 @@ protected function _workWorker(): ForemanInterface { $this->setJob($this->_getSelector()->getWorkableJob()); $this->_getLocator()->setJob($this->_getJob()); - try{ - $this->_injectWorkerService(); + try { $this->_updateJobAsWorking(); $this->_runWorker(); $this->_updateJobAfterWork(); - }catch(Locator\Exception | \Error $throwable){ + } catch (Locator\Exception | \Error $throwable) { $this->_panicJob(); $jobId = $this->_getJob()->getId(); throw new \RuntimeException("Panicking job with ID[$jobId].", 0, $throwable); @@ -66,7 +65,7 @@ protected function _injectWorkerService(): ForemanInterface { $worker = $this->_getLocator()->getClass(); if (method_exists($worker, 'setApiV1WorkerService')) { - $worker->setApiV1WorkerService($this->_getApiV1WorkerService()->setJob($this->_getJob())); + $worker->setApiV1WorkerService($this->getApiV1WorkerService()->setJob($this->_getJob())); } return $this; @@ -74,14 +73,15 @@ protected function _injectWorkerService(): ForemanInterface protected function _runWorker(): ForemanInterface { - try{ - $this->_getApmNewRelic()->startTransaction(); + try { $className = $this->_getLocator()->getClassName(); $methodName = $this->_getLocator()->getMethodName(); + $this->_getApmNewRelic()->startTransaction(); $this->_getApmNewRelic()->nameTransaction($className . '::' . $methodName); + $this->_injectWorkerService(); call_user_func($this->_getLocator()->getCallable()); $this->_getApmNewRelic()->endTransaction(); - }catch(\Exception $throwable){ + } catch (\Exception $throwable) { $this->_crashJob(); throw $throwable; } @@ -91,11 +91,11 @@ protected function _runWorker(): ForemanInterface protected function _updateJobAsWorking(): ForemanInterface { - try{ + try { $updateWork = $this->_getServiceUpdateWorkFactory()->create(); $updateWork->setJob($this->_getJob()); $updateWork->save(); - }catch(\Exception $exception){ + } catch (\Exception $exception) { $this->_panicJob(); $this->_getSemaphore()->releaseLock($this->_getNewJobOwnerResource($this->_getJob())); throw $exception; @@ -110,8 +110,8 @@ protected function _updateJobAfterWork(): ForemanInterface $updateCompleteSuccess = $this->_getServiceUpdateCompleteSuccessFactory()->create(); $updateCompleteSuccess->setJob($this->_getJob()); $updateCompleteSuccess->save(); - }else { - if (!$this->_getApiV1WorkerService()->isRequestApplied()) { + } else { + if (!$this->getApiV1WorkerService()->isRequestApplied()) { $this->_panicJob(); $jobId = $this->_getJob()->getId(); throw new \LogicException("Worker related to job with ID[$jobId] did not request a next state."); diff --git a/src/Maintainer.php b/src/Maintainer.php index 19e89b15..80449ddc 100644 --- a/src/Maintainer.php +++ b/src/Maintainer.php @@ -37,10 +37,10 @@ public function deleteCompletedJobs(): MaintainerInterface public function rescheduleCrashedJobs(): MaintainerInterface { if ($this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_RESCHEDULE_JOBS)->testAndSetLock()) { - try{ + try { $this->_rescheduleCrashedJobs(); $this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_RESCHEDULE_JOBS)->releaseLock(); - }catch(\Exception $exception){ + } catch (\Exception $exception) { if ($this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_RESCHEDULE_JOBS)->hasLock()) { $this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_RESCHEDULE_JOBS)->releaseLock(); } @@ -55,14 +55,14 @@ protected function _rescheduleCrashedJobs(): Maintainer { foreach ($this->_getJobCollectionCrashDetection()->getIterator() as $job) { $jobSemaphoreResource = $this->_getNewJobOwnerResource($job); - try{ + try { if ($jobSemaphoreResource->testAndSetLock()) { $crashUpdate = $this->_getServiceUpdateCrashFactory()->create(); $crashUpdate->setJob($job); $crashUpdate->save(); $jobSemaphoreResource->releaseLock(); } - }catch(\Exception $exception){ + } catch (\Exception $exception) { if ($jobSemaphoreResource->hasLock()) { $jobSemaphoreResource->releaseLock(); } @@ -76,10 +76,10 @@ protected function _rescheduleCrashedJobs(): Maintainer public function updatePendingJobs(): MaintainerInterface { if ($this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_UPDATE_PENDING_JOBS)->testAndSetLock()) { - try{ + try { $this->_updatePendingJobs(); $this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_UPDATE_PENDING_JOBS)->releaseLock(); - }catch(\Exception $exception){ + } catch (\Exception $exception) { if ($this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_UPDATE_PENDING_JOBS)->hasLock()) { $this->_getSemaphoreResource(self::SEMAPHORE_RESOURCE_NAME_UPDATE_PENDING_JOBS)->releaseLock(); } @@ -97,18 +97,18 @@ protected function _updatePendingJobs(): Maintainer $scheduleLimitCollection = $this->_getJobCollectionScheduleLimitByJobType($jobType); $numberOfScheduledJobs = $scheduleLimitCollection->getNumberOfCurrentlyScheduledJobs(); $scheduleLimit = $jobType->getScheduleLimit(); - try{ - if ($numberOfScheduledJobs <= $scheduleLimit) { + try { + if ($numberOfScheduledJobs < $scheduleLimit) { $waitUpdate = $this->_getServiceUpdateWaitFactory()->create(); $waitUpdate->setJob($job); $waitUpdate->save(); - }elseif ($numberOfScheduledJobs > $scheduleLimit + $jobType->getScheduleLimitAllowance()) { + $scheduleLimitCollection->incrementNumberOfCurrentlyScheduledJobs(); + } elseif ($job->getWorkAtDateTime() < new \DateTime('now')) { $failedLimitCheckUpdate = $this->_getServiceUpdateCompleteFailedScheduleLimitCheckFactory()->create(); $failedLimitCheckUpdate->setJob($job); $failedLimitCheckUpdate->save(); - $scheduleLimitCollection->decrementNumberOfCurrentlyScheduledJobs(); } - }catch(\Exception $exception){ + } catch (\Exception $exception) { $updatePanic = $this->_getServiceUpdatePanicFactory()->create(); $updatePanic->setJob($job); $updatePanic->save(); diff --git a/src/Process/Pool/Factory.yml b/src/Process/Pool/Factory.yml index 37f2efcd..e56c10f7 100644 --- a/src/Process/Pool/Factory.yml +++ b/src/Process/Pool/Factory.yml @@ -1,5 +1,5 @@ parameters: - process_pool_strategy.max_child_processes: 10 + process_pool_strategy.max_child_processes: 20 process_pool_strategy.child_process_wait_throttle: 1 process_pool_strategy.max_alarm_time: 5 process_pool_strategy-server.max_child_processes: 1 diff --git a/src/Process/Pool/Logger.yml b/src/Process/Pool/Logger.yml index 42043524..e55995fe 100644 --- a/src/Process/Pool/Logger.yml +++ b/src/Process/Pool/Logger.yml @@ -1,7 +1,7 @@ parameters: process.pool.logger.process_id_padding: 6 process.pool.logger.path_padding: 80 - process.pool.logger.is_enabled: false + process.pool.logger.is_enabled: true services: neighborhoods.kojo.process.pool.logger: class: Neighborhoods\Kojo\Process\Pool\Logger diff --git a/src/Worker/Locator.php b/src/Worker/Locator.php index cbfdd6c4..9ed994de 100644 --- a/src/Worker/Locator.php +++ b/src/Worker/Locator.php @@ -11,8 +11,6 @@ class Locator implements LocatorInterface { use Job\AwareTrait; use Defensive\AwareTrait; - protected const PROP_METHOD_NAME = 'method_name'; - protected const PROP_CLASS_NAME = 'class_name'; protected $_callable = []; public function getClass() @@ -23,20 +21,21 @@ public function getClass() public function getCallable(): callable { if (empty($this->_callable)) { - try{ - $class = $this->_getJob()->getWorkerUri(); - $method = $this->_getJob()->getWorkerMethod(); - $this->_create(self::PROP_CLASS_NAME, $class); - $this->_create(self::PROP_METHOD_NAME, $method); - $object = new $class; - $callable = [$object, $method]; + try { + $className = $this->getClassName(); + $methodName = $this->getMethodName(); + $object = new $className; + $callable = [$object, $methodName]; if (is_callable($callable)) { $this->_callable = $callable; - }else { - throw new \RuntimeException("Class[$class] and method[$method] is not callable."); + } else { + throw new \RuntimeException("Class[$className] and method[$methodName] is not callable."); } - }catch(\Throwable $throwable){ - throw new Exception($throwable->getMessage(), Exception::CODE_CANNOT_INSTANTIATE_WORKER, $throwable); + } catch (\Throwable $throwable) { + throw (new Exception( + $throwable->getMessage(), + $throwable + ))->setCode(Exception::CODE_CANNOT_INSTANTIATE_WORKER); } } @@ -45,11 +44,11 @@ public function getCallable(): callable public function getMethodName(): string { - return $this->_read(self::PROP_METHOD_NAME); + return $this->_getJob()->getWorkerMethod(); } public function getClassName(): string { - return $this->_read(self::PROP_CLASS_NAME); + return $this->_getJob()->getWorkerUri(); } } \ No newline at end of file diff --git a/tests/BehaviorSmokeTest/BehaviorSmokeTest.php b/tests/BehaviorSmokeTest/BehaviorSmokeTest.php index 3d3b4f95..9a530f80 100644 --- a/tests/BehaviorSmokeTest/BehaviorSmokeTest.php +++ b/tests/BehaviorSmokeTest/BehaviorSmokeTest.php @@ -1,7 +1,7 @@