Initial commit
This commit is contained in:
commit
8ccb179643
169
Tasks/Tasks.php
Normal file
169
Tasks/Tasks.php
Normal file
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library;
|
||||
use Application\Library\Tasks\Executor;
|
||||
use Application\Library\Tasks\SuperVisor;
|
||||
use Application\Library\Tasks\Task;
|
||||
use Application\Library\Tasks\TasksException;
|
||||
use Application\Library\Tasks\TaskStorage;
|
||||
use Application\Library\Tasks\Worker;
|
||||
use FuzeWorks\Config;
|
||||
use FuzeWorks\ConfigORM\ConfigORM;
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Exception\Exception;
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\iLibrary;
|
||||
use FuzeWorks\Priority;
|
||||
|
||||
class Tasks implements iLibrary
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ConfigORM
|
||||
*/
|
||||
private $cfg;
|
||||
|
||||
/**
|
||||
* Tasks constructor.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var Config $config */
|
||||
$config = Factory::getInstance('config');
|
||||
$config->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';
|
||||
}
|
||||
}
|
53
Tasks/config.tasks.php
Normal file
53
Tasks/config.tasks.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
return array(
|
||||
'SuperVisor' => [
|
||||
'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']
|
||||
]
|
||||
);
|
68
Tasks/src/Constraint.php
Normal file
68
Tasks/src/Constraint.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
|
||||
|
||||
interface Constraint
|
||||
{
|
||||
/**
|
||||
* Whether this constraint intervenes on the current situation.
|
||||
*
|
||||
* Return true ONLY when this constraint changes the execution of the Task. Otherwise return false.
|
||||
*
|
||||
* @param Task $task
|
||||
* @return bool
|
||||
*/
|
||||
public function intervene(Task $task): bool;
|
||||
|
||||
/**
|
||||
* When intervene() returns true, this method should return the new status of the task.
|
||||
*
|
||||
* Return 0 when the task should remain unchanged.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function blockCode(): int;
|
||||
|
||||
/**
|
||||
* In case blockCode() returns Task::DELAYED, this method shall return the actual delay time
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function delayTime(): int;
|
||||
|
||||
}
|
63
Tasks/src/Events/TaskHandleEvent.php
Normal file
63
Tasks/src/Events/TaskHandleEvent.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks\Events;
|
||||
use Application\Library\Tasks\Task;
|
||||
use FuzeWorks\Event;
|
||||
|
||||
class TaskHandleEvent extends Event
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Task
|
||||
*/
|
||||
protected $task;
|
||||
|
||||
public function init(Task $task)
|
||||
{
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
public function getTask(): Task
|
||||
{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
public function updateTask(Task $task)
|
||||
{
|
||||
$this->task = $task;
|
||||
}
|
||||
}
|
73
Tasks/src/Executor.php
Normal file
73
Tasks/src/Executor.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
|
||||
|
||||
interface Executor
|
||||
{
|
||||
|
||||
// Control methods
|
||||
/**
|
||||
* Start executing a task.
|
||||
*
|
||||
* Returns the Task since it makes modifications. Has to be modified in TaskStorage by SuperVisor.
|
||||
*
|
||||
* @param Task $task
|
||||
* @param bool $post
|
||||
* @return Task
|
||||
*/
|
||||
public function startTask(Task $task, bool $post = false): Task;
|
||||
|
||||
/**
|
||||
* Stops the execution of a task.
|
||||
*
|
||||
* Returns the task since it makes modifications. Has to be modified in TaskStorage by SuperVisor.
|
||||
*
|
||||
* @param Task $task
|
||||
* @return Task
|
||||
*/
|
||||
public function stopTask(Task $task): Task;
|
||||
|
||||
// Task info
|
||||
public function getTaskRunning(Task $task): bool;
|
||||
public function getTaskStats(Task $task): ?array;
|
||||
public function getTaskExitCode(Task $task): ?int;
|
||||
|
||||
// All tasks info
|
||||
public function getRunningTasks(): array;
|
||||
|
||||
}
|
150
Tasks/src/Executors/ShellExecutor.php
Normal file
150
Tasks/src/Executors/ShellExecutor.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks\Executors;
|
||||
use Application\Library\Tasks\Executor;
|
||||
use Application\Library\Tasks\Task;
|
||||
use Application\Library\Tasks\TasksException;
|
||||
|
||||
class ShellExecutor implements Executor
|
||||
{
|
||||
|
||||
private $binary;
|
||||
private $worker;
|
||||
private $stdout = "> /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.
|
||||
}
|
||||
}
|
77
Tasks/src/Handler.php
Normal file
77
Tasks/src/Handler.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
interface Handler
|
||||
{
|
||||
|
||||
/**
|
||||
* The handler method used to handle this task.
|
||||
* This handler will execute the actual task.
|
||||
*
|
||||
* Should return true when successful. Return false when failed.
|
||||
*
|
||||
* @param Task $task
|
||||
* @return bool
|
||||
*/
|
||||
public function primaryHandler(Task $task): bool;
|
||||
|
||||
/**
|
||||
* Any output generated by primaryHandler should be returned here.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOutput();
|
||||
|
||||
/**
|
||||
* The handler method used after the primaryHandler if so requested
|
||||
*
|
||||
* The task will instruct the supervisor whether the postHandler is to be called.
|
||||
*
|
||||
* Remember: postHandler is called in a new process. Data is not shared between processes unless done manually.
|
||||
* @param Task $task
|
||||
* @return bool
|
||||
*/
|
||||
public function postHandler(Task $task): bool;
|
||||
|
||||
/**
|
||||
* Any output generated by postHandler should be returned here
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPostOutput();
|
||||
|
||||
}
|
65
Tasks/src/SuperVisor.php
Normal file
65
Tasks/src/SuperVisor.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
|
||||
|
||||
interface SuperVisor
|
||||
{
|
||||
const RUNNING = 1;
|
||||
const CONSTRAINED = 2;
|
||||
const FINISHED = 3;
|
||||
|
||||
/**
|
||||
* SuperVisor constructor.
|
||||
*
|
||||
* @param TaskStorage $taskStorage
|
||||
* @param Executor $executor
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(TaskStorage $taskStorage, Executor $executor, array $options = []);
|
||||
|
||||
/**
|
||||
* Cycles the tasks.
|
||||
*
|
||||
* Should return SuperVisor::RUNNING while still overseeing running tasks.
|
||||
* Should return SuperVisor::CONSTRAINED when no tasks or running, but some tasks are still queued but constrained
|
||||
* Should return SuperVisor::FINISHED when all tasks are finished
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function cycle(): int;
|
||||
}
|
211
Tasks/src/Supervisors/ParallelSuperVisor.php
Normal file
211
Tasks/src/Supervisors/ParallelSuperVisor.php
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks\Supervisors;
|
||||
use Application\Library\Tasks\Executor;
|
||||
use Application\Library\Tasks\SuperVisor;
|
||||
use Application\Library\Tasks\Task;
|
||||
use Application\Library\Tasks\TasksException;
|
||||
use Application\Library\Tasks\TaskStorage;
|
||||
|
||||
class ParallelSuperVisor implements SuperVisor
|
||||
{
|
||||
/**
|
||||
* @var TaskStorage
|
||||
*/
|
||||
protected $taskStorage;
|
||||
|
||||
/**
|
||||
* @var Executor
|
||||
*/
|
||||
protected $executor;
|
||||
|
||||
/**
|
||||
* @var Task[]
|
||||
*/
|
||||
protected $tasks = [];
|
||||
|
||||
public function __construct(TaskStorage $taskStorage, Executor $executor, array $options = [])
|
||||
{
|
||||
$this->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;$i<count($this->tasks);$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;
|
||||
}
|
||||
|
||||
|
||||
}
|
358
Tasks/src/Task.php
Normal file
358
Tasks/src/Task.php
Normal file
@ -0,0 +1,358 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
class Task
|
||||
{
|
||||
|
||||
const PENDING = 1;
|
||||
const RUNNING = 2;
|
||||
const FAILED = 3;
|
||||
const SUCCESS = 4;
|
||||
const POST = 5;
|
||||
const COMPLETED = 6;
|
||||
const DELAYED = 7;
|
||||
const CANCELLED = 8;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $taskId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $handlerClass;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $status = Task::PENDING;
|
||||
|
||||
/**
|
||||
* @var Constraint[]
|
||||
*/
|
||||
protected $constraints = [];
|
||||
|
||||
/**
|
||||
* When the status of this task is Task::DELAYED, this is the amount of time in seconds before it should be tried again.
|
||||
*
|
||||
* @var int Delay time in seconds
|
||||
*/
|
||||
protected $delayTime = 0;
|
||||
|
||||
/**
|
||||
* The output of the execution of this task
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $output;
|
||||
protected $postOutput;
|
||||
|
||||
/**
|
||||
* The errors thrown by the execution of this task
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $errors;
|
||||
protected $postErrors;
|
||||
|
||||
/**
|
||||
* Contains a key, value array with properties of this Task
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Whether the post handler should be called after every task execution
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $callPostHandler = false;
|
||||
|
||||
/**
|
||||
* Whether the post handler should be called after execution has failed
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $callPostHandlerWhenFailed = false;
|
||||
|
||||
/**
|
||||
* Task constructor.
|
||||
*
|
||||
* Creates a Task object, which can be added to the TaskQueue.
|
||||
*
|
||||
* @param string $identifier The unique identifier of this task. Make sure it is always unique!
|
||||
* @param string $handlerClass The class that shall handle this task
|
||||
* @param mixed $parameters,... The arguments provided to the method that shall handle this class
|
||||
* @throws TasksException
|
||||
*/
|
||||
public function __construct(string $identifier, string $handlerClass)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
|
||||
|
||||
}
|
41
Tasks/src/TaskFailException.php
Normal file
41
Tasks/src/TaskFailException.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
|
||||
class TaskFailException extends TasksException
|
||||
{
|
||||
}
|
121
Tasks/src/TaskStorage.php
Normal file
121
Tasks/src/TaskStorage.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
|
||||
interface TaskStorage
|
||||
{
|
||||
|
||||
/**
|
||||
* Add a task to the TaskStorage.
|
||||
*
|
||||
* @param Task $task
|
||||
* @return bool
|
||||
*/
|
||||
public function addTask(Task $task): bool;
|
||||
|
||||
/**
|
||||
* Retrieves a list of all tasks logged in the system
|
||||
*
|
||||
* @return Task[]
|
||||
*/
|
||||
public function readTasks(): array;
|
||||
|
||||
/**
|
||||
* Reload the list of all tasks.
|
||||
*/
|
||||
public function refreshTasks();
|
||||
|
||||
/**
|
||||
* Retrieves an individual task by its identifier
|
||||
*
|
||||
* @param string $identifier
|
||||
* @return Task
|
||||
* @throws TasksException
|
||||
*/
|
||||
public function getTaskById(string $identifier): Task;
|
||||
|
||||
/**
|
||||
* Modifies a task
|
||||
*
|
||||
* @param Task $task
|
||||
* @return bool
|
||||
* @throws TasksException
|
||||
*/
|
||||
public function modifyTask(Task $task): bool;
|
||||
|
||||
/**
|
||||
* Delete a task from the TaskStorage. Should not be used to finish a task!
|
||||
*
|
||||
* @param Task $task
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteTask(Task $task): bool;
|
||||
|
||||
/**
|
||||
* Write the task output into TaskStorage.
|
||||
*
|
||||
* @param Task $task
|
||||
* @param string $output
|
||||
* @param string $errors
|
||||
* @param int $statusCode
|
||||
* @return bool
|
||||
*/
|
||||
public function writeTaskOutput(Task $task, string $output, string $errors, int $statusCode): bool;
|
||||
|
||||
/**
|
||||
* Write the output of the postHandler into TaskStorage
|
||||
*
|
||||
* @param Task $task
|
||||
* @param string $output
|
||||
* @param string $errors
|
||||
* @param int $statusCode
|
||||
* @return bool
|
||||
*/
|
||||
public function writePostOutput(Task $task, string $output, string $errors, int $statusCode): bool;
|
||||
|
||||
/**
|
||||
* Read the task output from taskStorage.
|
||||
*
|
||||
* The following output is expected:
|
||||
* array('output' => string $output, 'errors' => string $errors, 'status' => $code)
|
||||
* OR null of not found (yet)
|
||||
*
|
||||
* @param Task $task
|
||||
* @return array
|
||||
*/
|
||||
public function readTaskOutput(Task $task): ?array;
|
||||
}
|
295
Tasks/src/TaskStorage/ArrayTaskStorage.php
Normal file
295
Tasks/src/TaskStorage/ArrayTaskStorage.php
Normal file
@ -0,0 +1,295 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks\TaskStorage;
|
||||
use Application\Library\Tasks\Task;
|
||||
use Application\Library\Tasks\TasksException;
|
||||
use Application\Library\Tasks\TaskStorage;
|
||||
|
||||
class ArrayTaskStorage implements TaskStorage
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of the file this storage edits
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fileName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* @var Task[]
|
||||
*/
|
||||
protected $tasks = [];
|
||||
|
||||
/**
|
||||
* ArrayTaskStorage constructor.
|
||||
*
|
||||
* @param string $fileName Name of the Storage file
|
||||
* @throws TasksException
|
||||
*/
|
||||
public function __construct(string $fileName)
|
||||
{
|
||||
if (!file_exists($fileName))
|
||||
throw new TasksException("Could not construct ArrayTaskStorage. Storage file '$fileName' doesn't exist.");
|
||||
|
||||
if (!is_writable($fileName))
|
||||
throw new TasksException("Could not construct ArrayTaskStorage. Storage file '$fileName' is not modifiable.");
|
||||
|
||||
$this->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;$i<count($this->tasks);$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;$i<count($this->tasks);$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, "<?php return $content ;");
|
||||
}
|
||||
|
||||
/**
|
||||
* Write File
|
||||
*
|
||||
* Writes data to the file specified in the path.
|
||||
* Creates a new file if non-existent.
|
||||
*
|
||||
* @param string $path File path
|
||||
* @param string $data Data to write
|
||||
* @param string $mode fopen() mode (default: 'wb')
|
||||
* @return bool
|
||||
*/
|
||||
private function write_file($path, $data, $mode = 'wb')
|
||||
{
|
||||
if ( ! $fp = @fopen($path, $mode))
|
||||
return false;
|
||||
|
||||
flock($fp, LOCK_EX);
|
||||
|
||||
for ($result = $written = 0, $length = strlen($data); $written < $length; $written += $result)
|
||||
if (($result = fwrite($fp, substr($data, $written))) === false)
|
||||
break;
|
||||
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
|
||||
return is_int($result);
|
||||
}
|
||||
}
|
42
Tasks/src/TasksException.php
Normal file
42
Tasks/src/TasksException.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
use FuzeWorks\Exception\LibraryException;
|
||||
|
||||
class TasksException extends LibraryException
|
||||
{
|
||||
}
|
171
Tasks/src/Worker.php
Normal file
171
Tasks/src/Worker.php
Normal file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks CLIComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace Application\Library\Tasks;
|
||||
use Application\Library\Tasks\Events\TaskHandleEvent;
|
||||
use FuzeWorks\Event\HaltExecutionEvent;
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Exception\EventException;
|
||||
use FuzeWorks\Logger;
|
||||
use FuzeWorks\Priority;
|
||||
|
||||
class Worker
|
||||
{
|
||||
|
||||
/**
|
||||
* @var TaskStorage
|
||||
*/
|
||||
protected $taskStorage;
|
||||
|
||||
public function __construct(TaskStorage $taskStorage)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
3
Tasks/storage.php
Normal file
3
Tasks/storage.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php return array (
|
||||
'tasks' => []
|
||||
) ;
|
84
Tasks/supervisor.php
Normal file
84
Tasks/supervisor.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks Application Skeleton.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
use Application\Library\Tasks;
|
||||
use Application\Library\Tasks\Executors\ShellExecutor;
|
||||
use Application\Library\Tasks\SuperVisor;
|
||||
use Application\Library\Tasks\Supervisors\ParallelSuperVisor;
|
||||
use Application\Library\Tasks\TaskStorage\ArrayTaskStorage;
|
||||
use FuzeWorks\Logger;
|
||||
use FuzeWorks\Priority;
|
||||
use FuzeWorks\WebAppComponent;
|
||||
|
||||
require_once(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor/autoload.php');
|
||||
|
||||
// Open configurator
|
||||
$configurator = new FuzeWorks\Configurator();
|
||||
|
||||
// Set up basic settings
|
||||
$configurator->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);
|
||||
}
|
82
Tasks/worker.php
Normal file
82
Tasks/worker.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks Application Skeleton.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
use Application\Library\Tasks;
|
||||
use FuzeWorks\Priority;
|
||||
use FuzeWorks\WebAppComponent;
|
||||
|
||||
require_once(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor/autoload.php');
|
||||
|
||||
// Open configurator
|
||||
$configurator = new FuzeWorks\Configurator();
|
||||
|
||||
// Set up basic settings
|
||||
$configurator->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);
|
Loading…
Reference in New Issue
Block a user