commit 8ccb1796434e902986529e856b5c86bd3a0b6276 Author: Abel Hoogeveen Date: Tue Jan 28 11:04:57 2020 +0100 Initial commit diff --git a/Tasks/Tasks.php b/Tasks/Tasks.php new file mode 100644 index 0000000..fe858eb --- /dev/null +++ b/Tasks/Tasks.php @@ -0,0 +1,169 @@ +addComponentPath(dirname(__FILE__), Priority::LOW); + $this->cfg = $config->getConfig('tasks'); + } + + /** + * @param Task $task + * @return bool + * @throws TasksException + */ + public function queueTask(Task $task): bool + { + $taskStorage = $this->getTaskStorage(); + return $taskStorage->addTask($task); + } + + /** + * @throws TasksException + */ + public function getSuperVisor(): SuperVisor + { + $cfg = $this->cfg->get('SuperVisor'); + $class = 'Application\Library\Tasks\Supervisors\\' . $cfg['type']; + $parameters = isset($cfg['parameters']) && is_array($cfg['parameters']) ? $cfg['parameters'] : []; + array_unshift($parameters, $this->getTaskStorage(), $this->getExecutor()); + if (!class_exists($class, true)) + throw new TasksException("Could not get SuperVisor. Type of '$class' not found."); + + $object = new $class(...$parameters); + if (!$object instanceof SuperVisor) + throw new TasksException("Could not get SuperVisor. Type of '$class' is not instanceof TaskStorage."); + + return $object; + } + + /** + * @return Worker + * @throws TasksException + */ + public function getWorker(): Worker + { + return new Worker($this->getTaskStorage()); + } + + /** + * Fetch the TaskStorage based on the configured type + * + * @return TaskStorage + * @throws TasksException + */ + public function getTaskStorage(): TaskStorage + { + $cfg = $this->cfg->get('TaskStorage'); + $class = 'Application\Library\Tasks\TaskStorage\\' . $cfg['type']; + $parameters = isset($cfg['parameters']) && is_array($cfg['parameters']) ? $cfg['parameters'] : []; + if (!class_exists($class, true)) + throw new TasksException("Could not get TaskStorage. Type of '$class' not found."); + + $object = new $class(...$parameters); + if (!$object instanceof TaskStorage) + throw new TasksException("Could not get TaskStorage. Type '$class' is not instanceof TaskStorage."); + + return $object; + } + + /** + * Fetch the Executor based on the configured type + * + * @return Executor + * @throws TasksException + */ + protected function getExecutor(): Executor + { + $cfg = $this->cfg->get('Executor'); + $class = 'Application\Library\Tasks\Executors\\' . $cfg['type']; + $parameters = isset($cfg['parameters']) && is_array($cfg['parameters']) ? $cfg['parameters'] : []; + if (!class_exists($class, true)) + throw new TasksException("Could not get Executor. Type of '$class' not found."); + + $object = new $class(...$parameters); + if (!$object instanceof Executor) + throw new TasksException("Could not get Executor. Type '$class' is not instanceof Executor."); + + return $object; + } + + /** + * @inheritDoc + */ + public function getClassesPrefix(): ?string + { + return '\Application\Library\Tasks'; + } + + /** + * @inheritDoc + */ + public function getSourceDirectory(): ?string + { + return 'src'; + } +} \ No newline at end of file diff --git a/Tasks/config.tasks.php b/Tasks/config.tasks.php new file mode 100644 index 0000000..73b5b6b --- /dev/null +++ b/Tasks/config.tasks.php @@ -0,0 +1,53 @@ + [ + 'type' => 'ParallelSuperVisor', + 'parameters' => [] + ], + 'TaskStorage' => [ + 'type' => 'ArrayTaskStorage', + + // For ArrayTaskStorage, first parameter is the file location of the array storage + 'parameters' => [dirname(__FILE__) . DS . 'storage.php'] + ], + 'Executor' => [ + 'type' => 'ShellExecutor', + + // For ShellExecutor, first parameter is the file location of the worker script + 'parameters' => [dirname(dirname(__DIR__)) . DS . 'worker.php'] + ] +); \ No newline at end of file diff --git a/Tasks/src/Constraint.php b/Tasks/src/Constraint.php new file mode 100644 index 0000000..c1ec515 --- /dev/null +++ b/Tasks/src/Constraint.php @@ -0,0 +1,68 @@ +task = $task; + } + + public function getTask(): Task + { + return $this->task; + } + + public function updateTask(Task $task) + { + $this->task = $task; + } +} \ No newline at end of file diff --git a/Tasks/src/Executor.php b/Tasks/src/Executor.php new file mode 100644 index 0000000..7a87cc4 --- /dev/null +++ b/Tasks/src/Executor.php @@ -0,0 +1,73 @@ + /dev/null"; + private $stderr = "2> /dev/null"; + + /** + * ShellExecutor constructor. + * + * @param string $workerFile The worker script that shall run individual tasks + * @throws TasksException + */ + public function __construct(string $workerFile) + { + // First determine the PHP binary + $this->binary = PHP_BINDIR . DS . 'php'; + + if (!file_exists($workerFile)) + throw new TasksException("Could not construct ShellExecutor. Worker script does not exist."); + + $this->worker = $workerFile; + } + + + private function shellExec($format, array $parameters = []) + { + $parameters = array_map("escapeshellarg", $parameters); + array_unshift($parameters, $format); + $command = call_user_func_array("sprintf", $parameters); + exec($command, $output); + return $output; + } + + 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 $!"; + + // Then execute the command using the base64_encoded string of the taskID + $output = $this->shellExec($commandString, [base64_encode($task->getId())]); + + // Add the PID to the task and change its state to 'RUNNING' + if ($post) + { + $task->setStatus(Task::POST); + $task->addAttribute('post_pid', $output[0]); + } + else + { + $task->setStatus(Task::RUNNING); + $task->addAttribute('run_pid', $output[0]); + } + + // And finally return the task + return $task; + } + + public function stopTask(Task $task): Task + { + // TODO: Implement stopTask() method. + } + + public function getTaskRunning(Task $task): bool + { + $stats = $this->getTaskStats($task); + return !is_null($stats); + } + + public function getTaskStats(Task $task): ?array + { + // First prepare the command used to gather info on processes + $commandString = "ps -o pid,%%cpu,%%mem,state,start -p %s | sed 1d"; + + // Then fetch the PID + try { + $pid = is_null($task->attribute('post_pid')) ? $task->attribute('run_pid') : $task->attribute('post_pid'); + $output = $this->shellExec($commandString, [$pid]); + + if (count($output) < 1) + return null; + + $last = $output[count($output) - 1]; + if (trim($last) === "") + return null; + + $parts = preg_split("/\s+/", trim($last)); + $pid = intval($parts[0]); + $state = strtoupper(trim($parts[3])); + if ("{$pid}" !== $parts[0] || $state === 'Z') + return null; + + return $parts; + } catch (TasksException $e) { + return null; + } + } + + public function getTaskExitCode(Task $task): int + { + // TODO: Implement getTaskExitCode() method. + } + + public function getRunningTasks(): array + { + // TODO: Implement getRunningTasks() method. + } +} \ No newline at end of file diff --git a/Tasks/src/Handler.php b/Tasks/src/Handler.php new file mode 100644 index 0000000..72e4a7d --- /dev/null +++ b/Tasks/src/Handler.php @@ -0,0 +1,77 @@ +taskStorage = $taskStorage; + $this->executor = $executor; + } + + /** + * @inheritDoc + */ + public function cycle(): int + { + // First: if there are no tasks, load them + $this->taskStorage->refreshTasks(); + $this->tasks = $this->taskStorage->readTasks(); + + // If there are still no tasks, nothing is queued, so this cycle can end. + if (empty($this->tasks)) + return SuperVisor::FINISHED; + + // Check if all tasks are completed + $allCompleted = true; + foreach ($this->tasks as $task) + if ($task->getStatus() !== Task::COMPLETED) + $allCompleted = false; + + if ($allCompleted) + return SuperVisor::FINISHED; + + for ($i=0;$itasks);$i++) + { + $task = $this->tasks[$i]; + dump(date('H:i:s') . ': ' . $task->getId() .'/'.$i . ": state #" . $task->getStatus()); + + // DELAYED Tasks. If a task is delayed, but the time has passed, mark the task as pending + if ($task->getStatus() === Task::DELAYED && time() < $task->getDelayTime()) + $task->setStatus(Task::PENDING); + + // FAILED Tasks, check if failed can be made pending using constraints + elseif ($task->getStatus() === Task::FAILED) + $task = $this->testConstraints($task); + + // FINISHED/CANCELLED/FAILED Tasks, check if they are old enough for removal + elseif ($task->getStatus() === Task::COMPLETED || $task->getStatus() === Task::CANCELLED || $task->getStatus() === Task::FAILED) + { + } + + // If the task is pending, start if not constrained + elseif ($task->getStatus() === Task::PENDING) + { + // First test for constraints. + $task = $this->testConstraints($task); + + // If the task is still PENDING, execute it + if ($task->getStatus() !== Task::PENDING) + continue; + + // START THE PROCESS + $task = $this->executor->startTask($task); + $this->taskStorage->modifyTask($task); + } + + // Check if tasks are still running + elseif ($task->getStatus() === Task::RUNNING) + { + $isRunning = $this->executor->getTaskRunning($task); + $output = $this->taskStorage->readTaskOutput($task); + $hasOutput = !is_null($output); + + if (!$isRunning && !$hasOutput) + $task->setStatus(Task::FAILED); + elseif (!$isRunning && $hasOutput) + { + try { + $task->setOutput($output['output'], $output['errors']); + $task->setStatus($output['statusCode']); + } catch (TasksException $e) { + // Ignore + } + } + // elseif (EXPIRED) + else + continue; + + $this->taskStorage->modifyTask($task); + } + + // Check if task succeeded, and whether the task must progress to POST or COMPLETED + // @todo Add failed handler + elseif ($task->getStatus() === Task::SUCCESS) + { + // Calling post handler when requested to do so + if ($task->getCallPostHandler() === true || ($task->getCallPostHandlerWhenFailed() === true && $output['statusCode'] === Task::FAILED)) + $task = $this->executor->startTask($task, true); + else + $task->setStatus(Task::COMPLETED); + + $this->taskStorage->modifyTask($task); + } + + // If the task is in post mode, check when that process has ended + elseif ($task->getStatus() === Task::POST) + { + $isRunning = $this->executor->getTaskRunning($task); + $output = $this->taskStorage->readTaskOutput($task); + $hasOutput = isset($output['postStatus']); + + if (!$isRunning && !$hasOutput) + $task->setStatus(Task::FAILED); + elseif (!$isRunning && $hasOutput) + { + try { + $task->setPostOutput($output['postOutput'], $output['postErrors']); + $task->setStatus(Task::COMPLETED); + } catch (TasksException $e) { + // Ignore + } + } + else + continue; + + $this->taskStorage->modifyTask($task); + } + + + + } + + return SuperVisor::RUNNING; + } + + private function testConstraints(Task $task): Task + { + $constraints = $task->getConstraints(); + foreach ($constraints as $constraint) + { + if ($constraint->intervene($task) && $constraint->blockCode() != 0) + { + $task->setStatus($constraint->blockCode()); + if ($constraint->blockCode() === Task::DELAYED) + $task->setDelayTime(time() + $constraint->delayTime()); + + // Save changes to TaskStorage + $this->taskStorage->modifyTask($task); + } + } + + return $task; + } + + +} \ No newline at end of file diff --git a/Tasks/src/Task.php b/Tasks/src/Task.php new file mode 100644 index 0000000..ccd95b2 --- /dev/null +++ b/Tasks/src/Task.php @@ -0,0 +1,358 @@ +taskId = $identifier; + $this->handlerClass = $handlerClass; + if (func_num_args() > 3) + $args = array_slice(func_get_args(), 3); + else + $args = []; + + foreach ($args as $arg) + if (!$this->isSerializable($arg)) + throw new TasksException("Could not create Task. Provided arguments are not serializable."); + + $this->arguments = $args; + } + + /** + * Returns the unique ID of this task + * + * @return string + */ + public function getId(): string + { + return $this->taskId; + } + + /** + * Gets the name of the class that shall process this task + * + * @return string + */ + public function getHandlerClass(): string + { + return $this->handlerClass; + } + + /** + * Gets the arguments to be provided to the method of the class that shall process this task + * + * @return array + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * Add a constraint to this Task; in order to make the execution conditional. + * + * @param Constraint $constraint + */ + public function addConstraint(Constraint $constraint) + { + $this->constraints[] = $constraint; + } + + /** + * Gets the constraints to this job. + * + * @return Constraint[] + */ + public function getConstraints(): array + { + return $this->constraints; + } + + /** + * Gets the current status of this Task + * + * @return int + */ + public function getStatus(): int + { + return $this->status; + } + + /** + * Sets the status of this Task. + * + * @param int $status + */ + public function setStatus(int $status) + { + $this->status = $status; + } + + /** + * Set the delay time to the Task + * + * @param int $delayTime + */ + public function setDelayTime(int $delayTime) + { + $this->delayTime = $delayTime; + } + + /** + * Receive the delay time for this task + * + * @return int + */ + public function getDelayTime(): int + { + return $this->delayTime; + } + + /** + * Fetch an attribute of this task + * + * @param string $key + * @return mixed + */ + public function attribute(string $key) + { + if (!isset($this->data[$key])) + return null; + + return $this->data[$key]; + } + + /** + * Adds an attribute to this task. + * + * @param string $key + * @param $value + * @throws TasksException + */ + public function addAttribute(string $key, $value) + { + if (!$this->isSerializable($value)) + throw new TasksException("Could not set Task '$this->taskId' attribute '$key'. Value not serializable."); + + $this->data[$key] = $value; + } + + /** + * Return the output of this task execution + * + * @return string|null + */ + public function getOutput(): ?string + { + return $this->output; + } + + public function getPostOutput(): ?string + { + return $this->postOutput; + } + + + /** + * Sets the conditions for when the Handler::postHandler should be called. + * + * If you want the postHandler to only get called on errors, set onEvery to false and onFail to true. + * + * @param bool $onEvery Call the post handler on every result + * @param bool $onFail Call the post handler only when failed + */ + public function setPostHandler(bool $onEvery = false, bool $onFail = false) + { + $this->callPostHandler = $onEvery; + $this->callPostHandlerWhenFailed = $onFail; + } + + public function getCallPostHandler(): bool + { + return $this->callPostHandler; + } + + public function getCallPostHandlerWhenFailed(): bool + { + return $this->callPostHandlerWhenFailed; + } + + /** + * Return the errors of this task execution + * + * @return string|null + */ + public function getErrors(): ?string + { + return $this->errors; + } + + public function getPostErrors(): ?string + { + return $this->postErrors; + } + + + public function setOutput(string $output, string $errors) + { + if (!is_null($this->output) || !is_null($this->errors)) + throw new TasksException("Could not set output. Output already set."); + + $this->output = $output; + $this->errors = $errors; + } + + public function setPostOutput(string $output, string $errors) + { + if (!is_null($this->postOutput) || !is_null($this->postErrors)) + throw new TasksException("Could not set post output. Output already set."); + + $this->postOutput = $output; + $this->postErrors = $errors; + } + + /** + * Checks whether an object can be serialized + * + * @param $value + * @return bool + */ + private function isSerializable ($value) { + $return = true; + $arr = array($value); + + array_walk_recursive($arr, function ($element) use (&$return) { + if (is_object($element) && get_class($element) == 'Closure') { + $return = false; + } + }); + + return $return; + } + + +} \ No newline at end of file diff --git a/Tasks/src/TaskFailException.php b/Tasks/src/TaskFailException.php new file mode 100644 index 0000000..6e72792 --- /dev/null +++ b/Tasks/src/TaskFailException.php @@ -0,0 +1,41 @@ + string $output, 'errors' => string $errors, 'status' => $code) + * OR null of not found (yet) + * + * @param Task $task + * @return array + */ + public function readTaskOutput(Task $task): ?array; +} \ No newline at end of file diff --git a/Tasks/src/TaskStorage/ArrayTaskStorage.php b/Tasks/src/TaskStorage/ArrayTaskStorage.php new file mode 100644 index 0000000..99f717a --- /dev/null +++ b/Tasks/src/TaskStorage/ArrayTaskStorage.php @@ -0,0 +1,295 @@ +fileName = $fileName; + $this->refreshTasks(); + } + + /** + * @inheritDoc + * @throws TasksException + */ + public function addTask(Task $task): bool + { + // Check if the task doesn't exist yet + $taskId = $task->getId(); + foreach ($this->tasks as $t) + { + if ($t->getId() === $taskId) + throw new TasksException("Could not add Task to TaskStorage. Task '$taskId' already exists."); + } + + $this->tasks[] = $task; + $this->commit(); + return true; + } + + /** + * @inheritDoc + */ + public function readTasks(): array + { + return $this->tasks; + } + + /** + * @inheritDoc + */ + public function refreshTasks() + { + $this->tasks = []; + $this->data = (array) include $this->fileName; + if (empty($this->data)) + $this->data = ['tasks' => []]; + + foreach ($this->data['tasks'] as $taskString) + $this->tasks[] = unserialize($taskString); + } + + /** + * @inheritDoc + * @throws TasksException + */ + public function getTaskById(string $identifier): Task + { + foreach ($this->tasks as $t) + { + if ($t->getId() === $identifier) + return $t; + } + + throw new TasksException("Could not get task by Id. Task not found."); + } + + /** + * @inheritDoc + * @throws TasksException + */ + public function modifyTask(Task $task): bool + { + $taskId = $task->getId(); + for ($i=0;$itasks);$i++) + { + if ($this->tasks[$i]->getId() === $taskId) + { + $this->tasks[$i] = $task; + $this->commit(); + return true; + } + } + + throw new TasksException("Could not modify task. Task '$taskId' doesn't exist."); + } + + /** + * @inheritDoc + * @throws TasksException + */ + public function deleteTask(Task $task): bool + { + $taskId = $task->getId(); + for ($i=0;$itasks);$i++) + { + if ($this->tasks[$i]->getId() === $taskId) + { + // Remove the task from the main storage + unset($this->tasks[$i]); + $this->commit(); + + // Afterwards remove the task output, if it exists + $file = dirname($this->fileName) . DS . 'task_' . md5($taskId) . '_output.json'; + if (file_exists($file)) + unlink($file); + + return true; + } + } + + throw new TasksException("Could not delete task. Task '$taskId' doesn't exist."); + } + + /** + * @inheritDoc + * @throws TasksException + */ + public function writeTaskOutput(Task $task, string $output, string $errors, int $statusCode): bool + { + // Get the directory of the main storage + $dir = dirname($this->fileName); + $file = $dir . DS . 'task_' . md5($task->getId()) . '_output.json'; + $contents = json_encode(['taskId' => $task->getId(), 'output' => $output, 'errors' => $errors, 'statusCode' => $statusCode]); + + // If file already exists, panic + if (file_exists($file)) + throw new TasksException("Could not write task output. Output already written!"); + + if (!$this->write_file($file, $contents)) + throw new TasksException("Could not write task output. File error."); + + return true; + } + + /** + * @inheritDoc + * @throws TasksException + */ + public function writePostOutput(Task $task, string $output, string $errors, int $statusCode): bool + { + // Get the directory of the main storage + $dir = dirname($this->fileName); + $file = $dir . DS . 'task_' . md5($task->getId()) . '_post_output.json'; + $contents = json_encode(['taskId' => $task->getId(), 'output' => $output, 'errors' => $errors, 'statusCode' => $statusCode]); + + // If file already exists, panic + if (file_exists($file)) + throw new TasksException("Could not write task output. Output already written!"); + + if (!$this->write_file($file, $contents)) + throw new TasksException("Could not write task output. File error."); + + return true; + } + + /** + * @inheritDoc + */ + public function readTaskOutput(Task $task): ?array + { + // Get the directory of the main storage + $dir = dirname($this->fileName); + $file = $dir . DS . 'task_' . md5($task->getId()) . '_output.json'; + $file2 = $dir . DS . 'task_' . md5($task->getId()) . '_post_output.json'; + + // If file doesn't exist, return so + if (!file_exists($file)) + return null; + + // Decode the contents + $contents = file_get_contents($file); + $data = json_decode($contents, true); + $output = ['output' => $data['output'], 'errors' => $data['errors'], 'statusCode' => $data['statusCode']]; + + // Add post data if necessary + if (file_exists($file2)) + { + $postContents = file_get_contents($file2); + $postData = json_decode($postContents, true); + $output['postOutput'] = $postData['output']; + $output['postErrors'] = $postData['errors']; + $output['postStatus'] = $postData['statusCode']; + } + + // And return them + return $output; + } + + private function commit() + { + $this->data = ['tasks' => []]; + foreach ($this->tasks as $task) + $this->data['tasks'][] = serialize($task); + + $content = var_export($this->data, true); + file_put_contents($this->fileName, "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 + $task = $this->taskStorage->getTaskById($taskID); + + // Fire a taskHandleEvent + /** @var TaskHandleEvent $event */ + $event = Events::fireEvent(new TaskHandleEvent(), $task); + $task = $event->getTask(); + + // Fetch the callable + $class = $task->getHandlerClass(); + if (!class_exists($class, true)) + throw new TasksException("Could not run task. '$class' not found."); + + // Create the handler + /** @var Handler $object */ + $object = new $class(); + if (!$object instanceof Handler) + 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($task); + $postOutput = $object->getPostOutput(); + $postOutput = is_null($postOutput) ? '' : (string) $postOutput; + $postErrors = $this->getErrors(); + + if (!$postSuccess) + $this->taskStorage->writePostOutput($task, $postOutput, $postErrors, Task::FAILED); + else + $this->taskStorage->writePostOutput($task, $postOutput, $postErrors, Task::SUCCESS); + + $this->output($postOutput, $postErrors); + return; + } + + // And execute + $success = $object->primaryHandler($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($task, $output, $errors, Task::FAILED); + else + $this->taskStorage->writeTaskOutput($task, $output, $errors, Task::SUCCESS); + + $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); + 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; + } +} \ No newline at end of file diff --git a/Tasks/storage.php b/Tasks/storage.php new file mode 100644 index 0000000..ba34c2d --- /dev/null +++ b/Tasks/storage.php @@ -0,0 +1,3 @@ + [] +) ; \ No newline at end of file diff --git a/Tasks/supervisor.php b/Tasks/supervisor.php new file mode 100644 index 0000000..1401a0d --- /dev/null +++ b/Tasks/supervisor.php @@ -0,0 +1,84 @@ +setTimeZone('Europe/Amsterdam'); +$configurator->setTempDirectory(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'temp'); +$configurator->setLogDirectory(dirname(__DIR__). DIRECTORY_SEPARATOR . 'log'); + +// Enable components +// WebComponent +$webAppComponent = new WebAppComponent(); +$configurator->addComponent($webAppComponent); + +// Add directories +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Config', 'config', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Helper', 'helpers', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Library', 'libraries', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Plugin', 'plugins', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Controller', 'controllers', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'View', 'views', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Model', 'models', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Layout', 'layouts', Priority::NORMAL); + +// Debug +$configurator->enableDebugMode()->setDebugAddress('ALL'); +$container = $configurator->createContainer(); + +Logger::enableScreenLog(); + +// RUN THE APP +/** @var Tasks $lib */ +$lib = $container->libraries->get('tasks'); + +$supervisor = $lib->getSuperVisor(); +while ($supervisor->cycle() === SuperVisor::RUNNING) { + usleep(250000); +} \ No newline at end of file diff --git a/Tasks/worker.php b/Tasks/worker.php new file mode 100644 index 0000000..d9cdf87 --- /dev/null +++ b/Tasks/worker.php @@ -0,0 +1,82 @@ +setTimeZone('Europe/Amsterdam'); +$configurator->setTempDirectory(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'temp'); +$configurator->setLogDirectory(dirname(__DIR__). DIRECTORY_SEPARATOR . 'log'); + +// Enable components +// WebComponent +$webAppComponent = new WebAppComponent(); +$configurator->addComponent($webAppComponent); + +// Add directories +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Config', 'config', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Helper', 'helpers', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Library', 'libraries', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Plugin', 'plugins', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Controller', 'controllers', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'View', 'views', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Model', 'models', Priority::HIGH); +$configurator->addDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Layout', 'layouts', Priority::NORMAL); + +// Debug +$configurator->enableDebugMode()->setDebugAddress('ALL'); +$container = $configurator->createContainer(); +//\FuzeWorks\Logger::enableScreenLog(); + +// 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('tasks'); +$worker = $lib->getWorker(); +$worker->run($taskID, $post); \ No newline at end of file