Scalr\System\Zmq\Cron\Task\Scheduler::enqueue PHP Method

enqueue() public method

See also: Scalr\System\Zmq\Cron\TaskInterface::enqueue()
public enqueue ( )
    public function enqueue()
    {
        $queue = new ArrayObject([]);
        $db = \Scalr::getDb();
        // get active tasks: first run (condition and last_start_time is null), others (condition and last_start_time + interval * 0.9 < now())
        $taskList = $db->GetAll("\n            SELECT *\n            FROM scheduler\n            WHERE `status` = ?\n            AND (`start_time` IS NULL OR CONVERT_TZ(`start_time`,'SYSTEM',`timezone`) <= CONVERT_TZ(NOW(),'SYSTEM',`timezone`))\n            AND (`last_start_time` IS NULL OR\n                 `last_start_time` IS NOT NULL AND `start_time` IS NULL AND (CONVERT_TZ(last_start_time + INTERVAL restart_every MINUTE, 'SYSTEM', `timezone`) < CONVERT_TZ(NOW(),'SYSTEM',`timezone`)) OR\n                 `last_start_time` IS NOT NULL AND `start_time` IS NOT NULL AND (CONVERT_TZ(last_start_time + INTERVAL (restart_every * 0.9) MINUTE, 'SYSTEM', `timezone`) < CONVERT_TZ(NOW(),'SYSTEM',`timezone`))\n            )\n            ORDER BY IF (last_start_time, last_start_time, start_time) ASC\n        ", [Scalr_SchedulerTask::STATUS_ACTIVE]);
        if (!$taskList) {
            $this->getLogger()->info("There are no tasks to execute in scheduler table.");
            return $queue;
        }
        $this->getLogger()->info("Found %d tasks", count($taskList));
        foreach ($taskList as $task) {
            try {
                // check account status (active or inactive)
                if (Scalr_Account::init()->loadById($task['account_id'])->status != Scalr_Account::STATUS_ACTIVE) {
                    continue;
                }
            } catch (Exception $e) {
                $this->getLogger()->info("Scheduler task #%s could not start: %s", $task['id'], $e->getMessage());
            }
            if ($task['last_start_time'] && $task['start_time']) {
                // try to auto-align time to start time
                $startTime = new DateTime($task['start_time']);
                $startTime->setTimezone(new DateTimeZone($task['timezone']));
                $currentTime = new DateTime('now', new DateTimeZone($task['timezone']));
                $offset = $startTime->getOffset() - $currentTime->getOffset();
                $num = ($currentTime->getTimestamp() - $startTime->getTimestamp() - $offset) / ($task['restart_every'] * 60);
                $numFloor = floor($num);
                // we check tasks which are longer than hour
                if ($task['restart_every'] > 55) {
                    // check how much intervals were missed
                    $lastStartTime = new DateTime($task['last_start_time']);
                    $lastStartTime->setTimezone(new DateTimeZone($task['timezone']));
                    if (($currentTime->getTimestamp() - $lastStartTime->getTimestamp() - ($lastStartTime->getOffset() - $currentTime->getOffset())) / ($task['restart_every'] * 60) > 2) {
                        // we missed one extra (or more) interval, so let's check if currentTime is synchronized with startTime
                        if ($num - $numFloor > 0.1) {
                            $this->getLogger()->debug(sprintf('Delay task (missed interval): %s, num: %f', $task['name'], $num));
                            continue;
                        }
                    }
                }
                // because of timezone's transitions
                // num should be less than 0.5 (because of interval * 0.9 in SQL query)
                if ($numFloor != round($num, 0, PHP_ROUND_HALF_UP)) {
                    $this->getLogger()->debug(sprintf('Delay task (interval): %s, Offset: %d, num: %f, floor: %f, round: %f', $task['name'], $offset, $num, floor($num), round($num, 0, PHP_ROUND_HALF_UP)));
                    continue;
                }
            }
            $this->log('DEBUG', "Adding task %s to queue", $task['id']);
            $queue->append($task['id']);
        }
        return $queue;
    }