1
|
|
|
<?php namespace Comodojo\Extender\Scheduler; |
2
|
|
|
|
3
|
|
|
use \Cron\CronExpression; |
4
|
|
|
use \Comodojo\Exception\DatabaseException; |
5
|
|
|
use \Comodojo\Database\EnhancedDatabase; |
6
|
|
|
use \Comodojo\Extender\Cache; |
7
|
|
|
use \Comodojo\Extender\Planner; |
8
|
|
|
use \Exception; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Extender scheduler |
12
|
|
|
* |
13
|
|
|
* @package Comodojo extender |
14
|
|
|
* @author Marco Giovinazzi <[email protected]> |
15
|
|
|
* @license GPL-3.0+ |
16
|
|
|
* |
17
|
|
|
* LICENSE: |
18
|
|
|
* |
19
|
|
|
* This program is free software: you can redistribute it and/or modify |
20
|
|
|
* it under the terms of the GNU Affero General Public License as |
21
|
|
|
* published by the Free Software Foundation, either version 3 of the |
22
|
|
|
* License, or (at your option) any later version. |
23
|
|
|
* |
24
|
|
|
* This program is distributed in the hope that it will be useful, |
25
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
26
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27
|
|
|
* GNU Affero General Public License for more details. |
28
|
|
|
* |
29
|
|
|
* You should have received a copy of the GNU Affero General Public License |
30
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
31
|
|
|
*/ |
32
|
|
|
|
33
|
|
|
class Scheduler { |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Get planned schedules |
37
|
|
|
* |
38
|
|
|
* @param \Monolog\Logger $logger |
39
|
|
|
* @param float $timestamp |
40
|
|
|
* |
41
|
|
|
* @return array |
42
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
43
|
|
|
* @throws \Exception |
44
|
|
|
*/ |
45
|
3 |
|
final public static function getSchedules($logger, $timestamp) { |
46
|
|
|
|
47
|
3 |
|
$schedules = array(); |
48
|
|
|
|
49
|
3 |
|
$planned = array(); |
50
|
|
|
|
51
|
|
|
try { |
52
|
|
|
|
53
|
3 |
|
$jobs = self::getJobs(); |
54
|
|
|
|
55
|
3 |
|
foreach ( $jobs as $job ) { |
56
|
|
|
|
57
|
|
|
if ( self::shouldRunJob($job, $logger, $timestamp) ) array_push($schedules, $job); |
58
|
|
|
|
59
|
|
|
else $planned[] = self::shouldPlanJob($job); |
60
|
|
|
|
61
|
3 |
|
} |
62
|
|
|
|
63
|
3 |
|
} catch (DatabaseException $de) { |
64
|
|
|
|
65
|
|
|
$logger->error("Cannot load job list due to database error", array( |
66
|
|
|
"ERROR" => $de->getMessage(), |
67
|
|
|
"ERRID" => $de->getCode() |
68
|
|
|
)); |
69
|
|
|
|
70
|
|
|
throw $de; |
71
|
|
|
|
72
|
3 |
|
} catch (Exception $e) { |
73
|
|
|
|
74
|
|
|
$logger->error("Cannot load job list due to generic error", array( |
75
|
|
|
"ERROR" => $e->getMessage(), |
76
|
|
|
"ERRID" => $e->getCode() |
77
|
|
|
)); |
78
|
|
|
|
79
|
|
|
throw $e; |
80
|
|
|
|
81
|
|
|
} |
82
|
|
|
|
83
|
3 |
|
$logger->info("\n".sizeof($schedules)." job(s) in current queue"); |
84
|
|
|
|
85
|
3 |
|
return array($schedules, empty($planned) ? null : min($planned)); |
86
|
|
|
|
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Update schedules (last run) |
91
|
|
|
* |
92
|
|
|
* @param Object $logger |
93
|
|
|
* @param array $completed_processes |
94
|
|
|
* |
95
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
96
|
|
|
*/ |
97
|
|
|
final public static function updateSchedules($logger, $completed_processes) { |
98
|
|
|
|
99
|
|
|
if ( empty($completed_processes) ) { |
100
|
|
|
|
101
|
|
|
$logger->info("No schedule to update, exiting"); |
102
|
|
|
|
103
|
|
|
return; |
104
|
|
|
|
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
try { |
108
|
|
|
|
109
|
|
|
$db = new EnhancedDatabase( |
110
|
|
|
EXTENDER_DATABASE_MODEL, |
111
|
|
|
EXTENDER_DATABASE_HOST, |
112
|
|
|
EXTENDER_DATABASE_PORT, |
113
|
|
|
EXTENDER_DATABASE_NAME, |
114
|
|
|
EXTENDER_DATABASE_USER, |
115
|
|
|
EXTENDER_DATABASE_PASS |
116
|
|
|
); |
117
|
|
|
|
118
|
|
|
$db->tablePrefix(EXTENDER_DATABASE_PREFIX)->autoClean(); |
119
|
|
|
|
120
|
|
|
foreach ( $completed_processes as $process ) { |
121
|
|
|
|
122
|
|
|
$db->table(EXTENDER_DATABASE_TABLE_JOBS) |
123
|
|
|
->keys("lastrun") |
124
|
|
|
->values($process[3]) |
125
|
|
|
->where('id', '=', $process[6]) |
126
|
|
|
->update(); |
127
|
|
|
|
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
} catch (DatabaseException $de) { |
131
|
|
|
|
132
|
|
|
unset($db); |
133
|
|
|
|
134
|
|
|
throw $de; |
135
|
|
|
|
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
unset($db); |
139
|
|
|
|
140
|
|
|
Cache::purge(); |
141
|
|
|
|
142
|
|
|
Planner::release(); |
143
|
|
|
|
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Get a schedule by name |
148
|
|
|
* |
149
|
|
|
* @param string $name |
150
|
|
|
* |
151
|
|
|
* @return array|null |
152
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
153
|
|
|
* @throws \Exception |
154
|
|
|
*/ |
155
|
3 |
|
final public static function getSchedule($name) { |
156
|
|
|
|
157
|
3 |
|
if ( empty($name) ) throw new Exception("Invalid job name"); |
158
|
|
|
|
159
|
|
|
try { |
160
|
|
|
|
161
|
3 |
|
$db = new EnhancedDatabase( |
162
|
3 |
|
EXTENDER_DATABASE_MODEL, |
163
|
3 |
|
EXTENDER_DATABASE_HOST, |
164
|
3 |
|
EXTENDER_DATABASE_PORT, |
165
|
3 |
|
EXTENDER_DATABASE_NAME, |
166
|
3 |
|
EXTENDER_DATABASE_USER, |
167
|
|
|
EXTENDER_DATABASE_PASS |
168
|
3 |
|
); |
169
|
|
|
|
170
|
3 |
|
$result = $db->tablePrefix(EXTENDER_DATABASE_PREFIX) |
171
|
3 |
|
->table(EXTENDER_DATABASE_TABLE_JOBS) |
172
|
3 |
|
->keys(array("id", "task", "description", |
173
|
3 |
|
"min", "hour", "dayofmonth", "month", |
174
|
3 |
|
"dayofweek", "year", "params", "firstrun", "lastrun")) |
175
|
3 |
|
->where("name", "=", $name) |
176
|
3 |
|
->get(); |
177
|
|
|
|
178
|
3 |
|
} catch (DatabaseException $e) { |
179
|
|
|
|
180
|
|
|
throw $e; |
181
|
|
|
|
182
|
|
|
} |
183
|
|
|
|
184
|
3 |
|
if ( $result->getLength() == 0 ) return null; |
185
|
|
|
|
186
|
3 |
|
$data = $result->getData(); |
187
|
|
|
|
188
|
3 |
|
$expression = implode(" ", array($data[0]['min'], $data[0]['hour'], $data[0]['dayofmonth'], $data[0]['month'], $data[0]['dayofweek'], $data[0]['year'])); |
189
|
|
|
|
190
|
|
|
return array( |
191
|
3 |
|
"id" => $data[0]["id"], |
192
|
3 |
|
"name" => $name, |
193
|
3 |
|
"task" => $data[0]["task"], |
194
|
3 |
|
"description" => $data[0]["description"], |
195
|
3 |
|
"expression" => $expression, |
196
|
3 |
|
"params" => unserialize($data[0]["params"]), |
197
|
3 |
|
"firstrun" => $data[0]["firstrun"], |
198
|
3 |
|
"lastrun" => $data[0]["lastrun"], |
199
|
3 |
|
"nextrun" => self::shouldPlanJob($data[0]) |
200
|
3 |
|
); |
201
|
|
|
|
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Add a schedule |
206
|
|
|
* |
207
|
|
|
* @param string $expression |
208
|
|
|
* @param string $name |
209
|
|
|
* @param string $task |
210
|
|
|
* @param string $description |
211
|
|
|
* @param array $params |
212
|
|
|
* |
213
|
|
|
* @return array |
214
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
215
|
|
|
* @throws \Exception |
216
|
|
|
*/ |
217
|
3 |
|
final public static function addSchedule($expression, $name, $task, $description = null, $params = array()) { |
218
|
|
|
|
219
|
3 |
|
if ( empty($name) ) throw new Exception("Invalid job name"); |
220
|
|
|
|
221
|
3 |
|
if ( empty($task) ) throw new Exception("A job feels alone without a task"); |
222
|
|
|
|
223
|
|
|
try { |
224
|
|
|
|
225
|
3 |
|
list($next_calculated_run, $parsed_expression) = self::validateExpression($expression); |
226
|
|
|
|
227
|
3 |
|
$firstrun = (int) date("U", strtotime($next_calculated_run)); |
228
|
|
|
|
229
|
3 |
|
list($min, $hour, $dayofmonth, $month, $dayofweek, $year) = $parsed_expression; |
230
|
|
|
|
231
|
3 |
|
$parameters = serialize($params); |
232
|
|
|
|
233
|
3 |
|
$db = new EnhancedDatabase( |
234
|
3 |
|
EXTENDER_DATABASE_MODEL, |
235
|
3 |
|
EXTENDER_DATABASE_HOST, |
236
|
3 |
|
EXTENDER_DATABASE_PORT, |
237
|
3 |
|
EXTENDER_DATABASE_NAME, |
238
|
3 |
|
EXTENDER_DATABASE_USER, |
239
|
|
|
EXTENDER_DATABASE_PASS |
240
|
3 |
|
); |
241
|
|
|
|
242
|
3 |
|
$result = $db->tablePrefix(EXTENDER_DATABASE_PREFIX) |
243
|
3 |
|
->table(EXTENDER_DATABASE_TABLE_JOBS) |
244
|
3 |
|
->keys(array("name", "task", "description", |
245
|
3 |
|
"min", "hour", "dayofmonth", "month", |
246
|
3 |
|
"dayofweek", "year", "params", "firstrun")) |
247
|
3 |
|
->values(array($name, $task, $description, |
248
|
3 |
|
$min, $hour, $dayofmonth, $month, |
249
|
3 |
|
$dayofweek, $year, $parameters, $firstrun)) |
250
|
3 |
|
->store(); |
251
|
|
|
|
252
|
3 |
|
} catch (DatabaseException $de) { |
253
|
|
|
|
254
|
|
|
throw $de; |
255
|
|
|
|
256
|
|
|
} catch (Exception $e) { |
257
|
|
|
|
258
|
|
|
throw $e; |
259
|
|
|
|
260
|
|
|
} |
261
|
|
|
|
262
|
3 |
|
Cache::purge(); |
263
|
|
|
|
264
|
3 |
|
Planner::release(); |
265
|
|
|
|
266
|
3 |
|
return array($result->getInsertId(), $next_calculated_run); |
267
|
|
|
|
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Remove a schedule |
272
|
|
|
* |
273
|
|
|
* @param string $name |
274
|
|
|
* |
275
|
|
|
* @return bool |
276
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
277
|
|
|
* @throws \Exception |
278
|
|
|
*/ |
279
|
3 |
|
final public static function removeSchedule($name) { |
280
|
|
|
|
281
|
3 |
|
if ( empty($name) ) throw new Exception("Invalid or empty job name"); |
282
|
|
|
|
283
|
|
|
try { |
284
|
|
|
|
285
|
3 |
|
$db = new EnhancedDatabase( |
286
|
3 |
|
EXTENDER_DATABASE_MODEL, |
287
|
3 |
|
EXTENDER_DATABASE_HOST, |
288
|
3 |
|
EXTENDER_DATABASE_PORT, |
289
|
3 |
|
EXTENDER_DATABASE_NAME, |
290
|
3 |
|
EXTENDER_DATABASE_USER, |
291
|
|
|
EXTENDER_DATABASE_PASS |
292
|
3 |
|
); |
293
|
|
|
|
294
|
3 |
|
$result = $db->tablePrefix(EXTENDER_DATABASE_PREFIX) |
295
|
3 |
|
->table(EXTENDER_DATABASE_TABLE_JOBS) |
296
|
3 |
|
->where("name", "=", $name) |
297
|
3 |
|
->delete(); |
298
|
|
|
|
299
|
3 |
|
} catch (DatabaseException $de) { |
300
|
|
|
|
301
|
|
|
throw $de; |
302
|
|
|
|
303
|
|
|
} |
304
|
|
|
|
305
|
3 |
|
if ( $result->getAffectedRows() == 0 ) return false; |
306
|
|
|
|
307
|
3 |
|
Cache::purge(); |
308
|
|
|
|
309
|
3 |
|
Planner::release(); |
310
|
|
|
|
311
|
3 |
|
return true; |
312
|
|
|
|
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Update single schedule (last run) |
317
|
|
|
* |
318
|
|
|
* @param string $name |
319
|
|
|
* @param float $lastrun |
320
|
|
|
* |
321
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
322
|
|
|
* @throws \Exception |
323
|
|
|
*/ |
324
|
3 |
|
final public static function updateSchedule($name, $lastrun) { |
325
|
|
|
|
326
|
3 |
|
if ( empty($name) ) throw new Exception("Invalid job name"); |
327
|
|
|
|
328
|
3 |
|
if ( empty($lastrun) ) throw new Exception("Empty job run datetime"); |
329
|
|
|
|
330
|
|
|
try { |
331
|
|
|
|
332
|
3 |
|
$db = new EnhancedDatabase( |
333
|
3 |
|
EXTENDER_DATABASE_MODEL, |
334
|
3 |
|
EXTENDER_DATABASE_HOST, |
335
|
3 |
|
EXTENDER_DATABASE_PORT, |
336
|
3 |
|
EXTENDER_DATABASE_NAME, |
337
|
3 |
|
EXTENDER_DATABASE_USER, |
338
|
|
|
EXTENDER_DATABASE_PASS |
339
|
3 |
|
); |
340
|
|
|
|
341
|
3 |
|
$db->tablePrefix(EXTENDER_DATABASE_PREFIX)->table(EXTENDER_DATABASE_TABLE_JOBS)->keys("lastrun")->values($lastrun)->where('name', '=', $name)->update(); |
342
|
|
|
|
343
|
|
|
} |
344
|
3 |
|
catch (DatabaseException $de) { |
345
|
|
|
|
346
|
|
|
unset($db); |
347
|
|
|
|
348
|
|
|
throw $de; |
349
|
|
|
|
350
|
|
|
} |
351
|
|
|
|
352
|
3 |
|
unset($db); |
353
|
|
|
|
354
|
3 |
|
Cache::purge(); |
355
|
|
|
|
356
|
3 |
|
Planner::release(); |
357
|
|
|
|
358
|
3 |
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Enable a schedule |
362
|
|
|
* |
363
|
|
|
* @param string $name |
364
|
|
|
* |
365
|
|
|
* @return bool |
366
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
367
|
|
|
* @throws \Exception |
368
|
|
|
*/ |
369
|
3 |
View Code Duplication |
final public static function enableSchedule($name) { |
|
|
|
|
370
|
|
|
|
371
|
3 |
|
if ( empty($name) ) throw new Exception("Invalid or empty job name"); |
372
|
|
|
|
373
|
|
|
try { |
374
|
|
|
|
375
|
3 |
|
$db = new EnhancedDatabase( |
376
|
3 |
|
EXTENDER_DATABASE_MODEL, |
377
|
3 |
|
EXTENDER_DATABASE_HOST, |
378
|
3 |
|
EXTENDER_DATABASE_PORT, |
379
|
3 |
|
EXTENDER_DATABASE_NAME, |
380
|
3 |
|
EXTENDER_DATABASE_USER, |
381
|
|
|
EXTENDER_DATABASE_PASS |
382
|
3 |
|
); |
383
|
|
|
|
384
|
3 |
|
$result = $db->tablePrefix(EXTENDER_DATABASE_PREFIX) |
385
|
3 |
|
->table(EXTENDER_DATABASE_TABLE_JOBS) |
386
|
3 |
|
->keys("enabled") |
387
|
3 |
|
->values(array(true)) |
388
|
3 |
|
->where("name", "=", $name) |
389
|
3 |
|
->update(); |
390
|
|
|
|
391
|
3 |
|
} catch (DatabaseException $de) { |
392
|
|
|
|
393
|
|
|
throw $de; |
394
|
|
|
|
395
|
|
|
} |
396
|
|
|
|
397
|
3 |
|
Cache::purge(); |
398
|
|
|
|
399
|
3 |
|
Planner::release(); |
400
|
|
|
|
401
|
3 |
|
return $result->getAffectedRows() == 1 ? true : false; |
402
|
|
|
|
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* Disable a schedule |
407
|
|
|
* |
408
|
|
|
* @param string $name |
409
|
|
|
* |
410
|
|
|
* @return bool |
411
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
412
|
|
|
* @throws \Exception |
413
|
|
|
*/ |
414
|
3 |
View Code Duplication |
final public static function disableSchedule($name) { |
|
|
|
|
415
|
|
|
|
416
|
3 |
|
if ( empty($name) ) throw new Exception("Invalid or empty job name"); |
417
|
|
|
|
418
|
|
|
try { |
419
|
|
|
|
420
|
3 |
|
$db = new EnhancedDatabase( |
421
|
3 |
|
EXTENDER_DATABASE_MODEL, |
422
|
3 |
|
EXTENDER_DATABASE_HOST, |
423
|
3 |
|
EXTENDER_DATABASE_PORT, |
424
|
3 |
|
EXTENDER_DATABASE_NAME, |
425
|
3 |
|
EXTENDER_DATABASE_USER, |
426
|
|
|
EXTENDER_DATABASE_PASS |
427
|
3 |
|
); |
428
|
|
|
|
429
|
3 |
|
$result = $db->tablePrefix(EXTENDER_DATABASE_PREFIX) |
430
|
3 |
|
->table(EXTENDER_DATABASE_TABLE_JOBS) |
431
|
3 |
|
->keys("enabled") |
432
|
3 |
|
->values(array(false)) |
433
|
3 |
|
->where("name", "=", $name) |
434
|
3 |
|
->update(); |
435
|
|
|
|
436
|
3 |
|
} catch (DatabaseException $de) { |
437
|
|
|
|
438
|
|
|
throw $de; |
439
|
|
|
|
440
|
|
|
} |
441
|
|
|
|
442
|
3 |
|
Cache::purge(); |
443
|
|
|
|
444
|
3 |
|
Planner::release(); |
445
|
|
|
|
446
|
3 |
|
return $result->getAffectedRows() == 1 ? true : false; |
447
|
|
|
|
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Validate a cron expression and, if valid, return next run timestamp plus |
452
|
|
|
* an array of expression parts |
453
|
|
|
* |
454
|
|
|
* @param string $expression |
455
|
|
|
* |
456
|
|
|
* @return array Next run timestamp at first position, expression parts at second |
457
|
|
|
* @throws \Exception |
458
|
|
|
*/ |
459
|
6 |
|
final public static function validateExpression($expression) { |
460
|
|
|
|
461
|
|
|
try { |
462
|
|
|
|
463
|
6 |
|
$cron = CronExpression::factory($expression); |
464
|
|
|
|
465
|
6 |
|
$s = $cron->getNextRunDate()->format('c'); |
466
|
|
|
|
467
|
6 |
|
$e = $cron->getExpression(); |
468
|
|
|
|
469
|
6 |
|
$e_array = preg_split('/\s/', $e, -1, PREG_SPLIT_NO_EMPTY); |
470
|
|
|
|
471
|
6 |
|
$e_count = count($e_array); |
472
|
|
|
|
473
|
6 |
|
if ( $e_count < 5 || $e_count > 6 ) throw new Exception($e." is not a valid cron expression"); |
474
|
|
|
|
475
|
6 |
|
if ( $e_count == 5 ) $e_array[] = "*"; |
476
|
|
|
|
477
|
|
|
} |
478
|
6 |
|
catch (Exception $e) { |
479
|
|
|
|
480
|
|
|
throw $e; |
481
|
|
|
|
482
|
|
|
} |
483
|
|
|
|
484
|
6 |
|
return array($s, $e_array); |
485
|
|
|
|
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* Get planned jobs |
490
|
|
|
* |
491
|
|
|
* @return array |
492
|
|
|
* @throws \Comodojo\Exception\DatabaseException |
493
|
|
|
*/ |
494
|
3 |
|
private static function getJobs() { |
495
|
|
|
|
496
|
3 |
|
$jobs = Cache::get(); |
497
|
|
|
|
498
|
3 |
|
if ( $jobs !== false ) return $jobs; |
499
|
|
|
|
500
|
|
|
try { |
501
|
|
|
|
502
|
3 |
|
$db = new EnhancedDatabase( |
503
|
3 |
|
EXTENDER_DATABASE_MODEL, |
504
|
3 |
|
EXTENDER_DATABASE_HOST, |
505
|
3 |
|
EXTENDER_DATABASE_PORT, |
506
|
3 |
|
EXTENDER_DATABASE_NAME, |
507
|
3 |
|
EXTENDER_DATABASE_USER, |
508
|
|
|
EXTENDER_DATABASE_PASS |
509
|
3 |
|
); |
510
|
|
|
|
511
|
3 |
|
$result = $db->tablePrefix(EXTENDER_DATABASE_PREFIX) |
512
|
3 |
|
->table(EXTENDER_DATABASE_TABLE_JOBS) |
513
|
3 |
|
->keys(array("id", "name", "task", "description", |
514
|
3 |
|
"min", "hour", "dayofmonth", "month", "dayofweek", "year", |
515
|
3 |
|
"params", "lastrun", "firstrun")) |
516
|
3 |
|
->where("enabled", "=", true) |
517
|
3 |
|
->get(); |
518
|
|
|
|
519
|
|
|
} |
520
|
3 |
|
catch (DatabaseException $de) { |
521
|
|
|
|
522
|
|
|
unset($db); |
523
|
|
|
|
524
|
|
|
throw $de; |
525
|
|
|
|
526
|
|
|
} |
527
|
|
|
|
528
|
3 |
|
unset($db); |
529
|
|
|
|
530
|
3 |
|
$jobs = $result->getData(); |
531
|
|
|
|
532
|
3 |
|
Cache::set($jobs); |
533
|
|
|
|
534
|
3 |
|
return $jobs; |
535
|
|
|
|
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
/** |
539
|
|
|
* Determine if a job should be executed |
540
|
|
|
* |
541
|
|
|
* @param array $job |
542
|
|
|
* @param object $logger |
543
|
|
|
* @param float $timestamp |
544
|
|
|
* |
545
|
|
|
* @return bool |
546
|
|
|
* @throws \Exception |
547
|
|
|
*/ |
548
|
|
|
private static function shouldRunJob($job, $logger, $timestamp) { |
549
|
|
|
|
550
|
|
|
$expression = implode(" ", array($job['min'], $job['hour'], $job['dayofmonth'], $job['month'], $job['dayofweek'], $job['year'])); |
551
|
|
|
|
552
|
|
|
if ( empty($job['lastrun']) ) { |
553
|
|
|
|
554
|
|
|
$next_calculated_run = (int) $job['firstrun']; |
555
|
|
|
|
556
|
|
|
} else { |
557
|
|
|
|
558
|
|
|
$last_date = date_create(); |
559
|
|
|
|
560
|
|
|
date_timestamp_set($last_date, (int) $job['lastrun']); |
561
|
|
|
|
562
|
|
|
try { |
563
|
|
|
|
564
|
|
|
$cron = CronExpression::factory($expression); |
565
|
|
|
|
566
|
|
|
$next_calculated_run = $cron->getNextRunDate($last_date)->format('U'); |
567
|
|
|
|
568
|
|
|
} |
569
|
|
|
catch (Exception $e) { |
570
|
|
|
|
571
|
|
|
$logger->error("Job ".$job['name']." cannot be executed due to cron parsing error", array( |
572
|
|
|
"ERROR" => $e->getMessage(), |
573
|
|
|
"ERRID" => $e->getCode() |
574
|
|
|
)); |
575
|
|
|
|
576
|
|
|
return false; |
577
|
|
|
|
578
|
|
|
} |
579
|
|
|
|
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
$torun = $next_calculated_run <= $timestamp ? true : false; |
583
|
|
|
|
584
|
|
|
$logger->debug("Job ".$job['name'].($torun ? " will be" : " will not be")." executed", array( |
585
|
|
|
"EXPRESSION" => $expression, |
586
|
|
|
"FIRSTRUNDATE"=> date('c', $job['firstrun']), |
587
|
|
|
"LASTRUNDATE" => date('c', $job['lastrun']), |
588
|
|
|
"NEXTRUN" => date('c', $next_calculated_run) |
589
|
|
|
)); |
590
|
|
|
|
591
|
|
|
return $torun; |
592
|
|
|
|
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
/** |
596
|
|
|
* Determine next planned jobs |
597
|
|
|
* |
598
|
|
|
* @param array $job |
599
|
|
|
* |
600
|
|
|
* @return int |
601
|
|
|
*/ |
602
|
3 |
|
private static function shouldPlanJob($job) { |
603
|
|
|
|
604
|
3 |
|
$expression = implode(" ", array($job['min'], $job['hour'], $job['dayofmonth'], $job['month'], $job['dayofweek'], $job['year'])); |
605
|
|
|
|
606
|
3 |
|
if ( empty($job['lastrun']) ) { |
607
|
|
|
|
608
|
3 |
|
$next_calculated_run = (int) $job['firstrun']; |
609
|
|
|
|
610
|
3 |
|
} else { |
611
|
|
|
|
612
|
3 |
|
$last_date = date_create(); |
613
|
|
|
|
614
|
3 |
|
date_timestamp_set($last_date, (int) $job['lastrun']); |
615
|
|
|
|
616
|
|
|
try { |
617
|
|
|
|
618
|
3 |
|
$cron = CronExpression::factory($expression); |
619
|
|
|
|
620
|
3 |
|
$next_calculated_run = $cron->getNextRunDate($last_date)->format('U'); |
621
|
|
|
|
622
|
|
|
} |
623
|
3 |
|
catch (Exception $e) { |
624
|
|
|
|
625
|
|
|
return false; |
626
|
|
|
|
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
} |
630
|
|
|
|
631
|
3 |
|
return $next_calculated_run; |
632
|
|
|
|
633
|
|
|
} |
634
|
|
|
|
635
|
|
|
} |
636
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.