isSerializable($handler)) throw new TasksException("Could not create Task. Provided Handler is not serializable."); $this->taskId = $identifier; $this->handler = $handler; $this->usePostHandler = $usePostHandler; 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; // Init the handler $this->handler->init($this); } /** * Returns the unique ID of this task * * @return string */ public function getId(): string { return $this->taskId; } /** * Gets the Handler that shall process this task * * @return Handler */ public function getHandler(): Handler { return $this->handler; } /** * Whether the postHandler on the Handler should be invoked after processing the initial task. * * @return bool */ public function getUsePostHandler(): bool { return $this->usePostHandler; } /** * 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. * * Must be one of the constants of this Task class * * @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; } /* ---------------------------------- Attributes setters and getters ------------------ */ /** * Fetch an attribute of this task * * @param string $key * @return mixed */ public function attribute(string $key) { if (!isset($this->attributes[$key])) return null; return $this->attributes[$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->attributes[$key] = $value; } /** * Remove an attribute from a Task * * @param string $key * @throws TasksException */ public function removeAttribute(string $key) { if (!isset($this->attributes[$key])) throw new TasksException("Could not remove Task '$this->taskId' attribute '$key'. Not found."); unset($this->attributes[$key]); } /* ---------------------------------- Output setters and getters ---------------------- */ /** * Return the output of this task execution * * @return string|null */ public function getOutput(): ?string { return $this->output; } public function getPostOutput(): ?string { return $this->postOutput; } /** * Return the errors of this task execution * * @return string|null */ public function getErrors(): ?string { return $this->errors; } public function getPostErrors(): ?string { return $this->postErrors; } /** * @param string $output * @param string $errors * @todo Handle output from multiple attempts */ public function setOutput(string $output, string $errors) { $this->output = $output; $this->errors = $errors; } /** * @param string $output * @param string $errors * @todo Handle output from multiple attempts */ public function setPostOutput(string $output, string $errors) { $this->postOutput = $output; $this->postErrors = $errors; } /* ---------------------------------- Failure settings and criteria ------------------- */ /** * Set whether this task should retry after a failure, and how many times * * @param bool $retryOnFail Whether this task should be retried if failing * @param int $maxRetries How many times the task should be retried * @param int $maxTime How long a task may run before it shall be forcefully shut down * @param bool $retryRegularFailures Whether regular Task::FAILED should be retried * @param bool $retryProcessFailures Whether process based Task::PFAILED should be retried * @param bool $retryPostFailures Whether failures during the Task::POST phase should be retried. */ public function setSettings(bool $retryOnFail, int $maxRetries = 2, int $maxTime = 30, bool $retryRegularFailures = true, bool $retryProcessFailures = true, bool $retryPostFailures = true) { $this->retryOnFail = $retryOnFail; $this->maxRetries = $maxRetries; $this->retryPFailures = $retryProcessFailures; $this->retryRFailures = $retryRegularFailures; $this->retryPostFailures = $retryPostFailures; $this->maxTime = $maxTime; } /** * Returns the failure retry settings * * @return array */ public function getSettings(): array { return [ 'retryOnFail' => $this->retryOnFail, 'maxRetries' => $this->maxRetries, 'retryPFailures' => $this->retryPFailures, 'retryRFailures' => $this->retryRFailures, 'retryPostFailures' => $this->retryPostFailures, 'maxTime' => $this->maxTime ]; } /* ---------------------------------- Retries and attempts registers ------------------ */ /** * Add a retry to the retry counter */ public function addRetry() { $this->retries++; } /** * Reset the retry counter back to 0 */ public function resetRetries() { $this->retries = 0; } /** * Receive the amount of retries already attempted * * @return int */ public function getRetries(): int { return $this->retries; } /* ---------------------------------- Runtime data getters and setters----------------- */ protected $taskStartTime; protected $taskEndTime; protected $postStartTime; protected $postEndTime; public function startTaskTime() { $this->taskEndTime = null; $this->taskStartTime = time(); } public function endTaskTime() { $this->taskEndTime = time(); } public function getTaskTime(): ?int { if (is_null($this->taskStartTime)) return null; if (is_null($this->taskEndTime)) return time() - $this->taskStartTime; return $this->taskEndTime - $this->taskStartTime; } public function startPostTime() { $this->postEndTime = null; $this->postStartTime = time(); } public function endPostTime() { $this->postEndTime = time(); } public function getPostTime(): ?int { if (is_null($this->postStartTime)) return null; if (is_null($this->postEndTime)) return time() - $this->postStartTime; return $this->postEndTime - $this->postStartTime; } /** * Checks whether an object can be serialized * * @param $value * @return bool * @todo Improve so it is properly tested */ 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; } }