@@ -19,70 +19,70 @@ |
||
19 | 19 | * @since 33.0.0 removed deprecated `execute()` method |
20 | 20 | */ |
21 | 21 | abstract class TimedJob extends Job { |
22 | - protected int $interval = 0; |
|
23 | - protected int $timeSensitivity = IJob::TIME_SENSITIVE; |
|
22 | + protected int $interval = 0; |
|
23 | + protected int $timeSensitivity = IJob::TIME_SENSITIVE; |
|
24 | 24 | |
25 | - /** |
|
26 | - * Set the interval for the job |
|
27 | - * |
|
28 | - * @param int $seconds the time to pass between two runs of the same job in seconds |
|
29 | - * |
|
30 | - * @since 15.0.0 |
|
31 | - */ |
|
32 | - public function setInterval(int $seconds): void { |
|
33 | - $this->interval = $seconds; |
|
34 | - } |
|
25 | + /** |
|
26 | + * Set the interval for the job |
|
27 | + * |
|
28 | + * @param int $seconds the time to pass between two runs of the same job in seconds |
|
29 | + * |
|
30 | + * @since 15.0.0 |
|
31 | + */ |
|
32 | + public function setInterval(int $seconds): void { |
|
33 | + $this->interval = $seconds; |
|
34 | + } |
|
35 | 35 | |
36 | - /** |
|
37 | - * Get the interval [seconds] for the job |
|
38 | - * |
|
39 | - * @since 32.0.0 |
|
40 | - */ |
|
41 | - public function getInterval(): int { |
|
42 | - return $this->interval; |
|
43 | - } |
|
36 | + /** |
|
37 | + * Get the interval [seconds] for the job |
|
38 | + * |
|
39 | + * @since 32.0.0 |
|
40 | + */ |
|
41 | + public function getInterval(): int { |
|
42 | + return $this->interval; |
|
43 | + } |
|
44 | 44 | |
45 | - /** |
|
46 | - * Whether the background job is time sensitive and needs to run soon after |
|
47 | - * the scheduled interval, of if it is okay to be delayed until a later time. |
|
48 | - * |
|
49 | - * @return bool |
|
50 | - * @since 24.0.0 |
|
51 | - */ |
|
52 | - public function isTimeSensitive(): bool { |
|
53 | - return $this->timeSensitivity === IJob::TIME_SENSITIVE; |
|
54 | - } |
|
45 | + /** |
|
46 | + * Whether the background job is time sensitive and needs to run soon after |
|
47 | + * the scheduled interval, of if it is okay to be delayed until a later time. |
|
48 | + * |
|
49 | + * @return bool |
|
50 | + * @since 24.0.0 |
|
51 | + */ |
|
52 | + public function isTimeSensitive(): bool { |
|
53 | + return $this->timeSensitivity === IJob::TIME_SENSITIVE; |
|
54 | + } |
|
55 | 55 | |
56 | - /** |
|
57 | - * If your background job is not time sensitive (sending instant email |
|
58 | - * notifications, etc.) it would be nice to set it to IJob::TIME_INSENSITIVE |
|
59 | - * This way the execution can be delayed during high usage times. |
|
60 | - * |
|
61 | - * @param int $sensitivity |
|
62 | - * @psalm-param IJob::TIME_* $sensitivity |
|
63 | - * @return void |
|
64 | - * @since 24.0.0 |
|
65 | - */ |
|
66 | - public function setTimeSensitivity(int $sensitivity): void { |
|
67 | - if ($sensitivity !== self::TIME_SENSITIVE |
|
68 | - && $sensitivity !== self::TIME_INSENSITIVE) { |
|
69 | - throw new \InvalidArgumentException('Invalid sensitivity'); |
|
70 | - } |
|
56 | + /** |
|
57 | + * If your background job is not time sensitive (sending instant email |
|
58 | + * notifications, etc.) it would be nice to set it to IJob::TIME_INSENSITIVE |
|
59 | + * This way the execution can be delayed during high usage times. |
|
60 | + * |
|
61 | + * @param int $sensitivity |
|
62 | + * @psalm-param IJob::TIME_* $sensitivity |
|
63 | + * @return void |
|
64 | + * @since 24.0.0 |
|
65 | + */ |
|
66 | + public function setTimeSensitivity(int $sensitivity): void { |
|
67 | + if ($sensitivity !== self::TIME_SENSITIVE |
|
68 | + && $sensitivity !== self::TIME_INSENSITIVE) { |
|
69 | + throw new \InvalidArgumentException('Invalid sensitivity'); |
|
70 | + } |
|
71 | 71 | |
72 | - $this->timeSensitivity = $sensitivity; |
|
73 | - } |
|
72 | + $this->timeSensitivity = $sensitivity; |
|
73 | + } |
|
74 | 74 | |
75 | - /** |
|
76 | - * Run the job if the last run is more than the interval ago |
|
77 | - * |
|
78 | - * @since 25.0.0 |
|
79 | - */ |
|
80 | - final public function start(IJobList $jobList): void { |
|
81 | - if (($this->time->getTime() - $this->lastRun) > $this->interval) { |
|
82 | - if ($this->interval >= 12 * 60 * 60 && $this->isTimeSensitive()) { |
|
83 | - Server::get(LoggerInterface::class)->debug('TimedJob ' . get_class($this) . ' has a configured interval of ' . $this->interval . ' seconds, but is also marked as time sensitive. Please consider marking it as time insensitive to allow more sensitive jobs to run when needed.'); |
|
84 | - } |
|
85 | - parent::start($jobList); |
|
86 | - } |
|
87 | - } |
|
75 | + /** |
|
76 | + * Run the job if the last run is more than the interval ago |
|
77 | + * |
|
78 | + * @since 25.0.0 |
|
79 | + */ |
|
80 | + final public function start(IJobList $jobList): void { |
|
81 | + if (($this->time->getTime() - $this->lastRun) > $this->interval) { |
|
82 | + if ($this->interval >= 12 * 60 * 60 && $this->isTimeSensitive()) { |
|
83 | + Server::get(LoggerInterface::class)->debug('TimedJob ' . get_class($this) . ' has a configured interval of ' . $this->interval . ' seconds, but is also marked as time sensitive. Please consider marking it as time insensitive to allow more sensitive jobs to run when needed.'); |
|
84 | + } |
|
85 | + parent::start($jobList); |
|
86 | + } |
|
87 | + } |
|
88 | 88 | } |
@@ -21,114 +21,114 @@ |
||
21 | 21 | * @since 33.0.0 removed deprecated `execute()` method |
22 | 22 | */ |
23 | 23 | abstract class Job implements IJob, IParallelAwareJob { |
24 | - protected int $id = 0; |
|
25 | - protected int $lastRun = 0; |
|
26 | - protected mixed $argument = null; |
|
27 | - protected bool $allowParallelRuns = true; |
|
28 | - |
|
29 | - /** |
|
30 | - * @since 15.0.0 |
|
31 | - */ |
|
32 | - public function __construct( |
|
33 | - protected ITimeFactory $time, |
|
34 | - ) { |
|
35 | - } |
|
36 | - |
|
37 | - /** |
|
38 | - * @inheritdoc |
|
39 | - * @since 25.0.0 |
|
40 | - */ |
|
41 | - public function start(IJobList $jobList): void { |
|
42 | - $jobList->setLastRun($this); |
|
43 | - $logger = \OCP\Server::get(LoggerInterface::class); |
|
44 | - |
|
45 | - try { |
|
46 | - $jobDetails = get_class($this) . ' (id: ' . $this->getId() . ', arguments: ' . json_encode($this->getArgument()) . ')'; |
|
47 | - $jobStartTime = $this->time->getTime(); |
|
48 | - $logger->debug('Starting job ' . $jobDetails, ['app' => 'cron']); |
|
49 | - $this->run($this->argument); |
|
50 | - $timeTaken = $this->time->getTime() - $jobStartTime; |
|
51 | - |
|
52 | - $logger->debug('Finished job ' . $jobDetails . ' in ' . $timeTaken . ' seconds', ['app' => 'cron']); |
|
53 | - $jobList->setExecutionTime($this, $timeTaken); |
|
54 | - } catch (\Throwable $e) { |
|
55 | - if ($logger) { |
|
56 | - $logger->error('Error while running background job ' . $jobDetails, [ |
|
57 | - 'app' => 'core', |
|
58 | - 'exception' => $e, |
|
59 | - ]); |
|
60 | - } |
|
61 | - } |
|
62 | - } |
|
63 | - |
|
64 | - /** |
|
65 | - * @since 15.0.0 |
|
66 | - */ |
|
67 | - final public function setId(int $id) { |
|
68 | - $this->id = $id; |
|
69 | - } |
|
70 | - |
|
71 | - /** |
|
72 | - * @since 15.0.0 |
|
73 | - */ |
|
74 | - final public function setLastRun(int $lastRun) { |
|
75 | - $this->lastRun = $lastRun; |
|
76 | - } |
|
77 | - |
|
78 | - /** |
|
79 | - * @since 15.0.0 |
|
80 | - */ |
|
81 | - public function setArgument($argument) { |
|
82 | - $this->argument = $argument; |
|
83 | - } |
|
84 | - |
|
85 | - /** |
|
86 | - * @since 15.0.0 |
|
87 | - */ |
|
88 | - final public function getId(): int { |
|
89 | - return $this->id; |
|
90 | - } |
|
91 | - |
|
92 | - /** |
|
93 | - * @since 15.0.0 |
|
94 | - */ |
|
95 | - final public function getLastRun(): int { |
|
96 | - return $this->lastRun; |
|
97 | - } |
|
98 | - |
|
99 | - /** |
|
100 | - * @since 15.0.0 |
|
101 | - */ |
|
102 | - public function getArgument() { |
|
103 | - return $this->argument; |
|
104 | - } |
|
105 | - |
|
106 | - /** |
|
107 | - * Set this to false to prevent two Jobs from this class from running in parallel |
|
108 | - * |
|
109 | - * @param bool $allow |
|
110 | - * @return void |
|
111 | - * @since 27.0.0 |
|
112 | - */ |
|
113 | - public function setAllowParallelRuns(bool $allow): void { |
|
114 | - $this->allowParallelRuns = $allow; |
|
115 | - } |
|
116 | - |
|
117 | - /** |
|
118 | - * @return bool |
|
119 | - * @since 27.0.0 |
|
120 | - */ |
|
121 | - public function getAllowParallelRuns(): bool { |
|
122 | - return $this->allowParallelRuns; |
|
123 | - } |
|
124 | - |
|
125 | - /** |
|
126 | - * The actual function that is called to run the job |
|
127 | - * |
|
128 | - * @param $argument |
|
129 | - * @return void |
|
130 | - * |
|
131 | - * @since 15.0.0 |
|
132 | - */ |
|
133 | - abstract protected function run($argument); |
|
24 | + protected int $id = 0; |
|
25 | + protected int $lastRun = 0; |
|
26 | + protected mixed $argument = null; |
|
27 | + protected bool $allowParallelRuns = true; |
|
28 | + |
|
29 | + /** |
|
30 | + * @since 15.0.0 |
|
31 | + */ |
|
32 | + public function __construct( |
|
33 | + protected ITimeFactory $time, |
|
34 | + ) { |
|
35 | + } |
|
36 | + |
|
37 | + /** |
|
38 | + * @inheritdoc |
|
39 | + * @since 25.0.0 |
|
40 | + */ |
|
41 | + public function start(IJobList $jobList): void { |
|
42 | + $jobList->setLastRun($this); |
|
43 | + $logger = \OCP\Server::get(LoggerInterface::class); |
|
44 | + |
|
45 | + try { |
|
46 | + $jobDetails = get_class($this) . ' (id: ' . $this->getId() . ', arguments: ' . json_encode($this->getArgument()) . ')'; |
|
47 | + $jobStartTime = $this->time->getTime(); |
|
48 | + $logger->debug('Starting job ' . $jobDetails, ['app' => 'cron']); |
|
49 | + $this->run($this->argument); |
|
50 | + $timeTaken = $this->time->getTime() - $jobStartTime; |
|
51 | + |
|
52 | + $logger->debug('Finished job ' . $jobDetails . ' in ' . $timeTaken . ' seconds', ['app' => 'cron']); |
|
53 | + $jobList->setExecutionTime($this, $timeTaken); |
|
54 | + } catch (\Throwable $e) { |
|
55 | + if ($logger) { |
|
56 | + $logger->error('Error while running background job ' . $jobDetails, [ |
|
57 | + 'app' => 'core', |
|
58 | + 'exception' => $e, |
|
59 | + ]); |
|
60 | + } |
|
61 | + } |
|
62 | + } |
|
63 | + |
|
64 | + /** |
|
65 | + * @since 15.0.0 |
|
66 | + */ |
|
67 | + final public function setId(int $id) { |
|
68 | + $this->id = $id; |
|
69 | + } |
|
70 | + |
|
71 | + /** |
|
72 | + * @since 15.0.0 |
|
73 | + */ |
|
74 | + final public function setLastRun(int $lastRun) { |
|
75 | + $this->lastRun = $lastRun; |
|
76 | + } |
|
77 | + |
|
78 | + /** |
|
79 | + * @since 15.0.0 |
|
80 | + */ |
|
81 | + public function setArgument($argument) { |
|
82 | + $this->argument = $argument; |
|
83 | + } |
|
84 | + |
|
85 | + /** |
|
86 | + * @since 15.0.0 |
|
87 | + */ |
|
88 | + final public function getId(): int { |
|
89 | + return $this->id; |
|
90 | + } |
|
91 | + |
|
92 | + /** |
|
93 | + * @since 15.0.0 |
|
94 | + */ |
|
95 | + final public function getLastRun(): int { |
|
96 | + return $this->lastRun; |
|
97 | + } |
|
98 | + |
|
99 | + /** |
|
100 | + * @since 15.0.0 |
|
101 | + */ |
|
102 | + public function getArgument() { |
|
103 | + return $this->argument; |
|
104 | + } |
|
105 | + |
|
106 | + /** |
|
107 | + * Set this to false to prevent two Jobs from this class from running in parallel |
|
108 | + * |
|
109 | + * @param bool $allow |
|
110 | + * @return void |
|
111 | + * @since 27.0.0 |
|
112 | + */ |
|
113 | + public function setAllowParallelRuns(bool $allow): void { |
|
114 | + $this->allowParallelRuns = $allow; |
|
115 | + } |
|
116 | + |
|
117 | + /** |
|
118 | + * @return bool |
|
119 | + * @since 27.0.0 |
|
120 | + */ |
|
121 | + public function getAllowParallelRuns(): bool { |
|
122 | + return $this->allowParallelRuns; |
|
123 | + } |
|
124 | + |
|
125 | + /** |
|
126 | + * The actual function that is called to run the job |
|
127 | + * |
|
128 | + * @param $argument |
|
129 | + * @return void |
|
130 | + * |
|
131 | + * @since 15.0.0 |
|
132 | + */ |
|
133 | + abstract protected function run($argument); |
|
134 | 134 | } |
@@ -16,17 +16,17 @@ |
||
16 | 16 | */ |
17 | 17 | abstract class QueuedJob extends Job { |
18 | 18 | |
19 | - /** |
|
20 | - * Run the job, then remove it from the joblist |
|
21 | - * |
|
22 | - * @since 25.0.0 |
|
23 | - */ |
|
24 | - final public function start(IJobList $jobList): void { |
|
25 | - if ($this->id) { |
|
26 | - $jobList->removeById($this->id); |
|
27 | - } else { |
|
28 | - $jobList->remove($this, $this->argument); |
|
29 | - } |
|
30 | - parent::start($jobList); |
|
31 | - } |
|
19 | + /** |
|
20 | + * Run the job, then remove it from the joblist |
|
21 | + * |
|
22 | + * @since 25.0.0 |
|
23 | + */ |
|
24 | + final public function start(IJobList $jobList): void { |
|
25 | + if ($this->id) { |
|
26 | + $jobList->removeById($this->id); |
|
27 | + } else { |
|
28 | + $jobList->remove($this, $this->argument); |
|
29 | + } |
|
30 | + parent::start($jobList); |
|
31 | + } |
|
32 | 32 | } |
@@ -18,68 +18,68 @@ |
||
18 | 18 | * @since 33.0.0 removed deprecated `execute()` method |
19 | 19 | */ |
20 | 20 | interface IJob { |
21 | - /** |
|
22 | - * @since 24.0.0 |
|
23 | - */ |
|
24 | - public const TIME_INSENSITIVE = 0; |
|
25 | - /** |
|
26 | - * @since 24.0.0 |
|
27 | - */ |
|
28 | - public const TIME_SENSITIVE = 1; |
|
21 | + /** |
|
22 | + * @since 24.0.0 |
|
23 | + */ |
|
24 | + public const TIME_INSENSITIVE = 0; |
|
25 | + /** |
|
26 | + * @since 24.0.0 |
|
27 | + */ |
|
28 | + public const TIME_SENSITIVE = 1; |
|
29 | 29 | |
30 | - /** |
|
31 | - * Start the background job with the registered argument |
|
32 | - * |
|
33 | - * This methods will take care of running the background job, of initializing |
|
34 | - * the state and cleaning up the job list after running the job. |
|
35 | - * |
|
36 | - * For common background job scenario, you will want to use TimedJob or QueuedJob |
|
37 | - * instead of overwriting this method. |
|
38 | - * |
|
39 | - * @param IJobList $jobList The job list that manages the state of this job |
|
40 | - * @since 25.0.0 |
|
41 | - */ |
|
42 | - public function start(IJobList $jobList): void; |
|
30 | + /** |
|
31 | + * Start the background job with the registered argument |
|
32 | + * |
|
33 | + * This methods will take care of running the background job, of initializing |
|
34 | + * the state and cleaning up the job list after running the job. |
|
35 | + * |
|
36 | + * For common background job scenario, you will want to use TimedJob or QueuedJob |
|
37 | + * instead of overwriting this method. |
|
38 | + * |
|
39 | + * @param IJobList $jobList The job list that manages the state of this job |
|
40 | + * @since 25.0.0 |
|
41 | + */ |
|
42 | + public function start(IJobList $jobList): void; |
|
43 | 43 | |
44 | - /** |
|
45 | - * @since 7.0.0 |
|
46 | - */ |
|
47 | - public function setId(int $id); |
|
44 | + /** |
|
45 | + * @since 7.0.0 |
|
46 | + */ |
|
47 | + public function setId(int $id); |
|
48 | 48 | |
49 | - /** |
|
50 | - * @since 7.0.0 |
|
51 | - */ |
|
52 | - public function setLastRun(int $lastRun); |
|
49 | + /** |
|
50 | + * @since 7.0.0 |
|
51 | + */ |
|
52 | + public function setLastRun(int $lastRun); |
|
53 | 53 | |
54 | - /** |
|
55 | - * @param mixed $argument |
|
56 | - * @since 7.0.0 |
|
57 | - */ |
|
58 | - public function setArgument($argument); |
|
54 | + /** |
|
55 | + * @param mixed $argument |
|
56 | + * @since 7.0.0 |
|
57 | + */ |
|
58 | + public function setArgument($argument); |
|
59 | 59 | |
60 | - /** |
|
61 | - * Get the id of the background job |
|
62 | - * This id is determined by the job list when a job is added to the list |
|
63 | - * |
|
64 | - * @return int |
|
65 | - * @since 7.0.0 |
|
66 | - */ |
|
67 | - public function getId(); |
|
60 | + /** |
|
61 | + * Get the id of the background job |
|
62 | + * This id is determined by the job list when a job is added to the list |
|
63 | + * |
|
64 | + * @return int |
|
65 | + * @since 7.0.0 |
|
66 | + */ |
|
67 | + public function getId(); |
|
68 | 68 | |
69 | - /** |
|
70 | - * Get the last time this job was run as unix timestamp |
|
71 | - * |
|
72 | - * @return int |
|
73 | - * @since 7.0.0 |
|
74 | - */ |
|
75 | - public function getLastRun(); |
|
69 | + /** |
|
70 | + * Get the last time this job was run as unix timestamp |
|
71 | + * |
|
72 | + * @return int |
|
73 | + * @since 7.0.0 |
|
74 | + */ |
|
75 | + public function getLastRun(); |
|
76 | 76 | |
77 | - /** |
|
78 | - * Get the argument associated with the background job |
|
79 | - * This is the argument that will be passed to the background job |
|
80 | - * |
|
81 | - * @return mixed |
|
82 | - * @since 7.0.0 |
|
83 | - */ |
|
84 | - public function getArgument(); |
|
77 | + /** |
|
78 | + * Get the argument associated with the background job |
|
79 | + * This is the argument that will be passed to the background job |
|
80 | + * |
|
81 | + * @return mixed |
|
82 | + * @since 7.0.0 |
|
83 | + */ |
|
84 | + public function getArgument(); |
|
85 | 85 | } |
@@ -26,10 +26,10 @@ discard block |
||
26 | 26 | use Psr\Log\LoggerInterface; |
27 | 27 | |
28 | 28 | try { |
29 | - require_once __DIR__ . '/lib/base.php'; |
|
29 | + require_once __DIR__ . '/lib/base.php'; |
|
30 | 30 | |
31 | - if (isset($argv[1]) && ($argv[1] === '-h' || $argv[1] === '--help')) { |
|
32 | - echo 'Description: |
|
31 | + if (isset($argv[1]) && ($argv[1] === '-h' || $argv[1] === '--help')) { |
|
32 | + echo 'Description: |
|
33 | 33 | Run the background job routine |
34 | 34 | |
35 | 35 | Usage: |
@@ -42,222 +42,222 @@ discard block |
||
42 | 42 | Options: |
43 | 43 | -h, --help Display this help message |
44 | 44 | -v, --verbose Output more information' . PHP_EOL; |
45 | - exit(0); |
|
46 | - } |
|
47 | - |
|
48 | - if (Util::needUpgrade()) { |
|
49 | - Server::get(LoggerInterface::class)->debug('Update required, skipping cron', ['app' => 'cron']); |
|
50 | - exit; |
|
51 | - } |
|
52 | - |
|
53 | - $config = Server::get(IConfig::class); |
|
54 | - |
|
55 | - if ($config->getSystemValueBool('maintenance', false)) { |
|
56 | - Server::get(LoggerInterface::class)->debug('We are in maintenance mode, skipping cron', ['app' => 'cron']); |
|
57 | - exit; |
|
58 | - } |
|
59 | - |
|
60 | - // Don't do anything if Nextcloud has not been installed |
|
61 | - if (!$config->getSystemValueBool('installed', false)) { |
|
62 | - exit(0); |
|
63 | - } |
|
64 | - |
|
65 | - // load all apps to get all api routes properly setup |
|
66 | - Server::get(IAppManager::class)->loadApps(); |
|
67 | - Server::get(ISession::class)->close(); |
|
68 | - |
|
69 | - $verbose = isset($argv[1]) && ($argv[1] === '-v' || $argv[1] === '--verbose'); |
|
70 | - |
|
71 | - // initialize a dummy memory session |
|
72 | - $session = new Memory(); |
|
73 | - $cryptoWrapper = Server::get(CryptoWrapper::class); |
|
74 | - $session = $cryptoWrapper->wrapSession($session); |
|
75 | - \OC::$server->setSession($session); |
|
76 | - |
|
77 | - $logger = Server::get(LoggerInterface::class); |
|
78 | - $appConfig = Server::get(IAppConfig::class); |
|
79 | - $tempManager = Server::get(ITempManager::class); |
|
80 | - |
|
81 | - $tempManager->cleanOld(); |
|
82 | - |
|
83 | - // Exit if background jobs are disabled! |
|
84 | - $appMode = $appConfig->getValueString('core', 'backgroundjobs_mode', 'ajax'); |
|
85 | - if ($appMode === 'none') { |
|
86 | - if (OC::$CLI) { |
|
87 | - echo 'Background Jobs are disabled!' . PHP_EOL; |
|
88 | - } else { |
|
89 | - OC_JSON::error(['data' => ['message' => 'Background jobs disabled!']]); |
|
90 | - } |
|
91 | - exit(1); |
|
92 | - } |
|
93 | - |
|
94 | - if (OC::$CLI) { |
|
95 | - // set to run indefinitely if needed |
|
96 | - if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { |
|
97 | - @set_time_limit(0); |
|
98 | - } |
|
99 | - |
|
100 | - // the cron job must be executed with the right user |
|
101 | - if (!function_exists('posix_getuid')) { |
|
102 | - echo 'The posix extensions are required - see https://www.php.net/manual/en/book.posix.php' . PHP_EOL; |
|
103 | - exit(1); |
|
104 | - } |
|
105 | - |
|
106 | - $user = posix_getuid(); |
|
107 | - $configUser = fileowner(OC::$configDir . 'config.php'); |
|
108 | - if ($user !== $configUser) { |
|
109 | - echo 'Console has to be executed with the user that owns the file config/config.php' . PHP_EOL; |
|
110 | - echo 'Current user id: ' . $user . PHP_EOL; |
|
111 | - echo 'Owner id of config.php: ' . $configUser . PHP_EOL; |
|
112 | - exit(1); |
|
113 | - } |
|
114 | - |
|
115 | - |
|
116 | - // We call Nextcloud from the CLI (aka cron) |
|
117 | - if ($appMode !== 'cron') { |
|
118 | - $appConfig->setValueString('core', 'backgroundjobs_mode', 'cron'); |
|
119 | - } |
|
120 | - |
|
121 | - // a specific job class list can optionally be given as argument |
|
122 | - $jobClasses = array_slice($argv, $verbose ? 2 : 1); |
|
123 | - $jobClasses = empty($jobClasses) ? null : $jobClasses; |
|
124 | - |
|
125 | - // Low-load hours |
|
126 | - $onlyTimeSensitive = false; |
|
127 | - $startHour = $config->getSystemValueInt('maintenance_window_start', 100); |
|
128 | - if ($jobClasses === null && $startHour <= 23) { |
|
129 | - $date = new \DateTime('now', new \DateTimeZone('UTC')); |
|
130 | - $currentHour = (int)$date->format('G'); |
|
131 | - $endHour = $startHour + 4; |
|
132 | - |
|
133 | - if ($startHour <= 20) { |
|
134 | - // Start time: 01:00 |
|
135 | - // End time: 05:00 |
|
136 | - // Only run sensitive tasks when it's before the start or after the end |
|
137 | - $onlyTimeSensitive = $currentHour < $startHour || $currentHour > $endHour; |
|
138 | - } else { |
|
139 | - // Start time: 23:00 |
|
140 | - // End time: 03:00 |
|
141 | - $endHour -= 24; // Correct the end time from 27:00 to 03:00 |
|
142 | - // Only run sensitive tasks when it's after the end and before the start |
|
143 | - $onlyTimeSensitive = $currentHour > $endHour && $currentHour < $startHour; |
|
144 | - } |
|
145 | - } |
|
146 | - |
|
147 | - // Work |
|
148 | - $jobList = Server::get(IJobList::class); |
|
149 | - |
|
150 | - // We only ask for jobs for 14 minutes, because after 5 minutes the next |
|
151 | - // system cron task should spawn and we want to have at most three |
|
152 | - // cron jobs running in parallel. |
|
153 | - $endTime = time() + 14 * 60; |
|
154 | - |
|
155 | - $executedJobs = []; |
|
156 | - |
|
157 | - while ($job = $jobList->getNext($onlyTimeSensitive, $jobClasses)) { |
|
158 | - if (isset($executedJobs[$job->getId()])) { |
|
159 | - $jobList->unlockJob($job); |
|
160 | - break; |
|
161 | - } |
|
162 | - |
|
163 | - $jobDetails = get_class($job) . ' (id: ' . $job->getId() . ', arguments: ' . json_encode($job->getArgument()) . ')'; |
|
164 | - $logger->debug('CLI cron call has selected job ' . $jobDetails, ['app' => 'cron']); |
|
165 | - |
|
166 | - $timeBefore = time(); |
|
167 | - $memoryBefore = memory_get_usage(); |
|
168 | - $memoryPeakBefore = memory_get_peak_usage(); |
|
169 | - |
|
170 | - if ($verbose) { |
|
171 | - echo 'Starting job ' . $jobDetails . PHP_EOL; |
|
172 | - } |
|
173 | - |
|
174 | - $job->start($jobList); |
|
175 | - |
|
176 | - $timeAfter = time(); |
|
177 | - $memoryAfter = memory_get_usage(); |
|
178 | - $memoryPeakAfter = memory_get_peak_usage(); |
|
179 | - |
|
180 | - $cronInterval = 5 * 60; |
|
181 | - $timeSpent = $timeAfter - $timeBefore; |
|
182 | - if ($timeSpent > $cronInterval) { |
|
183 | - $logLevel = match (true) { |
|
184 | - $timeSpent > $cronInterval * 128 => ILogger::FATAL, |
|
185 | - $timeSpent > $cronInterval * 64 => ILogger::ERROR, |
|
186 | - $timeSpent > $cronInterval * 16 => ILogger::WARN, |
|
187 | - $timeSpent > $cronInterval * 8 => ILogger::INFO, |
|
188 | - default => ILogger::DEBUG, |
|
189 | - }; |
|
190 | - $logger->log( |
|
191 | - $logLevel, |
|
192 | - 'Background job ' . $jobDetails . ' ran for ' . $timeSpent . ' seconds', |
|
193 | - ['app' => 'cron'] |
|
194 | - ); |
|
195 | - } |
|
196 | - |
|
197 | - if ($memoryAfter - $memoryBefore > 50_000_000) { |
|
198 | - $message = 'Used memory grew by more than 50 MB when executing job ' . $jobDetails . ': ' . Util::humanFileSize($memoryAfter) . ' (before: ' . Util::humanFileSize($memoryBefore) . ')'; |
|
199 | - $logger->warning($message, ['app' => 'cron']); |
|
200 | - if ($verbose) { |
|
201 | - echo $message . PHP_EOL; |
|
202 | - } |
|
203 | - } |
|
204 | - if ($memoryPeakAfter > 300_000_000 && $memoryPeakBefore <= 300_000_000) { |
|
205 | - $message = 'Cron job used more than 300 MB of ram after executing job ' . $jobDetails . ': ' . Util::humanFileSize($memoryPeakAfter) . ' (before: ' . Util::humanFileSize($memoryPeakBefore) . ')'; |
|
206 | - $logger->warning($message, ['app' => 'cron']); |
|
207 | - if ($verbose) { |
|
208 | - echo $message . PHP_EOL; |
|
209 | - } |
|
210 | - } |
|
211 | - |
|
212 | - // clean up after unclean jobs |
|
213 | - Server::get(SetupManager::class)->tearDown(); |
|
214 | - $tempManager->clean(); |
|
215 | - |
|
216 | - if ($verbose) { |
|
217 | - echo 'Job ' . $jobDetails . ' done in ' . ($timeAfter - $timeBefore) . ' seconds' . PHP_EOL; |
|
218 | - } |
|
219 | - |
|
220 | - $jobList->setLastJob($job); |
|
221 | - $executedJobs[$job->getId()] = true; |
|
222 | - unset($job); |
|
223 | - |
|
224 | - if ($timeAfter > $endTime) { |
|
225 | - break; |
|
226 | - } |
|
227 | - } |
|
228 | - } else { |
|
229 | - // We call cron.php from some website |
|
230 | - if ($appMode === 'cron') { |
|
231 | - // Cron is cron :-P |
|
232 | - OC_JSON::error(['data' => ['message' => 'Backgroundjobs are using system cron!']]); |
|
233 | - } else { |
|
234 | - // Work and success :-) |
|
235 | - $jobList = Server::get(IJobList::class); |
|
236 | - $job = $jobList->getNext(); |
|
237 | - if ($job != null) { |
|
238 | - $logger->debug('WebCron call has selected job with ID ' . strval($job->getId()), ['app' => 'cron']); |
|
239 | - $job->start($jobList); |
|
240 | - $jobList->setLastJob($job); |
|
241 | - } |
|
242 | - OC_JSON::success(); |
|
243 | - } |
|
244 | - } |
|
245 | - |
|
246 | - // Log the successful cron execution |
|
247 | - $appConfig->setValueInt('core', 'lastcron', time()); |
|
248 | - exit(); |
|
45 | + exit(0); |
|
46 | + } |
|
47 | + |
|
48 | + if (Util::needUpgrade()) { |
|
49 | + Server::get(LoggerInterface::class)->debug('Update required, skipping cron', ['app' => 'cron']); |
|
50 | + exit; |
|
51 | + } |
|
52 | + |
|
53 | + $config = Server::get(IConfig::class); |
|
54 | + |
|
55 | + if ($config->getSystemValueBool('maintenance', false)) { |
|
56 | + Server::get(LoggerInterface::class)->debug('We are in maintenance mode, skipping cron', ['app' => 'cron']); |
|
57 | + exit; |
|
58 | + } |
|
59 | + |
|
60 | + // Don't do anything if Nextcloud has not been installed |
|
61 | + if (!$config->getSystemValueBool('installed', false)) { |
|
62 | + exit(0); |
|
63 | + } |
|
64 | + |
|
65 | + // load all apps to get all api routes properly setup |
|
66 | + Server::get(IAppManager::class)->loadApps(); |
|
67 | + Server::get(ISession::class)->close(); |
|
68 | + |
|
69 | + $verbose = isset($argv[1]) && ($argv[1] === '-v' || $argv[1] === '--verbose'); |
|
70 | + |
|
71 | + // initialize a dummy memory session |
|
72 | + $session = new Memory(); |
|
73 | + $cryptoWrapper = Server::get(CryptoWrapper::class); |
|
74 | + $session = $cryptoWrapper->wrapSession($session); |
|
75 | + \OC::$server->setSession($session); |
|
76 | + |
|
77 | + $logger = Server::get(LoggerInterface::class); |
|
78 | + $appConfig = Server::get(IAppConfig::class); |
|
79 | + $tempManager = Server::get(ITempManager::class); |
|
80 | + |
|
81 | + $tempManager->cleanOld(); |
|
82 | + |
|
83 | + // Exit if background jobs are disabled! |
|
84 | + $appMode = $appConfig->getValueString('core', 'backgroundjobs_mode', 'ajax'); |
|
85 | + if ($appMode === 'none') { |
|
86 | + if (OC::$CLI) { |
|
87 | + echo 'Background Jobs are disabled!' . PHP_EOL; |
|
88 | + } else { |
|
89 | + OC_JSON::error(['data' => ['message' => 'Background jobs disabled!']]); |
|
90 | + } |
|
91 | + exit(1); |
|
92 | + } |
|
93 | + |
|
94 | + if (OC::$CLI) { |
|
95 | + // set to run indefinitely if needed |
|
96 | + if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { |
|
97 | + @set_time_limit(0); |
|
98 | + } |
|
99 | + |
|
100 | + // the cron job must be executed with the right user |
|
101 | + if (!function_exists('posix_getuid')) { |
|
102 | + echo 'The posix extensions are required - see https://www.php.net/manual/en/book.posix.php' . PHP_EOL; |
|
103 | + exit(1); |
|
104 | + } |
|
105 | + |
|
106 | + $user = posix_getuid(); |
|
107 | + $configUser = fileowner(OC::$configDir . 'config.php'); |
|
108 | + if ($user !== $configUser) { |
|
109 | + echo 'Console has to be executed with the user that owns the file config/config.php' . PHP_EOL; |
|
110 | + echo 'Current user id: ' . $user . PHP_EOL; |
|
111 | + echo 'Owner id of config.php: ' . $configUser . PHP_EOL; |
|
112 | + exit(1); |
|
113 | + } |
|
114 | + |
|
115 | + |
|
116 | + // We call Nextcloud from the CLI (aka cron) |
|
117 | + if ($appMode !== 'cron') { |
|
118 | + $appConfig->setValueString('core', 'backgroundjobs_mode', 'cron'); |
|
119 | + } |
|
120 | + |
|
121 | + // a specific job class list can optionally be given as argument |
|
122 | + $jobClasses = array_slice($argv, $verbose ? 2 : 1); |
|
123 | + $jobClasses = empty($jobClasses) ? null : $jobClasses; |
|
124 | + |
|
125 | + // Low-load hours |
|
126 | + $onlyTimeSensitive = false; |
|
127 | + $startHour = $config->getSystemValueInt('maintenance_window_start', 100); |
|
128 | + if ($jobClasses === null && $startHour <= 23) { |
|
129 | + $date = new \DateTime('now', new \DateTimeZone('UTC')); |
|
130 | + $currentHour = (int)$date->format('G'); |
|
131 | + $endHour = $startHour + 4; |
|
132 | + |
|
133 | + if ($startHour <= 20) { |
|
134 | + // Start time: 01:00 |
|
135 | + // End time: 05:00 |
|
136 | + // Only run sensitive tasks when it's before the start or after the end |
|
137 | + $onlyTimeSensitive = $currentHour < $startHour || $currentHour > $endHour; |
|
138 | + } else { |
|
139 | + // Start time: 23:00 |
|
140 | + // End time: 03:00 |
|
141 | + $endHour -= 24; // Correct the end time from 27:00 to 03:00 |
|
142 | + // Only run sensitive tasks when it's after the end and before the start |
|
143 | + $onlyTimeSensitive = $currentHour > $endHour && $currentHour < $startHour; |
|
144 | + } |
|
145 | + } |
|
146 | + |
|
147 | + // Work |
|
148 | + $jobList = Server::get(IJobList::class); |
|
149 | + |
|
150 | + // We only ask for jobs for 14 minutes, because after 5 minutes the next |
|
151 | + // system cron task should spawn and we want to have at most three |
|
152 | + // cron jobs running in parallel. |
|
153 | + $endTime = time() + 14 * 60; |
|
154 | + |
|
155 | + $executedJobs = []; |
|
156 | + |
|
157 | + while ($job = $jobList->getNext($onlyTimeSensitive, $jobClasses)) { |
|
158 | + if (isset($executedJobs[$job->getId()])) { |
|
159 | + $jobList->unlockJob($job); |
|
160 | + break; |
|
161 | + } |
|
162 | + |
|
163 | + $jobDetails = get_class($job) . ' (id: ' . $job->getId() . ', arguments: ' . json_encode($job->getArgument()) . ')'; |
|
164 | + $logger->debug('CLI cron call has selected job ' . $jobDetails, ['app' => 'cron']); |
|
165 | + |
|
166 | + $timeBefore = time(); |
|
167 | + $memoryBefore = memory_get_usage(); |
|
168 | + $memoryPeakBefore = memory_get_peak_usage(); |
|
169 | + |
|
170 | + if ($verbose) { |
|
171 | + echo 'Starting job ' . $jobDetails . PHP_EOL; |
|
172 | + } |
|
173 | + |
|
174 | + $job->start($jobList); |
|
175 | + |
|
176 | + $timeAfter = time(); |
|
177 | + $memoryAfter = memory_get_usage(); |
|
178 | + $memoryPeakAfter = memory_get_peak_usage(); |
|
179 | + |
|
180 | + $cronInterval = 5 * 60; |
|
181 | + $timeSpent = $timeAfter - $timeBefore; |
|
182 | + if ($timeSpent > $cronInterval) { |
|
183 | + $logLevel = match (true) { |
|
184 | + $timeSpent > $cronInterval * 128 => ILogger::FATAL, |
|
185 | + $timeSpent > $cronInterval * 64 => ILogger::ERROR, |
|
186 | + $timeSpent > $cronInterval * 16 => ILogger::WARN, |
|
187 | + $timeSpent > $cronInterval * 8 => ILogger::INFO, |
|
188 | + default => ILogger::DEBUG, |
|
189 | + }; |
|
190 | + $logger->log( |
|
191 | + $logLevel, |
|
192 | + 'Background job ' . $jobDetails . ' ran for ' . $timeSpent . ' seconds', |
|
193 | + ['app' => 'cron'] |
|
194 | + ); |
|
195 | + } |
|
196 | + |
|
197 | + if ($memoryAfter - $memoryBefore > 50_000_000) { |
|
198 | + $message = 'Used memory grew by more than 50 MB when executing job ' . $jobDetails . ': ' . Util::humanFileSize($memoryAfter) . ' (before: ' . Util::humanFileSize($memoryBefore) . ')'; |
|
199 | + $logger->warning($message, ['app' => 'cron']); |
|
200 | + if ($verbose) { |
|
201 | + echo $message . PHP_EOL; |
|
202 | + } |
|
203 | + } |
|
204 | + if ($memoryPeakAfter > 300_000_000 && $memoryPeakBefore <= 300_000_000) { |
|
205 | + $message = 'Cron job used more than 300 MB of ram after executing job ' . $jobDetails . ': ' . Util::humanFileSize($memoryPeakAfter) . ' (before: ' . Util::humanFileSize($memoryPeakBefore) . ')'; |
|
206 | + $logger->warning($message, ['app' => 'cron']); |
|
207 | + if ($verbose) { |
|
208 | + echo $message . PHP_EOL; |
|
209 | + } |
|
210 | + } |
|
211 | + |
|
212 | + // clean up after unclean jobs |
|
213 | + Server::get(SetupManager::class)->tearDown(); |
|
214 | + $tempManager->clean(); |
|
215 | + |
|
216 | + if ($verbose) { |
|
217 | + echo 'Job ' . $jobDetails . ' done in ' . ($timeAfter - $timeBefore) . ' seconds' . PHP_EOL; |
|
218 | + } |
|
219 | + |
|
220 | + $jobList->setLastJob($job); |
|
221 | + $executedJobs[$job->getId()] = true; |
|
222 | + unset($job); |
|
223 | + |
|
224 | + if ($timeAfter > $endTime) { |
|
225 | + break; |
|
226 | + } |
|
227 | + } |
|
228 | + } else { |
|
229 | + // We call cron.php from some website |
|
230 | + if ($appMode === 'cron') { |
|
231 | + // Cron is cron :-P |
|
232 | + OC_JSON::error(['data' => ['message' => 'Backgroundjobs are using system cron!']]); |
|
233 | + } else { |
|
234 | + // Work and success :-) |
|
235 | + $jobList = Server::get(IJobList::class); |
|
236 | + $job = $jobList->getNext(); |
|
237 | + if ($job != null) { |
|
238 | + $logger->debug('WebCron call has selected job with ID ' . strval($job->getId()), ['app' => 'cron']); |
|
239 | + $job->start($jobList); |
|
240 | + $jobList->setLastJob($job); |
|
241 | + } |
|
242 | + OC_JSON::success(); |
|
243 | + } |
|
244 | + } |
|
245 | + |
|
246 | + // Log the successful cron execution |
|
247 | + $appConfig->setValueInt('core', 'lastcron', time()); |
|
248 | + exit(); |
|
249 | 249 | } catch (Exception $ex) { |
250 | - Server::get(LoggerInterface::class)->error( |
|
251 | - $ex->getMessage(), |
|
252 | - ['app' => 'cron', 'exception' => $ex] |
|
253 | - ); |
|
254 | - echo $ex . PHP_EOL; |
|
255 | - exit(1); |
|
250 | + Server::get(LoggerInterface::class)->error( |
|
251 | + $ex->getMessage(), |
|
252 | + ['app' => 'cron', 'exception' => $ex] |
|
253 | + ); |
|
254 | + echo $ex . PHP_EOL; |
|
255 | + exit(1); |
|
256 | 256 | } catch (Error $ex) { |
257 | - Server::get(LoggerInterface::class)->error( |
|
258 | - $ex->getMessage(), |
|
259 | - ['app' => 'cron', 'exception' => $ex] |
|
260 | - ); |
|
261 | - echo $ex . PHP_EOL; |
|
262 | - exit(1); |
|
257 | + Server::get(LoggerInterface::class)->error( |
|
258 | + $ex->getMessage(), |
|
259 | + ['app' => 'cron', 'exception' => $ex] |
|
260 | + ); |
|
261 | + echo $ex . PHP_EOL; |
|
262 | + exit(1); |
|
263 | 263 | } |
@@ -13,7 +13,7 @@ discard block |
||
13 | 13 | * SPDX-License-Identifier: AGPL-3.0-only |
14 | 14 | */ |
15 | 15 | |
16 | -require_once __DIR__ . '/lib/versioncheck.php'; |
|
16 | +require_once __DIR__.'/lib/versioncheck.php'; |
|
17 | 17 | |
18 | 18 | use OCP\App\IAppManager; |
19 | 19 | use OCP\BackgroundJob\IJobList; |
@@ -26,7 +26,7 @@ discard block |
||
26 | 26 | use Psr\Log\LoggerInterface; |
27 | 27 | |
28 | 28 | try { |
29 | - require_once __DIR__ . '/lib/base.php'; |
|
29 | + require_once __DIR__.'/lib/base.php'; |
|
30 | 30 | |
31 | 31 | if (isset($argv[1]) && ($argv[1] === '-h' || $argv[1] === '--help')) { |
32 | 32 | echo 'Description: |
@@ -84,7 +84,7 @@ discard block |
||
84 | 84 | $appMode = $appConfig->getValueString('core', 'backgroundjobs_mode', 'ajax'); |
85 | 85 | if ($appMode === 'none') { |
86 | 86 | if (OC::$CLI) { |
87 | - echo 'Background Jobs are disabled!' . PHP_EOL; |
|
87 | + echo 'Background Jobs are disabled!'.PHP_EOL; |
|
88 | 88 | } else { |
89 | 89 | OC_JSON::error(['data' => ['message' => 'Background jobs disabled!']]); |
90 | 90 | } |
@@ -99,16 +99,16 @@ discard block |
||
99 | 99 | |
100 | 100 | // the cron job must be executed with the right user |
101 | 101 | if (!function_exists('posix_getuid')) { |
102 | - echo 'The posix extensions are required - see https://www.php.net/manual/en/book.posix.php' . PHP_EOL; |
|
102 | + echo 'The posix extensions are required - see https://www.php.net/manual/en/book.posix.php'.PHP_EOL; |
|
103 | 103 | exit(1); |
104 | 104 | } |
105 | 105 | |
106 | 106 | $user = posix_getuid(); |
107 | - $configUser = fileowner(OC::$configDir . 'config.php'); |
|
107 | + $configUser = fileowner(OC::$configDir.'config.php'); |
|
108 | 108 | if ($user !== $configUser) { |
109 | - echo 'Console has to be executed with the user that owns the file config/config.php' . PHP_EOL; |
|
110 | - echo 'Current user id: ' . $user . PHP_EOL; |
|
111 | - echo 'Owner id of config.php: ' . $configUser . PHP_EOL; |
|
109 | + echo 'Console has to be executed with the user that owns the file config/config.php'.PHP_EOL; |
|
110 | + echo 'Current user id: '.$user.PHP_EOL; |
|
111 | + echo 'Owner id of config.php: '.$configUser.PHP_EOL; |
|
112 | 112 | exit(1); |
113 | 113 | } |
114 | 114 | |
@@ -127,7 +127,7 @@ discard block |
||
127 | 127 | $startHour = $config->getSystemValueInt('maintenance_window_start', 100); |
128 | 128 | if ($jobClasses === null && $startHour <= 23) { |
129 | 129 | $date = new \DateTime('now', new \DateTimeZone('UTC')); |
130 | - $currentHour = (int)$date->format('G'); |
|
130 | + $currentHour = (int) $date->format('G'); |
|
131 | 131 | $endHour = $startHour + 4; |
132 | 132 | |
133 | 133 | if ($startHour <= 20) { |
@@ -160,15 +160,15 @@ discard block |
||
160 | 160 | break; |
161 | 161 | } |
162 | 162 | |
163 | - $jobDetails = get_class($job) . ' (id: ' . $job->getId() . ', arguments: ' . json_encode($job->getArgument()) . ')'; |
|
164 | - $logger->debug('CLI cron call has selected job ' . $jobDetails, ['app' => 'cron']); |
|
163 | + $jobDetails = get_class($job).' (id: '.$job->getId().', arguments: '.json_encode($job->getArgument()).')'; |
|
164 | + $logger->debug('CLI cron call has selected job '.$jobDetails, ['app' => 'cron']); |
|
165 | 165 | |
166 | 166 | $timeBefore = time(); |
167 | 167 | $memoryBefore = memory_get_usage(); |
168 | 168 | $memoryPeakBefore = memory_get_peak_usage(); |
169 | 169 | |
170 | 170 | if ($verbose) { |
171 | - echo 'Starting job ' . $jobDetails . PHP_EOL; |
|
171 | + echo 'Starting job '.$jobDetails.PHP_EOL; |
|
172 | 172 | } |
173 | 173 | |
174 | 174 | $job->start($jobList); |
@@ -189,23 +189,23 @@ discard block |
||
189 | 189 | }; |
190 | 190 | $logger->log( |
191 | 191 | $logLevel, |
192 | - 'Background job ' . $jobDetails . ' ran for ' . $timeSpent . ' seconds', |
|
192 | + 'Background job '.$jobDetails.' ran for '.$timeSpent.' seconds', |
|
193 | 193 | ['app' => 'cron'] |
194 | 194 | ); |
195 | 195 | } |
196 | 196 | |
197 | 197 | if ($memoryAfter - $memoryBefore > 50_000_000) { |
198 | - $message = 'Used memory grew by more than 50 MB when executing job ' . $jobDetails . ': ' . Util::humanFileSize($memoryAfter) . ' (before: ' . Util::humanFileSize($memoryBefore) . ')'; |
|
198 | + $message = 'Used memory grew by more than 50 MB when executing job '.$jobDetails.': '.Util::humanFileSize($memoryAfter).' (before: '.Util::humanFileSize($memoryBefore).')'; |
|
199 | 199 | $logger->warning($message, ['app' => 'cron']); |
200 | 200 | if ($verbose) { |
201 | - echo $message . PHP_EOL; |
|
201 | + echo $message.PHP_EOL; |
|
202 | 202 | } |
203 | 203 | } |
204 | 204 | if ($memoryPeakAfter > 300_000_000 && $memoryPeakBefore <= 300_000_000) { |
205 | - $message = 'Cron job used more than 300 MB of ram after executing job ' . $jobDetails . ': ' . Util::humanFileSize($memoryPeakAfter) . ' (before: ' . Util::humanFileSize($memoryPeakBefore) . ')'; |
|
205 | + $message = 'Cron job used more than 300 MB of ram after executing job '.$jobDetails.': '.Util::humanFileSize($memoryPeakAfter).' (before: '.Util::humanFileSize($memoryPeakBefore).')'; |
|
206 | 206 | $logger->warning($message, ['app' => 'cron']); |
207 | 207 | if ($verbose) { |
208 | - echo $message . PHP_EOL; |
|
208 | + echo $message.PHP_EOL; |
|
209 | 209 | } |
210 | 210 | } |
211 | 211 | |
@@ -214,7 +214,7 @@ discard block |
||
214 | 214 | $tempManager->clean(); |
215 | 215 | |
216 | 216 | if ($verbose) { |
217 | - echo 'Job ' . $jobDetails . ' done in ' . ($timeAfter - $timeBefore) . ' seconds' . PHP_EOL; |
|
217 | + echo 'Job '.$jobDetails.' done in '.($timeAfter - $timeBefore).' seconds'.PHP_EOL; |
|
218 | 218 | } |
219 | 219 | |
220 | 220 | $jobList->setLastJob($job); |
@@ -235,7 +235,7 @@ discard block |
||
235 | 235 | $jobList = Server::get(IJobList::class); |
236 | 236 | $job = $jobList->getNext(); |
237 | 237 | if ($job != null) { |
238 | - $logger->debug('WebCron call has selected job with ID ' . strval($job->getId()), ['app' => 'cron']); |
|
238 | + $logger->debug('WebCron call has selected job with ID '.strval($job->getId()), ['app' => 'cron']); |
|
239 | 239 | $job->start($jobList); |
240 | 240 | $jobList->setLastJob($job); |
241 | 241 | } |
@@ -251,13 +251,13 @@ discard block |
||
251 | 251 | $ex->getMessage(), |
252 | 252 | ['app' => 'cron', 'exception' => $ex] |
253 | 253 | ); |
254 | - echo $ex . PHP_EOL; |
|
254 | + echo $ex.PHP_EOL; |
|
255 | 255 | exit(1); |
256 | 256 | } catch (Error $ex) { |
257 | 257 | Server::get(LoggerInterface::class)->error( |
258 | 258 | $ex->getMessage(), |
259 | 259 | ['app' => 'cron', 'exception' => $ex] |
260 | 260 | ); |
261 | - echo $ex . PHP_EOL; |
|
261 | + echo $ex.PHP_EOL; |
|
262 | 262 | exit(1); |
263 | 263 | } |
@@ -20,155 +20,155 @@ |
||
20 | 20 | |
21 | 21 | class JobWorker extends JobBase { |
22 | 22 | |
23 | - public function __construct( |
|
24 | - protected IJobList $jobList, |
|
25 | - protected LoggerInterface $logger, |
|
26 | - private ITempManager $tempManager, |
|
27 | - private SetupManager $setupManager, |
|
28 | - ) { |
|
29 | - parent::__construct($jobList, $logger); |
|
30 | - } |
|
31 | - protected function configure(): void { |
|
32 | - parent::configure(); |
|
33 | - |
|
34 | - $this |
|
35 | - ->setName('background-job:worker') |
|
36 | - ->setDescription('Run a background job worker') |
|
37 | - ->addArgument( |
|
38 | - 'job-classes', |
|
39 | - InputArgument::OPTIONAL | InputArgument::IS_ARRAY, |
|
40 | - 'The classes of the jobs to look for in the database' |
|
41 | - ) |
|
42 | - ->addOption( |
|
43 | - 'once', |
|
44 | - null, |
|
45 | - InputOption::VALUE_NONE, |
|
46 | - 'Only execute the worker once (as a regular cron execution would do it)' |
|
47 | - ) |
|
48 | - ->addOption( |
|
49 | - 'interval', |
|
50 | - 'i', |
|
51 | - InputOption::VALUE_OPTIONAL, |
|
52 | - 'Interval in seconds in which the worker should repeat already processed jobs (set to 0 for no repeat)', |
|
53 | - 5 |
|
54 | - ) |
|
55 | - ->addOption( |
|
56 | - 'stop_after', |
|
57 | - 't', |
|
58 | - InputOption::VALUE_OPTIONAL, |
|
59 | - 'Duration after which the worker should stop and exit. The worker won\'t kill a potential running job, it will exit after this job has finished running (supported values are: "30" or "30s" for 30 seconds, "10m" for 10 minutes and "2h" for 2 hours)' |
|
60 | - ) |
|
61 | - ; |
|
62 | - } |
|
63 | - |
|
64 | - protected function execute(InputInterface $input, OutputInterface $output): int { |
|
65 | - $startTime = time(); |
|
66 | - $stopAfterOptionValue = $input->getOption('stop_after'); |
|
67 | - $stopAfterSeconds = $stopAfterOptionValue === null |
|
68 | - ? null |
|
69 | - : $this->parseStopAfter($stopAfterOptionValue); |
|
70 | - if ($stopAfterSeconds !== null) { |
|
71 | - $output->writeln('<info>Background job worker will stop after ' . $stopAfterSeconds . ' seconds</info>'); |
|
72 | - } |
|
73 | - |
|
74 | - $jobClasses = $input->getArgument('job-classes'); |
|
75 | - $jobClasses = empty($jobClasses) ? null : $jobClasses; |
|
76 | - |
|
77 | - if ($jobClasses !== null) { |
|
78 | - // at least one class is invalid |
|
79 | - foreach ($jobClasses as $jobClass) { |
|
80 | - if (!class_exists($jobClass)) { |
|
81 | - $output->writeln('<error>Invalid job class: ' . $jobClass . '</error>'); |
|
82 | - return 1; |
|
83 | - } |
|
84 | - } |
|
85 | - } |
|
86 | - |
|
87 | - while (true) { |
|
88 | - // Stop if we exceeded stop_after value |
|
89 | - if ($stopAfterSeconds !== null && ($startTime + $stopAfterSeconds) < time()) { |
|
90 | - $output->writeln('stop_after time has been exceeded, exiting...', OutputInterface::VERBOSITY_VERBOSE); |
|
91 | - break; |
|
92 | - } |
|
93 | - // Handle canceling of the process |
|
94 | - try { |
|
95 | - $this->abortIfInterrupted(); |
|
96 | - } catch (InterruptedException $e) { |
|
97 | - $output->writeln('<info>Background job worker stopped</info>'); |
|
98 | - break; |
|
99 | - } |
|
100 | - |
|
101 | - $this->printSummary($input, $output); |
|
102 | - |
|
103 | - usleep(50000); |
|
104 | - $job = $this->jobList->getNext(false, $jobClasses); |
|
105 | - if (!$job) { |
|
106 | - if ($input->getOption('once') === true) { |
|
107 | - if ($jobClasses === null) { |
|
108 | - $output->writeln('No job is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
|
109 | - } else { |
|
110 | - $output->writeln('No job of classes [' . implode(', ', $jobClasses) . '] is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
|
111 | - } |
|
112 | - $output->writeln('Exiting...', OutputInterface::VERBOSITY_VERBOSE); |
|
113 | - break; |
|
114 | - } |
|
115 | - |
|
116 | - $output->writeln('Waiting for new jobs to be queued', OutputInterface::VERBOSITY_VERBOSE); |
|
117 | - // Re-check interval for new jobs |
|
118 | - sleep(1); |
|
119 | - continue; |
|
120 | - } |
|
121 | - |
|
122 | - $output->writeln('Running job ' . get_class($job) . ' with ID ' . $job->getId()); |
|
123 | - |
|
124 | - if ($output->isVerbose()) { |
|
125 | - $this->printJobInfo($job->getId(), $job, $output); |
|
126 | - } |
|
127 | - |
|
128 | - $job->start($this->jobList); |
|
129 | - $output->writeln('Job ' . $job->getId() . ' has finished', OutputInterface::VERBOSITY_VERBOSE); |
|
130 | - |
|
131 | - // clean up after unclean jobs |
|
132 | - $this->setupManager->tearDown(); |
|
133 | - $this->tempManager->clean(); |
|
134 | - |
|
135 | - $this->jobList->setLastJob($job); |
|
136 | - $this->jobList->unlockJob($job); |
|
137 | - |
|
138 | - if ($input->getOption('once') === true) { |
|
139 | - break; |
|
140 | - } |
|
141 | - } |
|
142 | - |
|
143 | - return 0; |
|
144 | - } |
|
145 | - |
|
146 | - private function printSummary(InputInterface $input, OutputInterface $output): void { |
|
147 | - if (!$output->isVeryVerbose()) { |
|
148 | - return; |
|
149 | - } |
|
150 | - $output->writeln('<comment>Summary</comment>'); |
|
151 | - |
|
152 | - $counts = []; |
|
153 | - foreach ($this->jobList->countByClass() as $row) { |
|
154 | - $counts[] = $row; |
|
155 | - } |
|
156 | - $this->writeTableInOutputFormat($input, $output, $counts); |
|
157 | - } |
|
158 | - |
|
159 | - private function parseStopAfter(string $value): ?int { |
|
160 | - if (is_numeric($value)) { |
|
161 | - return (int)$value; |
|
162 | - } |
|
163 | - if (preg_match("/^(\d+)s$/i", $value, $matches)) { |
|
164 | - return (int)$matches[0]; |
|
165 | - } |
|
166 | - if (preg_match("/^(\d+)m$/i", $value, $matches)) { |
|
167 | - return 60 * ((int)$matches[0]); |
|
168 | - } |
|
169 | - if (preg_match("/^(\d+)h$/i", $value, $matches)) { |
|
170 | - return 60 * 60 * ((int)$matches[0]); |
|
171 | - } |
|
172 | - return null; |
|
173 | - } |
|
23 | + public function __construct( |
|
24 | + protected IJobList $jobList, |
|
25 | + protected LoggerInterface $logger, |
|
26 | + private ITempManager $tempManager, |
|
27 | + private SetupManager $setupManager, |
|
28 | + ) { |
|
29 | + parent::__construct($jobList, $logger); |
|
30 | + } |
|
31 | + protected function configure(): void { |
|
32 | + parent::configure(); |
|
33 | + |
|
34 | + $this |
|
35 | + ->setName('background-job:worker') |
|
36 | + ->setDescription('Run a background job worker') |
|
37 | + ->addArgument( |
|
38 | + 'job-classes', |
|
39 | + InputArgument::OPTIONAL | InputArgument::IS_ARRAY, |
|
40 | + 'The classes of the jobs to look for in the database' |
|
41 | + ) |
|
42 | + ->addOption( |
|
43 | + 'once', |
|
44 | + null, |
|
45 | + InputOption::VALUE_NONE, |
|
46 | + 'Only execute the worker once (as a regular cron execution would do it)' |
|
47 | + ) |
|
48 | + ->addOption( |
|
49 | + 'interval', |
|
50 | + 'i', |
|
51 | + InputOption::VALUE_OPTIONAL, |
|
52 | + 'Interval in seconds in which the worker should repeat already processed jobs (set to 0 for no repeat)', |
|
53 | + 5 |
|
54 | + ) |
|
55 | + ->addOption( |
|
56 | + 'stop_after', |
|
57 | + 't', |
|
58 | + InputOption::VALUE_OPTIONAL, |
|
59 | + 'Duration after which the worker should stop and exit. The worker won\'t kill a potential running job, it will exit after this job has finished running (supported values are: "30" or "30s" for 30 seconds, "10m" for 10 minutes and "2h" for 2 hours)' |
|
60 | + ) |
|
61 | + ; |
|
62 | + } |
|
63 | + |
|
64 | + protected function execute(InputInterface $input, OutputInterface $output): int { |
|
65 | + $startTime = time(); |
|
66 | + $stopAfterOptionValue = $input->getOption('stop_after'); |
|
67 | + $stopAfterSeconds = $stopAfterOptionValue === null |
|
68 | + ? null |
|
69 | + : $this->parseStopAfter($stopAfterOptionValue); |
|
70 | + if ($stopAfterSeconds !== null) { |
|
71 | + $output->writeln('<info>Background job worker will stop after ' . $stopAfterSeconds . ' seconds</info>'); |
|
72 | + } |
|
73 | + |
|
74 | + $jobClasses = $input->getArgument('job-classes'); |
|
75 | + $jobClasses = empty($jobClasses) ? null : $jobClasses; |
|
76 | + |
|
77 | + if ($jobClasses !== null) { |
|
78 | + // at least one class is invalid |
|
79 | + foreach ($jobClasses as $jobClass) { |
|
80 | + if (!class_exists($jobClass)) { |
|
81 | + $output->writeln('<error>Invalid job class: ' . $jobClass . '</error>'); |
|
82 | + return 1; |
|
83 | + } |
|
84 | + } |
|
85 | + } |
|
86 | + |
|
87 | + while (true) { |
|
88 | + // Stop if we exceeded stop_after value |
|
89 | + if ($stopAfterSeconds !== null && ($startTime + $stopAfterSeconds) < time()) { |
|
90 | + $output->writeln('stop_after time has been exceeded, exiting...', OutputInterface::VERBOSITY_VERBOSE); |
|
91 | + break; |
|
92 | + } |
|
93 | + // Handle canceling of the process |
|
94 | + try { |
|
95 | + $this->abortIfInterrupted(); |
|
96 | + } catch (InterruptedException $e) { |
|
97 | + $output->writeln('<info>Background job worker stopped</info>'); |
|
98 | + break; |
|
99 | + } |
|
100 | + |
|
101 | + $this->printSummary($input, $output); |
|
102 | + |
|
103 | + usleep(50000); |
|
104 | + $job = $this->jobList->getNext(false, $jobClasses); |
|
105 | + if (!$job) { |
|
106 | + if ($input->getOption('once') === true) { |
|
107 | + if ($jobClasses === null) { |
|
108 | + $output->writeln('No job is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
|
109 | + } else { |
|
110 | + $output->writeln('No job of classes [' . implode(', ', $jobClasses) . '] is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
|
111 | + } |
|
112 | + $output->writeln('Exiting...', OutputInterface::VERBOSITY_VERBOSE); |
|
113 | + break; |
|
114 | + } |
|
115 | + |
|
116 | + $output->writeln('Waiting for new jobs to be queued', OutputInterface::VERBOSITY_VERBOSE); |
|
117 | + // Re-check interval for new jobs |
|
118 | + sleep(1); |
|
119 | + continue; |
|
120 | + } |
|
121 | + |
|
122 | + $output->writeln('Running job ' . get_class($job) . ' with ID ' . $job->getId()); |
|
123 | + |
|
124 | + if ($output->isVerbose()) { |
|
125 | + $this->printJobInfo($job->getId(), $job, $output); |
|
126 | + } |
|
127 | + |
|
128 | + $job->start($this->jobList); |
|
129 | + $output->writeln('Job ' . $job->getId() . ' has finished', OutputInterface::VERBOSITY_VERBOSE); |
|
130 | + |
|
131 | + // clean up after unclean jobs |
|
132 | + $this->setupManager->tearDown(); |
|
133 | + $this->tempManager->clean(); |
|
134 | + |
|
135 | + $this->jobList->setLastJob($job); |
|
136 | + $this->jobList->unlockJob($job); |
|
137 | + |
|
138 | + if ($input->getOption('once') === true) { |
|
139 | + break; |
|
140 | + } |
|
141 | + } |
|
142 | + |
|
143 | + return 0; |
|
144 | + } |
|
145 | + |
|
146 | + private function printSummary(InputInterface $input, OutputInterface $output): void { |
|
147 | + if (!$output->isVeryVerbose()) { |
|
148 | + return; |
|
149 | + } |
|
150 | + $output->writeln('<comment>Summary</comment>'); |
|
151 | + |
|
152 | + $counts = []; |
|
153 | + foreach ($this->jobList->countByClass() as $row) { |
|
154 | + $counts[] = $row; |
|
155 | + } |
|
156 | + $this->writeTableInOutputFormat($input, $output, $counts); |
|
157 | + } |
|
158 | + |
|
159 | + private function parseStopAfter(string $value): ?int { |
|
160 | + if (is_numeric($value)) { |
|
161 | + return (int)$value; |
|
162 | + } |
|
163 | + if (preg_match("/^(\d+)s$/i", $value, $matches)) { |
|
164 | + return (int)$matches[0]; |
|
165 | + } |
|
166 | + if (preg_match("/^(\d+)m$/i", $value, $matches)) { |
|
167 | + return 60 * ((int)$matches[0]); |
|
168 | + } |
|
169 | + if (preg_match("/^(\d+)h$/i", $value, $matches)) { |
|
170 | + return 60 * 60 * ((int)$matches[0]); |
|
171 | + } |
|
172 | + return null; |
|
173 | + } |
|
174 | 174 | } |
@@ -68,7 +68,7 @@ discard block |
||
68 | 68 | ? null |
69 | 69 | : $this->parseStopAfter($stopAfterOptionValue); |
70 | 70 | if ($stopAfterSeconds !== null) { |
71 | - $output->writeln('<info>Background job worker will stop after ' . $stopAfterSeconds . ' seconds</info>'); |
|
71 | + $output->writeln('<info>Background job worker will stop after '.$stopAfterSeconds.' seconds</info>'); |
|
72 | 72 | } |
73 | 73 | |
74 | 74 | $jobClasses = $input->getArgument('job-classes'); |
@@ -78,7 +78,7 @@ discard block |
||
78 | 78 | // at least one class is invalid |
79 | 79 | foreach ($jobClasses as $jobClass) { |
80 | 80 | if (!class_exists($jobClass)) { |
81 | - $output->writeln('<error>Invalid job class: ' . $jobClass . '</error>'); |
|
81 | + $output->writeln('<error>Invalid job class: '.$jobClass.'</error>'); |
|
82 | 82 | return 1; |
83 | 83 | } |
84 | 84 | } |
@@ -107,7 +107,7 @@ discard block |
||
107 | 107 | if ($jobClasses === null) { |
108 | 108 | $output->writeln('No job is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
109 | 109 | } else { |
110 | - $output->writeln('No job of classes [' . implode(', ', $jobClasses) . '] is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
|
110 | + $output->writeln('No job of classes ['.implode(', ', $jobClasses).'] is currently queued', OutputInterface::VERBOSITY_VERBOSE); |
|
111 | 111 | } |
112 | 112 | $output->writeln('Exiting...', OutputInterface::VERBOSITY_VERBOSE); |
113 | 113 | break; |
@@ -119,14 +119,14 @@ discard block |
||
119 | 119 | continue; |
120 | 120 | } |
121 | 121 | |
122 | - $output->writeln('Running job ' . get_class($job) . ' with ID ' . $job->getId()); |
|
122 | + $output->writeln('Running job '.get_class($job).' with ID '.$job->getId()); |
|
123 | 123 | |
124 | 124 | if ($output->isVerbose()) { |
125 | 125 | $this->printJobInfo($job->getId(), $job, $output); |
126 | 126 | } |
127 | 127 | |
128 | 128 | $job->start($this->jobList); |
129 | - $output->writeln('Job ' . $job->getId() . ' has finished', OutputInterface::VERBOSITY_VERBOSE); |
|
129 | + $output->writeln('Job '.$job->getId().' has finished', OutputInterface::VERBOSITY_VERBOSE); |
|
130 | 130 | |
131 | 131 | // clean up after unclean jobs |
132 | 132 | $this->setupManager->tearDown(); |
@@ -158,16 +158,16 @@ discard block |
||
158 | 158 | |
159 | 159 | private function parseStopAfter(string $value): ?int { |
160 | 160 | if (is_numeric($value)) { |
161 | - return (int)$value; |
|
161 | + return (int) $value; |
|
162 | 162 | } |
163 | 163 | if (preg_match("/^(\d+)s$/i", $value, $matches)) { |
164 | - return (int)$matches[0]; |
|
164 | + return (int) $matches[0]; |
|
165 | 165 | } |
166 | 166 | if (preg_match("/^(\d+)m$/i", $value, $matches)) { |
167 | - return 60 * ((int)$matches[0]); |
|
167 | + return 60 * ((int) $matches[0]); |
|
168 | 168 | } |
169 | 169 | if (preg_match("/^(\d+)h$/i", $value, $matches)) { |
170 | - return 60 * 60 * ((int)$matches[0]); |
|
170 | + return 60 * 60 * ((int) $matches[0]); |
|
171 | 171 | } |
172 | 172 | return null; |
173 | 173 | } |
@@ -19,120 +19,120 @@ |
||
19 | 19 | use Symfony\Component\Console\Output\OutputInterface; |
20 | 20 | |
21 | 21 | class Job extends Command { |
22 | - public function __construct( |
|
23 | - protected IJobList $jobList, |
|
24 | - ) { |
|
25 | - parent::__construct(); |
|
26 | - } |
|
27 | - |
|
28 | - protected function configure(): void { |
|
29 | - $this |
|
30 | - ->setName('background-job:execute') |
|
31 | - ->setDescription('Execute a single background job manually') |
|
32 | - ->addArgument( |
|
33 | - 'job-id', |
|
34 | - InputArgument::REQUIRED, |
|
35 | - 'The ID of the job in the database' |
|
36 | - ) |
|
37 | - ->addOption( |
|
38 | - 'force-execute', |
|
39 | - null, |
|
40 | - InputOption::VALUE_NONE, |
|
41 | - 'Force execute the background job, independent from last run and being reserved' |
|
42 | - ) |
|
43 | - ; |
|
44 | - } |
|
45 | - |
|
46 | - protected function execute(InputInterface $input, OutputInterface $output): int { |
|
47 | - $jobId = (int)$input->getArgument('job-id'); |
|
48 | - |
|
49 | - $job = $this->jobList->getById($jobId); |
|
50 | - if ($job === null) { |
|
51 | - $output->writeln('<error>Job with ID ' . $jobId . ' could not be found in the database</error>'); |
|
52 | - return 1; |
|
53 | - } |
|
54 | - |
|
55 | - $this->printJobInfo($jobId, $job, $output); |
|
56 | - $output->writeln(''); |
|
57 | - |
|
58 | - $lastRun = $job->getLastRun(); |
|
59 | - if ($input->getOption('force-execute')) { |
|
60 | - $lastRun = 0; |
|
61 | - $output->writeln('<comment>Forcing execution of the job</comment>'); |
|
62 | - $output->writeln(''); |
|
63 | - |
|
64 | - $this->jobList->resetBackgroundJob($job); |
|
65 | - } |
|
66 | - |
|
67 | - $job = $this->jobList->getById($jobId); |
|
68 | - if ($job === null) { |
|
69 | - $output->writeln('<error>Something went wrong when trying to retrieve Job with ID ' . $jobId . ' from database</error>'); |
|
70 | - return 1; |
|
71 | - } |
|
72 | - $job->start($this->jobList); |
|
73 | - $job = $this->jobList->getById($jobId); |
|
74 | - |
|
75 | - if (($job === null) || ($lastRun !== $job->getLastRun())) { |
|
76 | - $output->writeln('<info>Job executed!</info>'); |
|
77 | - $output->writeln(''); |
|
78 | - |
|
79 | - if ($job instanceof TimedJob) { |
|
80 | - $this->printJobInfo($jobId, $job, $output); |
|
81 | - } |
|
82 | - } else { |
|
83 | - $output->writeln('<comment>Job was not executed because it is not due</comment>'); |
|
84 | - $output->writeln('Specify the <question>--force-execute</question> option to run it anyway'); |
|
85 | - } |
|
86 | - |
|
87 | - return 0; |
|
88 | - } |
|
89 | - |
|
90 | - protected function printJobInfo(int $jobId, IJob $job, OutputInterface $output): void { |
|
91 | - $row = $this->jobList->getDetailsById($jobId); |
|
92 | - |
|
93 | - $lastRun = new \DateTime(); |
|
94 | - $lastRun->setTimestamp((int)$row['last_run']); |
|
95 | - $lastChecked = new \DateTime(); |
|
96 | - $lastChecked->setTimestamp((int)$row['last_checked']); |
|
97 | - $reservedAt = new \DateTime(); |
|
98 | - $reservedAt->setTimestamp((int)$row['reserved_at']); |
|
99 | - |
|
100 | - $output->writeln('Job class: ' . get_class($job)); |
|
101 | - $output->writeln('Arguments: ' . json_encode($job->getArgument())); |
|
102 | - |
|
103 | - $isTimedJob = $job instanceof TimedJob; |
|
104 | - if ($isTimedJob) { |
|
105 | - $output->writeln('Type: timed'); |
|
106 | - } elseif ($job instanceof QueuedJob) { |
|
107 | - $output->writeln('Type: queued'); |
|
108 | - } else { |
|
109 | - $output->writeln('Type: job'); |
|
110 | - } |
|
111 | - |
|
112 | - $output->writeln(''); |
|
113 | - $output->writeln('Last checked: ' . $lastChecked->format(\DateTimeInterface::ATOM)); |
|
114 | - if ((int)$row['reserved_at'] === 0) { |
|
115 | - $output->writeln('Reserved at: -'); |
|
116 | - } else { |
|
117 | - $output->writeln('Reserved at: <comment>' . $reservedAt->format(\DateTimeInterface::ATOM) . '</comment>'); |
|
118 | - } |
|
119 | - $output->writeln('Last executed: ' . $lastRun->format(\DateTimeInterface::ATOM)); |
|
120 | - $output->writeln('Last duration: ' . $row['execution_duration']); |
|
121 | - |
|
122 | - if ($isTimedJob) { |
|
123 | - $reflection = new \ReflectionClass($job); |
|
124 | - $intervalProperty = $reflection->getProperty('interval'); |
|
125 | - $intervalProperty->setAccessible(true); |
|
126 | - $interval = $intervalProperty->getValue($job); |
|
127 | - |
|
128 | - $nextRun = new \DateTime(); |
|
129 | - $nextRun->setTimestamp($row['last_run'] + $interval); |
|
130 | - |
|
131 | - if ($nextRun > new \DateTime()) { |
|
132 | - $output->writeln('Next execution: <comment>' . $nextRun->format(\DateTimeInterface::ATOM) . '</comment>'); |
|
133 | - } else { |
|
134 | - $output->writeln('Next execution: <info>' . $nextRun->format(\DateTimeInterface::ATOM) . '</info>'); |
|
135 | - } |
|
136 | - } |
|
137 | - } |
|
22 | + public function __construct( |
|
23 | + protected IJobList $jobList, |
|
24 | + ) { |
|
25 | + parent::__construct(); |
|
26 | + } |
|
27 | + |
|
28 | + protected function configure(): void { |
|
29 | + $this |
|
30 | + ->setName('background-job:execute') |
|
31 | + ->setDescription('Execute a single background job manually') |
|
32 | + ->addArgument( |
|
33 | + 'job-id', |
|
34 | + InputArgument::REQUIRED, |
|
35 | + 'The ID of the job in the database' |
|
36 | + ) |
|
37 | + ->addOption( |
|
38 | + 'force-execute', |
|
39 | + null, |
|
40 | + InputOption::VALUE_NONE, |
|
41 | + 'Force execute the background job, independent from last run and being reserved' |
|
42 | + ) |
|
43 | + ; |
|
44 | + } |
|
45 | + |
|
46 | + protected function execute(InputInterface $input, OutputInterface $output): int { |
|
47 | + $jobId = (int)$input->getArgument('job-id'); |
|
48 | + |
|
49 | + $job = $this->jobList->getById($jobId); |
|
50 | + if ($job === null) { |
|
51 | + $output->writeln('<error>Job with ID ' . $jobId . ' could not be found in the database</error>'); |
|
52 | + return 1; |
|
53 | + } |
|
54 | + |
|
55 | + $this->printJobInfo($jobId, $job, $output); |
|
56 | + $output->writeln(''); |
|
57 | + |
|
58 | + $lastRun = $job->getLastRun(); |
|
59 | + if ($input->getOption('force-execute')) { |
|
60 | + $lastRun = 0; |
|
61 | + $output->writeln('<comment>Forcing execution of the job</comment>'); |
|
62 | + $output->writeln(''); |
|
63 | + |
|
64 | + $this->jobList->resetBackgroundJob($job); |
|
65 | + } |
|
66 | + |
|
67 | + $job = $this->jobList->getById($jobId); |
|
68 | + if ($job === null) { |
|
69 | + $output->writeln('<error>Something went wrong when trying to retrieve Job with ID ' . $jobId . ' from database</error>'); |
|
70 | + return 1; |
|
71 | + } |
|
72 | + $job->start($this->jobList); |
|
73 | + $job = $this->jobList->getById($jobId); |
|
74 | + |
|
75 | + if (($job === null) || ($lastRun !== $job->getLastRun())) { |
|
76 | + $output->writeln('<info>Job executed!</info>'); |
|
77 | + $output->writeln(''); |
|
78 | + |
|
79 | + if ($job instanceof TimedJob) { |
|
80 | + $this->printJobInfo($jobId, $job, $output); |
|
81 | + } |
|
82 | + } else { |
|
83 | + $output->writeln('<comment>Job was not executed because it is not due</comment>'); |
|
84 | + $output->writeln('Specify the <question>--force-execute</question> option to run it anyway'); |
|
85 | + } |
|
86 | + |
|
87 | + return 0; |
|
88 | + } |
|
89 | + |
|
90 | + protected function printJobInfo(int $jobId, IJob $job, OutputInterface $output): void { |
|
91 | + $row = $this->jobList->getDetailsById($jobId); |
|
92 | + |
|
93 | + $lastRun = new \DateTime(); |
|
94 | + $lastRun->setTimestamp((int)$row['last_run']); |
|
95 | + $lastChecked = new \DateTime(); |
|
96 | + $lastChecked->setTimestamp((int)$row['last_checked']); |
|
97 | + $reservedAt = new \DateTime(); |
|
98 | + $reservedAt->setTimestamp((int)$row['reserved_at']); |
|
99 | + |
|
100 | + $output->writeln('Job class: ' . get_class($job)); |
|
101 | + $output->writeln('Arguments: ' . json_encode($job->getArgument())); |
|
102 | + |
|
103 | + $isTimedJob = $job instanceof TimedJob; |
|
104 | + if ($isTimedJob) { |
|
105 | + $output->writeln('Type: timed'); |
|
106 | + } elseif ($job instanceof QueuedJob) { |
|
107 | + $output->writeln('Type: queued'); |
|
108 | + } else { |
|
109 | + $output->writeln('Type: job'); |
|
110 | + } |
|
111 | + |
|
112 | + $output->writeln(''); |
|
113 | + $output->writeln('Last checked: ' . $lastChecked->format(\DateTimeInterface::ATOM)); |
|
114 | + if ((int)$row['reserved_at'] === 0) { |
|
115 | + $output->writeln('Reserved at: -'); |
|
116 | + } else { |
|
117 | + $output->writeln('Reserved at: <comment>' . $reservedAt->format(\DateTimeInterface::ATOM) . '</comment>'); |
|
118 | + } |
|
119 | + $output->writeln('Last executed: ' . $lastRun->format(\DateTimeInterface::ATOM)); |
|
120 | + $output->writeln('Last duration: ' . $row['execution_duration']); |
|
121 | + |
|
122 | + if ($isTimedJob) { |
|
123 | + $reflection = new \ReflectionClass($job); |
|
124 | + $intervalProperty = $reflection->getProperty('interval'); |
|
125 | + $intervalProperty->setAccessible(true); |
|
126 | + $interval = $intervalProperty->getValue($job); |
|
127 | + |
|
128 | + $nextRun = new \DateTime(); |
|
129 | + $nextRun->setTimestamp($row['last_run'] + $interval); |
|
130 | + |
|
131 | + if ($nextRun > new \DateTime()) { |
|
132 | + $output->writeln('Next execution: <comment>' . $nextRun->format(\DateTimeInterface::ATOM) . '</comment>'); |
|
133 | + } else { |
|
134 | + $output->writeln('Next execution: <info>' . $nextRun->format(\DateTimeInterface::ATOM) . '</info>'); |
|
135 | + } |
|
136 | + } |
|
137 | + } |
|
138 | 138 | } |
@@ -44,11 +44,11 @@ discard block |
||
44 | 44 | } |
45 | 45 | |
46 | 46 | protected function execute(InputInterface $input, OutputInterface $output): int { |
47 | - $jobId = (int)$input->getArgument('job-id'); |
|
47 | + $jobId = (int) $input->getArgument('job-id'); |
|
48 | 48 | |
49 | 49 | $job = $this->jobList->getById($jobId); |
50 | 50 | if ($job === null) { |
51 | - $output->writeln('<error>Job with ID ' . $jobId . ' could not be found in the database</error>'); |
|
51 | + $output->writeln('<error>Job with ID '.$jobId.' could not be found in the database</error>'); |
|
52 | 52 | return 1; |
53 | 53 | } |
54 | 54 | |
@@ -66,7 +66,7 @@ discard block |
||
66 | 66 | |
67 | 67 | $job = $this->jobList->getById($jobId); |
68 | 68 | if ($job === null) { |
69 | - $output->writeln('<error>Something went wrong when trying to retrieve Job with ID ' . $jobId . ' from database</error>'); |
|
69 | + $output->writeln('<error>Something went wrong when trying to retrieve Job with ID '.$jobId.' from database</error>'); |
|
70 | 70 | return 1; |
71 | 71 | } |
72 | 72 | $job->start($this->jobList); |
@@ -91,14 +91,14 @@ discard block |
||
91 | 91 | $row = $this->jobList->getDetailsById($jobId); |
92 | 92 | |
93 | 93 | $lastRun = new \DateTime(); |
94 | - $lastRun->setTimestamp((int)$row['last_run']); |
|
94 | + $lastRun->setTimestamp((int) $row['last_run']); |
|
95 | 95 | $lastChecked = new \DateTime(); |
96 | - $lastChecked->setTimestamp((int)$row['last_checked']); |
|
96 | + $lastChecked->setTimestamp((int) $row['last_checked']); |
|
97 | 97 | $reservedAt = new \DateTime(); |
98 | - $reservedAt->setTimestamp((int)$row['reserved_at']); |
|
98 | + $reservedAt->setTimestamp((int) $row['reserved_at']); |
|
99 | 99 | |
100 | - $output->writeln('Job class: ' . get_class($job)); |
|
101 | - $output->writeln('Arguments: ' . json_encode($job->getArgument())); |
|
100 | + $output->writeln('Job class: '.get_class($job)); |
|
101 | + $output->writeln('Arguments: '.json_encode($job->getArgument())); |
|
102 | 102 | |
103 | 103 | $isTimedJob = $job instanceof TimedJob; |
104 | 104 | if ($isTimedJob) { |
@@ -110,14 +110,14 @@ discard block |
||
110 | 110 | } |
111 | 111 | |
112 | 112 | $output->writeln(''); |
113 | - $output->writeln('Last checked: ' . $lastChecked->format(\DateTimeInterface::ATOM)); |
|
114 | - if ((int)$row['reserved_at'] === 0) { |
|
113 | + $output->writeln('Last checked: '.$lastChecked->format(\DateTimeInterface::ATOM)); |
|
114 | + if ((int) $row['reserved_at'] === 0) { |
|
115 | 115 | $output->writeln('Reserved at: -'); |
116 | 116 | } else { |
117 | - $output->writeln('Reserved at: <comment>' . $reservedAt->format(\DateTimeInterface::ATOM) . '</comment>'); |
|
117 | + $output->writeln('Reserved at: <comment>'.$reservedAt->format(\DateTimeInterface::ATOM).'</comment>'); |
|
118 | 118 | } |
119 | - $output->writeln('Last executed: ' . $lastRun->format(\DateTimeInterface::ATOM)); |
|
120 | - $output->writeln('Last duration: ' . $row['execution_duration']); |
|
119 | + $output->writeln('Last executed: '.$lastRun->format(\DateTimeInterface::ATOM)); |
|
120 | + $output->writeln('Last duration: '.$row['execution_duration']); |
|
121 | 121 | |
122 | 122 | if ($isTimedJob) { |
123 | 123 | $reflection = new \ReflectionClass($job); |
@@ -129,9 +129,9 @@ discard block |
||
129 | 129 | $nextRun->setTimestamp($row['last_run'] + $interval); |
130 | 130 | |
131 | 131 | if ($nextRun > new \DateTime()) { |
132 | - $output->writeln('Next execution: <comment>' . $nextRun->format(\DateTimeInterface::ATOM) . '</comment>'); |
|
132 | + $output->writeln('Next execution: <comment>'.$nextRun->format(\DateTimeInterface::ATOM).'</comment>'); |
|
133 | 133 | } else { |
134 | - $output->writeln('Next execution: <info>' . $nextRun->format(\DateTimeInterface::ATOM) . '</info>'); |
|
134 | + $output->writeln('Next execution: <info>'.$nextRun->format(\DateTimeInterface::ATOM).'</info>'); |
|
135 | 135 | } |
136 | 136 | } |
137 | 137 | } |