taskStorage = $taskStorage; Events::addListener([$this, 'fatalHandler'], 'haltExecutionEvent', Priority::HIGH); } /** * @param string $taskID * @param bool $post * @throws EventException * @throws TasksException */ public function run(string $taskID, bool $post = false) { // First fetch the task 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 */ $event = Events::fireEvent(new TaskHandleEvent(), $task); $task = $event->getTask(); // Set task to this worker $this->task = $task; $this->post = $post; // Fetch the callable $class = $this->task->getHandlerClass(); if (!class_exists($class, true)) { $errors = 'Could not run task. HandlerClass \'' . $class . '\' not found.'; if (!$post) $this->taskStorage->writeTaskOutput($this->task, '', $errors, Task::PFAILED, $this->task->getRetries()); else $this->taskStorage->writePostOutput($this->task, '', $errors, Task::PFAILED, $this->task->getRetries()); throw new TasksException("Could not run task. '$class' not found."); } // Create the handler /** @var Handler $object */ $object = new $class(); if (!$object instanceof Handler) { $errors = "Could not run task. '$class' is not instance of Handler."; if (!$post) $this->taskStorage->writeTaskOutput($this->task, '', $errors, Task::PFAILED, $this->task->getRetries()); else $this->taskStorage->writePostOutput($this->task, '', $errors, Task::PFAILED, $this->task->getRetries()); throw new TasksException("Could not run task. '$class' is not instance of Handler."); } // Run postHandler if post mode is requested if ($post) { $postSuccess = $object->postHandler($this->task); $postOutput = $object->getPostOutput(); $postOutput = is_null($postOutput) ? '' : (string) $postOutput; $postErrors = $this->getErrors(); if (!$postSuccess) $this->taskStorage->writePostOutput($this->task, $postOutput, $postErrors, Task::FAILED, $this->task->getRetries()); else $this->taskStorage->writePostOutput($this->task, $postOutput, $postErrors, Task::SUCCESS, $this->task->getRetries()); $this->output($postOutput, $postErrors); return; } // Run primaryHandler if requested $success = $object->primaryHandler($this->task); $output = $object->getOutput(); $output = is_null($output) ? '' : (string) $output; $errors = $this->getErrors(); // And afterwards write the results to the TaskStorage if (!$success) $this->taskStorage->writeTaskOutput($this->task, $output, $errors, Task::FAILED, $this->task->getRetries()); else $this->taskStorage->writeTaskOutput($this->task, $output, $errors, Task::SUCCESS, $this->task->getRetries()); $this->output($output, $errors); } /** * In case a fatal error or exception occurs, the errors shall be redirected to stderr * * @param HaltExecutionEvent $event */ public function fatalHandler(HaltExecutionEvent $event) { // Cancel further execution by FuzeWorks $event->setCancelled(true); // Collect all error logs $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) $this->taskStorage->writeTaskOutput($this->task, '', $errors, Task::FAILED, $this->task->getRetries()); else $this->taskStorage->writePostOutput($this->task, '', $errors, Task::FAILED, $this->task->getRetries()); } catch (TasksException $e) { // Ignore } exit; } /** * Get all errors, exceptions and warnings from runtime and turn them into a string * * @return string */ protected function getErrors(): string { $output = []; foreach (Logger::$logs as $log) { if ($log['type'] !== 'ERROR' && $log['type'] !== 'EXCEPTION' && $log['type'] !== 'WARNING') continue; $output[] = strtoupper($log['type']) . ' ' . (!empty($log['logFile']) && !empty($log['logLine']) ? $log['logFile'] . ':' . $log['logLine'] . " '" : "'") . $log['message'] . "'"; } return implode("\n", $output); } /** * Output the results to stdout and stderr * * @param string $output * @param string $errors */ protected function output(string $output, string $errors) { // First write to stderr if (!empty($errors)) fwrite(STDERR, $errors . PHP_EOL); // Afterwards write to stdout if (!empty($output)) echo $output . PHP_EOL; } }