Welcome to mirror list, hosted at ThFree Co, Russian Federation.

TaskScheduler.php « core - github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 1a29780f725c58218d4bfe786d861d1b950e1212 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<?php
/**
 * Piwik - Open source web analytics
 *
 * @link http://piwik.org
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 *
 * @category Piwik
 * @package Piwik
 */

// When set to true, all scheduled tasks will be triggered in all requests (careful!)
define('DEBUG_FORCE_SCHEDULED_TASKS', false);

/**
 * Piwik_TaskScheduler is the class used to manage the execution of periodicaly planned task.
 *
 * It performs the following actions :
 *    - Identifies tasks of Piwik
 *  - Runs tasks
 *
 * @package Piwik
 */

class Piwik_TaskScheduler
{
    const GET_TASKS_EVENT = "TaskScheduler.getScheduledTasks";
    const TIMETABLE_OPTION_STRING = "TaskScheduler.timetable";
    static private $running = false;

    /**
     * runTasks collects tasks defined within piwik plugins, runs them if they are scheduled and reschedules
     * the tasks that have been executed.
     *
     * @return array
     */
    static public function runTasks()
    {
        // get the array where rescheduled timetables are stored
        $timetable = self::getTimetableFromOptionTable();

        // collect tasks
        $tasks = array();
        Piwik_PostEvent(self::GET_TASKS_EVENT, $tasks);

        // remove from timetable tasks that are not active anymore
        $activeTaskNames = array();
        foreach ($tasks as $task) {
            $activeTaskNames[] = $task->getName();
        }
        foreach (array_keys($timetable) as $taskName) {
            if (!in_array($taskName, $activeTaskNames)) {
                unset($timetable[$taskName]);
            }
        }

        // for every priority level, starting with the highest and concluding with the lowest
        $executionResults = array();
        for ($priority = Piwik_ScheduledTask::HIGHEST_PRIORITY;
             $priority <= Piwik_ScheduledTask::LOWEST_PRIORITY;
             ++$priority) {
            // loop through each task
            foreach ($tasks as $task) {
                // if the task does not have the current priority level, don't execute it yet
                if ($task->getPriority() != $priority) {
                    continue;
                }

                $taskName = $task->getName();
                if (self::taskShouldBeExecuted($taskName, $timetable)) {
                    self::$running = true;
                    $message = self::executeTask($task);
                    self::$running = false;

                    $executionResults[] = array('task' => $taskName, 'output' => $message);
                }

                if (self::taskShouldBeRescheduled($taskName, $timetable)) {
                    // update the scheduled time
                    $timetable[$taskName] = $task->getRescheduledTime();
                    Piwik_SetOption(self::TIMETABLE_OPTION_STRING, serialize($timetable));
                }
            }
        }

        return $executionResults;
    }

    static public function isTaskBeingExecuted()
    {
        return self::$running;
    }

    /**
     * return the next task schedule for a given class and method name
     *
     * @param string $className
     * @param string $methodName
     * @param string $methodParameter
     * @return mixed int|bool the next schedule in miliseconds, false if task has never been run
     */
    static public function getScheduledTimeForMethod($className, $methodName, $methodParameter = null)
    {

        // get the array where rescheduled timetables are stored
        $timetable = self::getTimetableFromOptionTable();

        $taskName = Piwik_ScheduledTask::getTaskName($className, $methodName, $methodParameter);

        return self::taskHasBeenScheduledOnce($taskName, $timetable) ? $timetable[$taskName] : false;
    }

    /*
     * Task has to be executed if :
     *  - the task has already been scheduled once and the current system time is greater than the scheduled time.
     * 	- execution is forced, see $forceTaskExecution
     */
    static private function taskShouldBeExecuted($taskName, $timetable)
    {
        $forceTaskExecution =
            (isset($GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS']) && $GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS'])
                || DEBUG_FORCE_SCHEDULED_TASKS;

        return $forceTaskExecution || (self::taskHasBeenScheduledOnce($taskName, $timetable) && time() >= $timetable[$taskName]);
    }

    /*
     * Task has to be rescheduled if :
     *  - the task has to be executed
     * 	- the task has never been scheduled before
     */
    static private function taskShouldBeRescheduled($taskName, $timetable)
    {
        return !self::taskHasBeenScheduledOnce($taskName, $timetable) || self::taskShouldBeExecuted($taskName, $timetable);
    }

    static private function taskHasBeenScheduledOnce($taskName, $timetable)
    {
        return isset($timetable[$taskName]);
    }

    static private function getTimetableFromOptionValue($option)
    {
        $unserializedTimetable = @unserialize($option);
        return $unserializedTimetable === false ? array() : $unserializedTimetable;
    }

    static private function getTimetableFromOptionTable()
    {
        return self::getTimetableFromOptionValue(Piwik_GetOption(self::TIMETABLE_OPTION_STRING));
    }

    static private function executeTask($task)
    {
        try {
            $timer = new Piwik_Timer();
            call_user_func(array($task->getObjectInstance(), $task->getMethodName()), $task->getMethodParameter());
            $message = $timer->__toString();
        } catch (Exception $e) {
            $message = 'ERROR: ' . $e->getMessage();
        }

        return $message;
    }
}