From 974a381b5a72684301df83f0c1c7fe2ee7ac8054 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Wed, 12 Feb 2020 15:28:03 +0100 Subject: [PATCH] Implemented changes to binaries. Binaries now accept a 'bootstrap' argument, allowing the developer to load a custom bootstrap from the project they're working on. This allows Async to run in the same environment as the project it's part of. --- bin/supervisor | 61 ++++++--- bin/worker | 125 ++++++++++++++++++ composer.json | 2 +- config.tasks.php | 2 +- .../Async/Executors/ShellExecutor.php | 4 +- .../Async/{Worker.php => ShellWorker.php} | 12 +- src/FuzeWorks/Async/Tasks.php | 6 +- supervisor.php | 70 ---------- worker.php | 68 ---------- 9 files changed, 184 insertions(+), 166 deletions(-) create mode 100644 bin/worker rename src/FuzeWorks/Async/{Worker.php => ShellWorker.php} (95%) delete mode 100644 supervisor.php delete mode 100644 worker.php diff --git a/bin/supervisor b/bin/supervisor index 28fda4b..62f174e 100644 --- a/bin/supervisor +++ b/bin/supervisor @@ -40,7 +40,9 @@ use FuzeWorks\Async\Tasks; use FuzeWorks\Async\TasksException; use FuzeWorks\Exception\InvalidArgumentException; use FuzeWorks\Exception\LibraryException; +use FuzeWorks\Factory; +// First perform a PHP version check if (version_compare('7.1.0', PHP_VERSION, '>')) { fwrite( STDERR, @@ -63,35 +65,56 @@ $autoloaders = [ ]; foreach ($autoloaders as $file) if (file_exists($file)) - require($file); + require_once($file); + +// If a bootstrap is provided, use that one +$arguments = getopt('', ['bootstrap:']); +if (!isset($arguments['bootstrap']) || empty($arguments['bootstrap'])) +{ + fwrite(STDERR, "Could not load supervisor. No bootstrap provided."); + die(1); +} +// Load the file. If it doesn't exist, fail. +$file = $arguments['bootstrap']; +if (!file_exists($file)) +{ + fwrite(STDERR, "Could not load supervisor. Provided bootstrap doesn't exist."); + die(1); +} + +// Load the bootstrap +/** @var Factory $container */ +$container = require($file); + +// Check if container is a Factory +if (!$container instanceof Factory) +{ + fwrite(STDERR, "Could not load supervisor. Provided bootstrap is not a valid bootstrap."); + die(1); +} + +// Check if the Async library is already loaded. If not, load it. +// @todo: Better check in libraries for existing library try { - // Open configurator - $configurator = new FuzeWorks\Configurator(); - - // Set up basic settings - $configurator->setTimeZone('Europe/Amsterdam'); - $configurator->setTempDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'temp'); - $configurator->setLogDirectory(dirname(__FILE__). DIRECTORY_SEPARATOR . 'log'); - - // Add Async library - $configurator->deferComponentClassMethod('libraries', 'addLibraryClass', null, 'async', '\FuzeWorks\Async\Tasks'); - - // Debug - $configurator->enableDebugMode()->setDebugAddress('ALL'); - - // Create container - $container = $configurator->createContainer(); - - // RUN THE APP /** @var Tasks $lib */ $lib = $container->libraries->get('async'); +} catch (LibraryException $e) { + $container->libraries->addLibraryClass('async', '\FuzeWorks\Async\Tasks'); + /** @var Tasks $lib */ + $lib = $container->libraries->get('async'); +} +// And finally, run the supervisor +try { $supervisor = $lib->getSuperVisor(); while ($supervisor->cycle() === SuperVisor::RUNNING) { usleep(250000); } + + // Write results + fwrite(STDOUT, "SuperVisor finished scheduled tasks."); } catch (InvalidArgumentException | TasksException | LibraryException $e) { fwrite(STDERR, sprintf('FuzeWorks Async could not load.' . PHP_EOL . 'Exception: ' . $e->getMessage() . PHP_EOL) diff --git a/bin/worker b/bin/worker new file mode 100644 index 0000000..ecac264 --- /dev/null +++ b/bin/worker @@ -0,0 +1,125 @@ +#!/usr/bin/env php +')) { + fwrite( + STDERR, + sprintf( + 'FuzeWorks Async requires PHP 7.1 or higher.' . PHP_EOL . + 'You are using PHP %s (%s).' . PHP_EOL, + PHP_VERSION, + PHP_BINARY + ) + ); + + die(1); +} + +// First load composer +$autoloaders = [ + __DIR__ . '/../../autoload.php', + __DIR__ . '/../vendor/autoload.php', + __DIR__ . '/vendor/autoload.php' +]; +foreach ($autoloaders as $file) + if (file_exists($file)) + require_once($file); + +// If a bootstrap is provided, use that one +$arguments = getopt('', ['bootstrap:']); +if (!isset($arguments['bootstrap']) || empty($arguments['bootstrap'])) +{ + fwrite(STDERR, "Could not load worker. No bootstrap provided."); + die(1); +} + + +// Load the file. If it doesn't exist, fail. +$file = $arguments['bootstrap']; +if (!file_exists($file)) +{ + fwrite(STDERR, "Could not load worker. Provided bootstrap doesn't exist."); + die(1); +} + +// Load the bootstrap +/** @var Factory $container */ +$container = require($file); + +// Check if container is a Factory +if (!$container instanceof Factory) +{ + fwrite(STDERR, "Could not load worker. Provided bootstrap is not a valid bootstrap."); + die(1); +} + +// Check if the Async library is already loaded. If not, load it. +// @todo: Better check in libraries for existing library +try { + /** @var Tasks $lib */ + $lib = $container->libraries->get('async'); +} catch (LibraryException $e) { + $container->libraries->addLibraryClass('async', '\FuzeWorks\Async\Tasks'); + /** @var Tasks $lib */ + $lib = $container->libraries->get('async'); +} + +// Fetch arguments for the worker +$arguments = getopt("t:p::"); +if (!isset($arguments['t'])) +{ + fwrite(STDERR, "Could not load worker. No taskID provided."); + die(1); +} + +// Prepare arguments +$taskID = base64_decode($arguments['t']); +$post = isset($arguments['p']); + +// RUN THE APP +$worker = $lib->getWorker(); +$worker->run($taskID, $post); + +fwrite(STDOUT,'Finished task \'' . $taskID . "'"); +?> \ No newline at end of file diff --git a/composer.json b/composer.json index 2a3620e..9698f4f 100644 --- a/composer.json +++ b/composer.json @@ -22,5 +22,5 @@ "FuzeWorks\\Async\\": "src/FuzeWorks/Async" } }, - "bin": ["bin/supervisor"] + "bin": ["bin/supervisor", "bin/worker"] } \ No newline at end of file diff --git a/config.tasks.php b/config.tasks.php index 21f14d5..7a00481 100644 --- a/config.tasks.php +++ b/config.tasks.php @@ -48,6 +48,6 @@ return array( 'type' => 'ShellExecutor', // For ShellExecutor, first parameter is the file location of the worker script - 'parameters' => [dirname(__FILE__) . DS . 'worker.php'] + 'parameters' => [dirname(__FILE__) . DS . 'bin' . DS . 'worker'] ] ); \ No newline at end of file diff --git a/src/FuzeWorks/Async/Executors/ShellExecutor.php b/src/FuzeWorks/Async/Executors/ShellExecutor.php index c8ad1e4..69e5c18 100644 --- a/src/FuzeWorks/Async/Executors/ShellExecutor.php +++ b/src/FuzeWorks/Async/Executors/ShellExecutor.php @@ -60,7 +60,7 @@ class ShellExecutor implements Executor $this->binary = PHP_BINDIR . DS . 'php'; if (!file_exists($workerFile)) - throw new TasksException("Could not construct ShellExecutor. Worker script does not exist."); + throw new TasksException("Could not construct ShellExecutor. ShellWorker script does not exist."); $this->worker = $workerFile; } @@ -77,7 +77,7 @@ class ShellExecutor implements Executor public function startTask(Task $task, bool $post = false): Task { // First prepare the command used to spawn workers - $commandString = "$this->binary $this->worker %s ".($post ? 'post' : 'run')." $this->stdout $this->stderr & echo $!"; + $commandString = "$this->binary $this->worker -t %s ".($post ? 'p' : '')." $this->stdout $this->stderr & echo $!"; // Then execute the command using the base64_encoded string of the taskID $output = $this->shellExec($commandString, [base64_encode($task->getId())]); diff --git a/src/FuzeWorks/Async/Worker.php b/src/FuzeWorks/Async/ShellWorker.php similarity index 95% rename from src/FuzeWorks/Async/Worker.php rename to src/FuzeWorks/Async/ShellWorker.php index c110e59..a614541 100644 --- a/src/FuzeWorks/Async/Worker.php +++ b/src/FuzeWorks/Async/ShellWorker.php @@ -42,7 +42,7 @@ use FuzeWorks\Exception\EventException; use FuzeWorks\Logger; use FuzeWorks\Priority; -class Worker +class ShellWorker { /** @@ -75,7 +75,11 @@ class Worker public function run(string $taskID, bool $post = false) { // First fetch the task - $task = $this->taskStorage->getTaskById($taskID); + try { + $task = $this->taskStorage->getTaskById($taskID); + } catch (TasksException $e) { + throw new TasksException("Could not run worker. Task not found."); + } // Fire a taskHandleEvent /** @var TaskHandleEvent $event */ @@ -159,6 +163,10 @@ class Worker $errors = $this->getErrors(); $this->output('', $errors); + // If no task is set yet, abort error logging to task + if (is_null($this->task)) + return; + try { // Write to TaskStorage if (!$this->post) diff --git a/src/FuzeWorks/Async/Tasks.php b/src/FuzeWorks/Async/Tasks.php index 1a8bbab..9a8cbe2 100644 --- a/src/FuzeWorks/Async/Tasks.php +++ b/src/FuzeWorks/Async/Tasks.php @@ -94,12 +94,12 @@ class Tasks implements iLibrary } /** - * @return Worker + * @return ShellWorker * @throws TasksException */ - public function getWorker(): Worker + public function getWorker(): ShellWorker { - return new Worker($this->getTaskStorage()); + return new ShellWorker($this->getTaskStorage()); } /** diff --git a/supervisor.php b/supervisor.php deleted file mode 100644 index 8fc8427..0000000 --- a/supervisor.php +++ /dev/null @@ -1,70 +0,0 @@ -setTimeZone('Europe/Amsterdam'); -$configurator->setTempDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'temp'); -$configurator->setLogDirectory(dirname(__FILE__). DIRECTORY_SEPARATOR . 'log'); - -// Add Async library -$configurator->deferComponentClassMethod('libraries', 'addLibraryClass', null, 'async', '\FuzeWorks\Async\Tasks'); - -// Debug -$configurator->enableDebugMode()->setDebugAddress('ALL'); - -// Create container -$container = $configurator->createContainer(); - -// Add lib -Logger::enableScreenLog(); - -// RUN THE APP -/** @var Tasks $lib */ -$lib = $container->libraries->get('async'); - -$supervisor = $lib->getSuperVisor(); -while ($supervisor->cycle() === SuperVisor::RUNNING) { - usleep(250000); -} \ No newline at end of file diff --git a/worker.php b/worker.php deleted file mode 100644 index 3439954..0000000 --- a/worker.php +++ /dev/null @@ -1,68 +0,0 @@ -setTimeZone('Europe/Amsterdam'); -$configurator->setTempDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'temp'); -$configurator->setLogDirectory(dirname(__FILE__). DIRECTORY_SEPARATOR . 'log'); - -// Add Async library -$configurator->deferComponentClassMethod('libraries', 'addLibraryClass', null, 'async', '\FuzeWorks\Async\Tasks'); - -// Debug -$configurator->enableDebugMode()->setDebugAddress('ALL'); - -// Create container -$container = $configurator->createContainer(); - -// Prepare arguments -$script = array_shift($argv); -$taskID = array_shift($argv); -$taskID = base64_decode($taskID); -$mode = trim(array_shift($argv)); -$post = ($mode === 'post' ? true : false); - -// RUN THE APP -/** @var Tasks $lib */ -$lib = $container->libraries->get('async'); -$worker = $lib->getWorker(); -$worker->run($taskID, $post); \ No newline at end of file