/** * Modify task in queue * @param Task $task * @throws Exceptions\QueueException * @return Task */ public function modify_task($task) { if (!$task instanceof Task) { return false; } $need_commit = false; if ($task->have_subtasks()) { $need_commit = true; $database_data = $this->driver->prepare_modify($task->get_uniqid()); if (is_null($database_data)) { throw new QueueException('Task for modify not found'); } foreach ($database_data as $id => $task_database_data) { /** * @var Task $modify_task */ $current_task = $id == 0 ? $task : $task->sub_tasks()->get($task_database_data[TaskConst::UNIQID]); $current_task_data = $current_task->to_array(); //check not modified parameters foreach ($this->not_modifiable_parameters as $not_modifiable_parameter) { if ($current_task_data[$not_modifiable_parameter] != $task_database_data[$not_modifiable_parameter]) { throw new QueueException("Parameter {$not_modifiable_parameter} was changed"); } } $diff = array_diff($current_task_data, $task_database_data); $current_task->set_array($diff); } $task->set_subtasks_quantity_not_performed(0)->set_subtasks_error(0); $have_in_process = false; foreach ($task->sub_tasks()->get_all() as $sub_task) { if ($sub_task->get_status() == Task::STATUS_IN_PROCESS) { $have_in_process = true; } switch ($sub_task->get_status()) { case Task::STATUS_CALLBACK_ERROR: $task->completed_error(Task::STATUS_CALLBACK_ERROR); case Task::STATUS_ERROR: $task->inc_subtasks_error(); if ($sub_task->settings()->get_nested_settings('error_break')) { $task->completed_error(); } break; case Task::STATUS_NEW: $task->inc_subtasks_quantity_not_performed(); break; } } if (!$have_in_process && $task->get_subtasks_quantity_not_performed() == 0 && !in_array($task->get_status(), array(Task::STATUS_ERROR, Task::STATUS_CALLBACK_ERROR))) { if ($task->get_subtasks_error() > 0) { $task->completed_error(Task::STATUS_DONE_WITH_ERROR); } else { $task->completed_ok(); } } $this->driver->modify_task($task->sub_tasks()->get_perform_task()); } $this->driver->modify_task($task, $need_commit); return $task; }
/** * SetUp tasks in queue */ public static function setUpBeforeClass() { static::prepareTestExecution(); self::$queue = new \PhpQueue\Queue(static::getQueueDriver()); self::$task_performer1 = new \PhpQueue\TaskPerformer(); self::$task_performer2 = new \PhpQueue\TaskPerformer(self::EXCLUSIVE_PERFORMER); //one task $task = new Task(self::JOB, self::TASK_ARGS); $task->set_callback(self::TASK_JOB_CALLBACK)->set_error_callback(self::TASK_JOB_CALLBACK); self::$queue->add_task($task); //task with sub tasks $task = new Task(self::JOB, self::TASK_ARGS); $task->set_callback(self::TASK_JOB_CALLBACK)->set_error_callback(self::TASK_JOB_CALLBACK); for ($i = 0; $i < self::TASKS_COUNT_5; $i++) { $sub_task = new Task(self::JOB_1, $i); $sub_task->set_callback(self::SUB_TASK_JOB_CALLBACK)->set_error_callback(self::SUB_TASK_JOB_CALLBACK); $task->sub_tasks()->add($sub_task); } self::$queue->add_task($task); //task with sub tasks and error break false and exclusive $task = new Task(self::JOB_2); $task->set_callback(self::TASK_JOB_CALLBACK)->set_error_callback(self::TASK_JOB_CALLBACK)->set_exclusive(true); for ($i = 0; $i < self::TASKS_COUNT_3; $i++) { $sub_task = new Task(self::JOB_2, $i); $task->sub_tasks()->add($sub_task); } self::$queue->add_task($task); //task with error $task = new Task(self::JOB); $task->set_callback(self::TASK_JOB_CALLBACK)->set_error_callback(self::TASK_JOB_CALLBACK)->settings()->set_error_break(false)->set_error_max_trial(self::TASKS_COUNT_3); for ($i = 0; $i < self::TASKS_COUNT_5; $i++) { if ($i == 2) { $sub_task = new Task(self::ERROR_JOB, $i); } else { $sub_task = new Task(self::JOB_2, $i); } $task->sub_tasks()->add($sub_task); } self::$queue->add_task($task); //task with subtasks and error $task = new Task(self::JOB); $task->set_task_group_id(2)->settings()->set_error_break(true)->set_error_max_trial(2); $sub_task = new Task(self::ERROR_JOB); $task->sub_tasks()->add($sub_task); for ($i = 0; $i < 3; $i++) { $sub_task = new Task(self::JOB_2, $i); $task->sub_tasks()->add($sub_task); } self::$queue->add_task($task); $task = new Task(self::ERROR_JOB); $task->set_task_group_id(3); self::$queue->add_task($task); }
/** * Execute task * @param Task $task * @return Task */ public function execute_task($task) { if (!$task instanceof Task) { return false; } if (is_null($task->get_start_date())) { $task->set_start_date(date('Y-m-d H:i:s')); } $task->set_performer($this->performer_name); if ($task->have_subtasks()) { if (!$task->get_exclusive()) { $task->null_performer(); } $this->execute_task($task->sub_tasks()->get_perform_task()); return $task; } $callback_classes_founded = $task->check_callback_class_names(); if (!$callback_classes_founded) { $task->set_status(Task::STATUS_ERROR); return $task; } $exec_array = $this->default_job_priority; for ($job_id = 0; $job_id < count($exec_array); $job_id++) { /** * @var \PhpQueue\Interfaces\IJob|\PhpQueue\Interfaces\ICallback|\PhpQueue\Interfaces\IErrorCallback */ $exec_class = null; $job_type = $exec_array[$job_id]; switch ($job_type) { case TaskConst::JOB: $exec_class = $task->get_task_name(); break; case TaskConst::TASK_CALLBACK: $exec_class = $task->get_callback(); break; case TaskConst::PARENT_CALLBACK: $exec_class = $task->get_parent_callback(); break; case TaskConst::GLOBAL_CALLBACK: $exec_class = $this->get_global_callback(); break; case TaskConst::TASK_ERROR_CALLBACK: $exec_class = $task->get_error_callback(); break; case TaskConst::PARENT_ERROR_CALLBACK: $exec_class = $task->get_parent_error_callback(); break; case TaskConst::GLOBAL_ERROR_CALLBACK: $exec_class = $this->get_global_error_callback(); break; } if (is_null($exec_class)) { continue; } $method_name = $this->interface_methods[Helper::interface_job($job_type)]; try { $response = call_user_func_array(array($exec_class, $method_name), array($task)); if ($job_type == TaskConst::JOB) { $task->completed_ok()->response()->set_response($response); } } catch (\Exception $exception) { $task->response()->set_error($exception->getMessage() . " File: " . $exception->getFile() . " Line: " . $exception->getLine()); if ($job_type != TaskConst::JOB) { $task->set_status(Task::STATUS_CALLBACK_ERROR); break; } $job_id = 0; $exec_array = $this->default_error_job_priority; if ($task->settings()->get_trial() >= $task->settings()->get_nested_settings('error_max_trial')) { $task->completed_error(); } else { $task->set_status(Task::STATUS_NEW)->settings()->inc_trial(); } } } return $task; }
/** * Get data from data provider, generate and return task * @param array $request * @return mixed */ public function get_task(array $request) { $request = array_filter($request); if (array_key_exists(TaskConst::UNIQID, $request)) { $request[TaskConst::NEED_SET_IN_PROCESS_FLAG] = false; } $this->lock_file(); $xml_dom = $this->get_xml_dom(); $result = call_user_func(function () use($xml_dom, $request) { $head_task = $this->xpath_find($xml_dom, $request); if (is_null($head_task)) { return false; } //select task from file $head_task_array = $this->get_task_array_from_file((string) $head_task[TaskConst::UNIQID]); if ($request[TaskConst::NEED_SET_IN_PROCESS_FLAG]) { //set status for task and index record if ((int) $head_task[TaskConst::STATUS] == Task::STATUS_NEW) { $head_task[TaskConst::STATUS] = Task::STATUS_IN_PROCESS; $head_task_array[TaskConst::STATUS] = Task::STATUS_IN_PROCESS; } if ((int) $head_task[TaskConst::SUBTASKS_QUANTITY_NOT_PERFORMED] > 0) { $head_task[TaskConst::SUBTASKS_QUANTITY_NOT_PERFORMED] = (int) $head_task[TaskConst::SUBTASKS_QUANTITY_NOT_PERFORMED] - 1; $head_task_array[TaskConst::SUBTASKS_QUANTITY_NOT_PERFORMED]--; } $this->save_array($head_task_array); } $task = new Task($head_task_array); // select sub tasks if (!property_exists($head_task, self::SUB_TASKS_XML)) { $this->save_xml_dom($xml_dom); return $task; } $perform_id = null; $sub_tasks = array(); foreach ($head_task->{self::SUB_TASKS_XML}->{self::TASK_XML} as $sub_task) { $sub_task = (array) $sub_task; $sub_tasks[] = $sub_task['@attributes']; } unset($sub_task); if ($request[TaskConst::NEED_SET_IN_PROCESS_FLAG]) { foreach ($sub_tasks as $sub_task) { if ((int) $sub_task[TaskConst::STATUS] != Task::STATUS_NEW) { continue; } $sub_task[TaskConst::STATUS] = Task::STATUS_IN_PROCESS; $sub_task_array = $this->get_task_array_from_file($sub_task[TaskConst::UNIQID]); $sub_task_array[TaskConst::STATUS] = Task::STATUS_IN_PROCESS; $this->save_array($sub_task_array); $perform_id = $sub_task[TaskConst::UNIQID]; break; } } foreach ($sub_tasks as $sub_task) { $sub_task_params = $this->get_task_array_from_file($sub_task[TaskConst::UNIQID]); if ($perform_id == $sub_task[TaskConst::UNIQID]) { $task->sub_tasks()->add_perform_task(new Task($sub_task_params)); continue; } $task->sub_tasks()->add(new Task($sub_task_params)); } $this->save_xml_dom($xml_dom); return $task; }); $this->release_file(); return $result; }
/** * Get data from data provider, generate and return task * @param array $request * @return mixed */ public function get_task(array $request) { $request = array_filter($request); $this->connection->beginTransaction(); $task = call_user_func(function () use($request) { if (array_key_exists(TaskConst::UNIQID, $request)) { $request[TaskConst::NEED_SET_IN_PROCESS_FLAG] = false; } $head_task = $this->select_task($request); if (!$head_task) { return false; } $task = new Task($head_task); if ($head_task[TaskConst::SUBTASKS_QUANTITY] > 0) { $sub_task_request = array(TaskConst::PARENT_ID => $head_task[TaskConst::UNIQID], TaskConst::NEED_SET_IN_PROCESS_FLAG => $request[TaskConst::NEED_SET_IN_PROCESS_FLAG]); $sub_tasks = $this->select_sub_task($sub_task_request); if (!empty($sub_tasks['sub_tasks'])) { foreach ($sub_tasks['sub_tasks'] as $sub_task) { if ($sub_task[TaskConst::UNIQID] == $sub_tasks['perform_task']) { $task->sub_tasks()->add_perform_task(new Task($sub_task)); continue; } $task->sub_tasks()->add(new Task($sub_task)); } } } return $task; }); $this->connection->commit(); return $task; }