PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Scheduler / Scheduler.php
matomo / app / core / Scheduler Last commit date
Schedule 6 years ago Scheduler.php 6 years ago Task.php 6 years ago TaskLoader.php 6 years ago Timetable.php 6 years ago
Scheduler.php
289 lines
1 <?php
2 /**
3 * Piwik - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 */
8
9 namespace Piwik\Scheduler;
10
11 use Exception;
12 use Piwik\Piwik;
13 use Piwik\Timer;
14 use Psr\Log\LoggerInterface;
15
16 /**
17 * Schedules task execution.
18 *
19 * A scheduled task is a callback that should be executed every so often (such as daily,
20 * weekly, monthly, etc.). They are registered by extending {@link \Piwik\Plugin\Tasks}.
21 *
22 * Tasks are executed when the `core:archive` command is executed.
23 *
24 * ### Examples
25 *
26 * **Scheduling a task**
27 *
28 * class Tasks extends \Piwik\Plugin\Tasks
29 * {
30 * public function schedule()
31 * {
32 * $this->hourly('myTask'); // myTask() will be executed once every hour
33 * }
34 * public function myTask()
35 * {
36 * // do something
37 * }
38 * }
39 *
40 * **Executing all pending tasks**
41 *
42 * $results = $scheduler->run();
43 * $task1Result = $results[0];
44 * $task1Name = $task1Result['task'];
45 * $task1Output = $task1Result['output'];
46 *
47 * echo "Executed task '$task1Name'. Task output:\n$task1Output";
48 */
49 class Scheduler
50 {
51 /**
52 * Is the scheduler running any task.
53 * @var bool
54 */
55 private $isRunningTask = false;
56
57 /**
58 * @var Timetable
59 */
60 private $timetable;
61
62 /**
63 * @var TaskLoader
64 */
65 private $loader;
66
67 /**
68 * @var LoggerInterface
69 */
70 private $logger;
71
72 public function __construct(TaskLoader $loader, LoggerInterface $logger)
73 {
74 $this->timetable = new Timetable();
75 $this->loader = $loader;
76 $this->logger = $logger;
77 }
78
79 /**
80 * Executes tasks that are scheduled to run, then reschedules them.
81 *
82 * @return array An array describing the results of scheduled task execution. Each element
83 * in the array will have the following format:
84 *
85 * ```
86 * array(
87 * 'task' => 'task name',
88 * 'output' => '... task output ...'
89 * )
90 * ```
91 */
92 public function run()
93 {
94 $tasks = $this->loader->loadTasks();
95
96 $this->logger->debug('{count} scheduled tasks loaded', array('count' => count($tasks)));
97
98 // remove from timetable tasks that are not active anymore
99 $this->timetable->removeInactiveTasks($tasks);
100
101 $this->logger->info("Starting Scheduled tasks... ");
102
103 // for every priority level, starting with the highest and concluding with the lowest
104 $executionResults = array();
105 for ($priority = Task::HIGHEST_PRIORITY; $priority <= Task::LOWEST_PRIORITY; ++$priority) {
106 $this->logger->debug("Executing tasks with priority {priority}:", array('priority' => $priority));
107
108 // loop through each task
109 foreach ($tasks as $task) {
110 // if the task does not have the current priority level, don't execute it yet
111 if ($task->getPriority() != $priority) {
112 continue;
113 }
114
115 $taskName = $task->getName();
116 $shouldExecuteTask = $this->timetable->shouldExecuteTask($taskName);
117
118 if ($this->timetable->taskShouldBeRescheduled($taskName)) {
119 $rescheduledDate = $this->timetable->rescheduleTask($task);
120
121 $this->logger->debug("Task {task} is scheduled to run again for {date}.", array('task' => $taskName, 'date' => $rescheduledDate));
122 }
123
124 /**
125 * Triggered before a task is executed.
126 *
127 * A plugin can listen to it and modify whether a specific task should be executed or not. This way
128 * you can force certain tasks to be executed more often or for example to be never executed.
129 *
130 * @param bool &$shouldExecuteTask Decides whether the task will be executed.
131 * @param Task $task The task that is about to be executed.
132 */
133 Piwik::postEvent('ScheduledTasks.shouldExecuteTask', array(&$shouldExecuteTask, $task));
134
135 if ($shouldExecuteTask) {
136 $message = $this->executeTask($task);
137
138 $executionResults[] = array('task' => $taskName, 'output' => $message);
139 }
140 }
141 }
142
143 $this->logger->info("done");
144
145 return $executionResults;
146 }
147
148 /**
149 * Run a specific task now. Will ignore the schedule completely.
150 *
151 * @param string $taskName
152 * @return string Task output.
153 */
154 public function runTaskNow($taskName)
155 {
156 $tasks = $this->loader->loadTasks();
157
158 foreach ($tasks as $task) {
159 if ($task->getName() === $taskName) {
160 return $this->executeTask($task);
161 }
162 }
163
164 throw new \InvalidArgumentException('Task ' . $taskName . ' not found');
165 }
166
167 /**
168 * Determines a task's scheduled time and persists it, overwriting the previous scheduled time.
169 *
170 * Call this method if your task's scheduled time has changed due to, for example, an option that
171 * was changed.
172 *
173 * @param Task $task Describes the scheduled task being rescheduled.
174 * @api
175 */
176 public function rescheduleTask(Task $task)
177 {
178 $this->logger->debug('Rescheduling task {task}', array('task' => $task->getName()));
179
180 $this->timetable->rescheduleTask($task);
181 }
182
183 /**
184 * Determines a task's scheduled time and persists it, overwriting the previous scheduled time.
185 *
186 * Call this method if your task's scheduled time has changed due to, for example, an option that
187 * was changed.
188 *
189 * The task will be run the first time tomorrow.
190 *
191 * @param Task $task Describes the scheduled task being rescheduled.
192 * @api
193 */
194 public function rescheduleTaskAndRunTomorrow(Task $task)
195 {
196 $this->logger->debug('Rescheduling task and setting first run for tomorrow {task}', array('task' => $task->getName()));
197
198 $this->timetable->rescheduleTaskAndRunTomorrow($task);
199 }
200
201 /**
202 * Returns true if the scheduler is currently running a task.
203 *
204 * @return bool
205 */
206 public function isRunningTask()
207 {
208 return $this->isRunningTask;
209 }
210
211 /**
212 * Return the next scheduled time given the class and method names of a scheduled task.
213 *
214 * @param string $className The name of the class that contains the scheduled task method.
215 * @param string $methodName The name of the scheduled task method.
216 * @param string|null $methodParameter Optional method parameter.
217 * @return mixed int|bool The time in miliseconds when the scheduled task will be executed
218 * next or false if it is not scheduled to run.
219 */
220 public function getScheduledTimeForMethod($className, $methodName, $methodParameter = null)
221 {
222 return $this->timetable->getScheduledTimeForMethod($className, $methodName, $methodParameter);
223 }
224
225 /**
226 * Returns the list of the task names.
227 *
228 * @return string[]
229 */
230 public function getTaskList()
231 {
232 $tasks = $this->loader->loadTasks();
233
234 return array_map(function (Task $task) {
235 return $task->getName();
236 }, $tasks);
237 }
238
239 /**
240 * Executes the given task
241 *
242 * @param Task $task
243 * @return string
244 */
245 private function executeTask($task)
246 {
247 $this->logger->info("Scheduler: executing task {taskName}...", array(
248 'taskName' => $task->getName(),
249 ));
250
251 $this->isRunningTask = true;
252
253 $timer = new Timer();
254
255 /**
256 * Triggered directly before a scheduled task is executed
257 *
258 * @param Task $task The task that is about to be executed
259 */
260 Piwik::postEvent('ScheduledTasks.execute', array(&$task));
261
262 try {
263 $callable = array($task->getObjectInstance(), $task->getMethodName());
264 call_user_func($callable, $task->getMethodParameter());
265 $message = $timer->__toString();
266 } catch (Exception $e) {
267 $message = 'ERROR: ' . $e->getMessage();
268 }
269
270 $this->isRunningTask = false;
271
272 /**
273 * Triggered after a scheduled task is successfully executed.
274 *
275 * You can use the event to execute for example another task whenever a specific task is executed or to clean up
276 * certain resources.
277 *
278 * @param Task $task The task that was just executed
279 */
280 Piwik::postEvent('ScheduledTasks.execute.end', array(&$task));
281
282 $this->logger->info("Scheduler: finished. {timeElapsed}", array(
283 'timeElapsed' => $timer,
284 ));
285
286 return $message;
287 }
288 }
289