comparison core/lib/Drupal/Core/Cron.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 1fec387a4317
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 namespace Drupal\Core;
4
5 use Drupal\Component\Utility\Timer;
6 use Drupal\Core\Extension\ModuleHandlerInterface;
7 use Drupal\Core\Queue\QueueWorkerManagerInterface;
8 use Drupal\Core\Queue\RequeueException;
9 use Drupal\Core\State\StateInterface;
10 use Drupal\Core\Lock\LockBackendInterface;
11 use Drupal\Core\Queue\QueueFactory;
12 use Drupal\Core\Session\AnonymousUserSession;
13 use Drupal\Core\Session\AccountSwitcherInterface;
14 use Drupal\Core\Queue\SuspendQueueException;
15 use Psr\Log\LoggerInterface;
16 use Psr\Log\NullLogger;
17
18 /**
19 * The Drupal core Cron service.
20 */
21 class Cron implements CronInterface {
22
23 /**
24 * The module handler service.
25 *
26 * @var \Drupal\Core\Extension\ModuleHandlerInterface
27 */
28 protected $moduleHandler;
29
30 /**
31 * The lock service.
32 *
33 * @var \Drupal\Core\Lock\LockBackendInterface
34 */
35 protected $lock;
36
37 /**
38 * The queue service.
39 *
40 * @var \Drupal\Core\Queue\QueueFactory
41 */
42 protected $queueFactory;
43
44 /**
45 * The state service.
46 *
47 * @var \Drupal\Core\State\StateInterface
48 */
49 protected $state;
50
51 /**
52 * The account switcher service.
53 *
54 * @var \Drupal\Core\Session\AccountSwitcherInterface
55 */
56 protected $accountSwitcher;
57
58 /**
59 * A logger instance.
60 *
61 * @var \Psr\Log\LoggerInterface
62 */
63 protected $logger;
64
65 /**
66 * The queue plugin manager.
67 *
68 * @var \Drupal\Core\Queue\QueueWorkerManagerInterface
69 */
70 protected $queueManager;
71
72 /**
73 * Constructs a cron object.
74 *
75 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
76 * The module handler
77 * @param \Drupal\Core\Lock\LockBackendInterface $lock
78 * The lock service.
79 * @param \Drupal\Core\Queue\QueueFactory $queue_factory
80 * The queue service.
81 * @param \Drupal\Core\State\StateInterface $state
82 * The state service.
83 * @param \Drupal\Core\Session\AccountSwitcherInterface $account_switcher
84 * The account switching service.
85 * @param \Psr\Log\LoggerInterface $logger
86 * A logger instance.
87 * @param \Drupal\Core\Queue\QueueWorkerManagerInterface $queue_manager
88 * The queue plugin manager.
89 */
90 public function __construct(ModuleHandlerInterface $module_handler, LockBackendInterface $lock, QueueFactory $queue_factory, StateInterface $state, AccountSwitcherInterface $account_switcher, LoggerInterface $logger, QueueWorkerManagerInterface $queue_manager) {
91 $this->moduleHandler = $module_handler;
92 $this->lock = $lock;
93 $this->queueFactory = $queue_factory;
94 $this->state = $state;
95 $this->accountSwitcher = $account_switcher;
96 $this->logger = $logger;
97 $this->queueManager = $queue_manager;
98 }
99
100 /**
101 * {@inheritdoc}
102 */
103 public function run() {
104 // Allow execution to continue even if the request gets cancelled.
105 @ignore_user_abort(TRUE);
106
107 // Force the current user to anonymous to ensure consistent permissions on
108 // cron runs.
109 $this->accountSwitcher->switchTo(new AnonymousUserSession());
110
111 // Try to allocate enough time to run all the hook_cron implementations.
112 drupal_set_time_limit(240);
113
114 $return = FALSE;
115
116 // Try to acquire cron lock.
117 if (!$this->lock->acquire('cron', 900.0)) {
118 // Cron is still running normally.
119 $this->logger->warning('Attempting to re-run cron while it is already running.');
120 }
121 else {
122 $this->invokeCronHandlers();
123 $this->setCronLastTime();
124
125 // Release cron lock.
126 $this->lock->release('cron');
127
128 // Return TRUE so other functions can check if it did run successfully
129 $return = TRUE;
130 }
131
132 // Process cron queues.
133 $this->processQueues();
134
135 // Restore the user.
136 $this->accountSwitcher->switchBack();
137
138 return $return;
139 }
140
141 /**
142 * Records and logs the request time for this cron invocation.
143 */
144 protected function setCronLastTime() {
145 // Record cron time.
146 $this->state->set('system.cron_last', REQUEST_TIME);
147 $this->logger->notice('Cron run completed.');
148 }
149
150 /**
151 * Processes cron queues.
152 */
153 protected function processQueues() {
154 // Grab the defined cron queues.
155 foreach ($this->queueManager->getDefinitions() as $queue_name => $info) {
156 if (isset($info['cron'])) {
157 // Make sure every queue exists. There is no harm in trying to recreate
158 // an existing queue.
159 $this->queueFactory->get($queue_name)->createQueue();
160
161 $queue_worker = $this->queueManager->createInstance($queue_name);
162 $end = time() + (isset($info['cron']['time']) ? $info['cron']['time'] : 15);
163 $queue = $this->queueFactory->get($queue_name);
164 $lease_time = isset($info['cron']['time']) ?: NULL;
165 while (time() < $end && ($item = $queue->claimItem($lease_time))) {
166 try {
167 $queue_worker->processItem($item->data);
168 $queue->deleteItem($item);
169 }
170 catch (RequeueException $e) {
171 // The worker requested the task be immediately requeued.
172 $queue->releaseItem($item);
173 }
174 catch (SuspendQueueException $e) {
175 // If the worker indicates there is a problem with the whole queue,
176 // release the item and skip to the next queue.
177 $queue->releaseItem($item);
178
179 watchdog_exception('cron', $e);
180
181 // Skip to the next queue.
182 continue 2;
183 }
184 catch (\Exception $e) {
185 // In case of any other kind of exception, log it and leave the item
186 // in the queue to be processed again later.
187 watchdog_exception('cron', $e);
188 }
189 }
190 }
191 }
192 }
193
194 /**
195 * Invokes any cron handlers implementing hook_cron.
196 */
197 protected function invokeCronHandlers() {
198 $module_previous = '';
199
200 // If detailed logging isn't enabled, don't log individual execution times.
201 $time_logging_enabled = \Drupal::config('system.cron')->get('logging');
202 $logger = $time_logging_enabled ? $this->logger : new NullLogger();
203
204 // Iterate through the modules calling their cron handlers (if any):
205 foreach ($this->moduleHandler->getImplementations('cron') as $module) {
206
207 if (!$module_previous) {
208 $logger->notice('Starting execution of @module_cron().', [
209 '@module' => $module,
210 ]);
211 }
212 else {
213 $logger->notice('Starting execution of @module_cron(), execution of @module_previous_cron() took @time.', [
214 '@module' => $module,
215 '@module_previous' => $module_previous,
216 '@time' => Timer::read('cron_' . $module_previous) . 'ms',
217 ]);
218 }
219 Timer::start('cron_' . $module);
220
221 // Do not let an exception thrown by one module disturb another.
222 try {
223 $this->moduleHandler->invoke($module, 'cron');
224 }
225 catch (\Exception $e) {
226 watchdog_exception('cron', $e);
227 }
228
229 Timer::stop('cron_' . $module);
230 $module_previous = $module;
231 }
232 if ($module_previous) {
233 $logger->notice('Execution of @module_previous_cron() took @time.', [
234 '@module_previous' => $module_previous,
235 '@time' => Timer::read('cron_' . $module_previous) . 'ms',
236 ]);
237 }
238 }
239
240 }