1
|
|
|
<?php |
2
|
|
|
/****************************************************************************** |
3
|
|
|
* Wikipedia Account Creation Assistance tool * |
4
|
|
|
* * |
5
|
|
|
* All code in this file is released into the public domain by the ACC * |
6
|
|
|
* Development Team. Please see team.json for a list of contributors. * |
7
|
|
|
******************************************************************************/ |
8
|
|
|
|
9
|
|
|
namespace Waca\Pages; |
10
|
|
|
|
11
|
|
|
use Waca\DataObjects\EmailTemplate; |
12
|
|
|
use Waca\DataObjects\JobQueue; |
13
|
|
|
use Waca\DataObjects\Log; |
14
|
|
|
use Waca\DataObjects\Request; |
15
|
|
|
use Waca\DataObjects\User; |
16
|
|
|
use Waca\Exceptions\ApplicationLogicException; |
17
|
|
|
use Waca\Helpers\Logger; |
18
|
|
|
use Waca\Helpers\LogHelper; |
19
|
|
|
use Waca\Helpers\SearchHelpers\JobQueueSearchHelper; |
20
|
|
|
use Waca\Helpers\SearchHelpers\LogSearchHelper; |
21
|
|
|
use Waca\Helpers\SearchHelpers\RequestSearchHelper; |
22
|
|
|
use Waca\Helpers\SearchHelpers\UserSearchHelper; |
23
|
|
|
use Waca\RequestStatus; |
24
|
|
|
use Waca\Tasks\PagedInternalPageBase; |
25
|
|
|
use Waca\WebRequest; |
26
|
|
|
|
27
|
|
|
class PageJobQueue extends PagedInternalPageBase |
28
|
|
|
{ |
29
|
|
|
/** |
30
|
|
|
* Main function for this page, when no specific actions are called. |
31
|
|
|
* @return void |
32
|
|
|
*/ |
33
|
|
|
protected function main() |
34
|
|
|
{ |
35
|
|
|
$this->setHtmlTitle('Job Queue Management'); |
36
|
|
|
|
37
|
|
|
$this->prepareMaps(); |
38
|
|
|
|
39
|
|
|
$database = $this->getDatabase(); |
40
|
|
|
|
41
|
|
|
/** @var JobQueue[] $jobList */ |
42
|
|
|
$jobList = JobQueueSearchHelper::get($database) |
43
|
|
|
->statusIn(array('ready', 'waiting', 'running', 'failed')) |
44
|
|
|
->notAcknowledged() |
45
|
|
|
->fetch(); |
46
|
|
|
|
47
|
|
|
$userIds = array(); |
48
|
|
|
$requestIds = array(); |
49
|
|
|
|
50
|
|
View Code Duplication |
foreach ($jobList as $job) { |
|
|
|
|
51
|
|
|
$userIds[] = $job->getTriggerUserId(); |
52
|
|
|
$requestIds[] = $job->getRequest(); |
53
|
|
|
|
54
|
|
|
$job->setDatabase($database); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
$this->assign('canSeeAll', $this->barrierTest('all', User::getCurrent($database))); |
58
|
|
|
|
59
|
|
|
$this->assign('users', UserSearchHelper::get($database)->inIds($userIds)->fetchMap('username')); |
60
|
|
|
$this->assign('requests', RequestSearchHelper::get($database)->inIds($requestIds)->fetchMap('name')); |
61
|
|
|
|
62
|
|
|
$this->assign('joblist', $jobList); |
63
|
|
|
$this->setTemplate('jobqueue/main.tpl'); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
protected function all() |
67
|
|
|
{ |
68
|
|
|
$this->setHtmlTitle('All Jobs'); |
69
|
|
|
|
70
|
|
|
$this->prepareMaps(); |
71
|
|
|
|
72
|
|
|
$database = $this->getDatabase(); |
73
|
|
|
|
74
|
|
|
$searchHelper = JobQueueSearchHelper::get($database); |
75
|
|
|
$this->setSearchHelper($searchHelper); |
76
|
|
|
$this->setupLimits(); |
77
|
|
|
|
78
|
|
|
$filterUser = WebRequest::getString('filterUser'); |
79
|
|
|
$filterTask = WebRequest::getString('filterTask'); |
80
|
|
|
$filterStatus = WebRequest::getString('filterStatus'); |
81
|
|
|
$filterRequest = WebRequest::getString('filterRequest'); |
82
|
|
|
|
83
|
|
|
if ($filterUser !== null) { |
84
|
|
|
$searchHelper->byUser(User::getByUsername($filterUser, $database)->getId()); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if ($filterTask !== null) { |
88
|
|
|
$searchHelper->byTask($filterTask); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
if ($filterStatus !== null) { |
92
|
|
|
$searchHelper->byStatus($filterStatus); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
if ($filterRequest !== null) { |
96
|
|
|
$searchHelper->byRequest($filterRequest); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** @var JobQueue[] $jobList */ |
100
|
|
|
$jobList = $searchHelper->getRecordCount($count)->fetch(); |
101
|
|
|
|
102
|
|
|
$this->setupPageData($count, array( |
103
|
|
|
'filterUser' => $filterUser, |
104
|
|
|
'filterTask' => $filterTask, |
105
|
|
|
'filterStatus' => $filterStatus, |
106
|
|
|
'filterRequest' => $filterRequest, |
107
|
|
|
)); |
108
|
|
|
|
109
|
|
|
$userIds = array(); |
110
|
|
|
$requestIds = array(); |
111
|
|
|
|
112
|
|
View Code Duplication |
foreach ($jobList as $job) { |
|
|
|
|
113
|
|
|
$userIds[] = $job->getTriggerUserId(); |
114
|
|
|
$requestIds[] = $job->getRequest(); |
115
|
|
|
|
116
|
|
|
$job->setDatabase($database); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
$this->getTypeAheadHelper()->defineTypeAheadSource('username-typeahead', function() use ($database) { |
120
|
|
|
return UserSearchHelper::get($database)->fetchColumn('username'); |
121
|
|
|
}); |
122
|
|
|
|
123
|
|
|
$this->assign('users', UserSearchHelper::get($database)->inIds($userIds)->fetchMap('username')); |
124
|
|
|
$this->assign('requests', RequestSearchHelper::get($database)->inIds($requestIds)->fetchMap('name')); |
125
|
|
|
|
126
|
|
|
$this->assign('joblist', $jobList); |
127
|
|
|
|
128
|
|
|
$this->setTemplate('jobqueue/all.tpl'); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
protected function view() |
132
|
|
|
{ |
133
|
|
|
$jobId = WebRequest::getInt('id'); |
134
|
|
|
$database = $this->getDatabase(); |
135
|
|
|
|
136
|
|
|
if ($jobId === null) { |
137
|
|
|
throw new ApplicationLogicException('No job specified'); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** @var JobQueue $job */ |
141
|
|
|
$job = JobQueue::getById($jobId, $database); |
142
|
|
|
|
143
|
|
|
if ($job === false) { |
144
|
|
|
throw new ApplicationLogicException('Could not find requested job'); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$this->setHtmlTitle('Job #' . $job->getId()); |
148
|
|
|
|
149
|
|
|
$this->prepareMaps(); |
150
|
|
|
|
151
|
|
|
$this->assign('user', User::getById($job->getTriggerUserId(), $database)); |
152
|
|
|
$this->assign('request', Request::getById($job->getRequest(), $database)); |
153
|
|
|
$this->assign('emailTemplate', EmailTemplate::getById($job->getEmailTemplate(), $database)); |
154
|
|
|
$this->assign('parent', JobQueue::getById($job->getParent(), $database)); |
155
|
|
|
|
156
|
|
|
/** @var Log[] $logs */ |
157
|
|
|
$logs = LogSearchHelper::get($database)->byObjectType('JobQueue') |
158
|
|
|
->byObjectId($job->getId())->getRecordCount($logCount)->fetch(); |
159
|
|
View Code Duplication |
if ($logCount === 0) { |
|
|
|
|
160
|
|
|
$this->assign('log', array()); |
161
|
|
|
} |
162
|
|
|
else { |
163
|
|
|
list($users, $logData) = LogHelper::prepareLogsForTemplate($logs, $database, $this->getSiteConfiguration()); |
164
|
|
|
|
165
|
|
|
$this->assign("log", $logData); |
166
|
|
|
$this->assign("users", $users); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
$this->assignCSRFToken(); |
170
|
|
|
|
171
|
|
|
$this->assign('job', $job); |
172
|
|
|
|
173
|
|
|
$this->assign('canAcknowledge', $this->barrierTest('acknowledge', User::getCurrent($database))); |
174
|
|
|
$this->assign('canRequeue', $this->barrierTest('requeue', User::getCurrent($database))); |
175
|
|
|
$this->setTemplate('jobqueue/view.tpl'); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
protected function acknowledge() |
179
|
|
|
{ |
180
|
|
|
if (!WebRequest::wasPosted()) { |
181
|
|
|
throw new ApplicationLogicException('This page does not support GET methods.'); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$this->validateCSRFToken(); |
185
|
|
|
|
186
|
|
|
$jobId = WebRequest::postInt('job'); |
187
|
|
|
$database = $this->getDatabase(); |
188
|
|
|
|
189
|
|
|
if ($jobId === null) { |
190
|
|
|
throw new ApplicationLogicException('No job specified'); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** @var JobQueue $job */ |
194
|
|
|
$job = JobQueue::getById($jobId, $database); |
195
|
|
|
|
196
|
|
|
if ($job === false) { |
197
|
|
|
throw new ApplicationLogicException('Could not find requested job'); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
$job->setUpdateVersion(WebRequest::postInt('updateVersion')); |
201
|
|
|
$job->setAcknowledged(true); |
|
|
|
|
202
|
|
|
$job->save(); |
203
|
|
|
|
204
|
|
|
Logger::backgroundJobAcknowledged($database, $job); |
205
|
|
|
|
206
|
|
|
$this->redirect('jobQueue', 'view', array('id' => $jobId)); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
protected function requeue() |
210
|
|
|
{ |
211
|
|
|
if (!WebRequest::wasPosted()) { |
212
|
|
|
throw new ApplicationLogicException('This page does not support GET methods.'); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
$this->validateCSRFToken(); |
216
|
|
|
|
217
|
|
|
$jobId = WebRequest::postInt('job'); |
218
|
|
|
$database = $this->getDatabase(); |
219
|
|
|
|
220
|
|
|
if ($jobId === null) { |
221
|
|
|
throw new ApplicationLogicException('No job specified'); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** @var JobQueue $job */ |
225
|
|
|
$job = JobQueue::getById($jobId, $database); |
226
|
|
|
|
227
|
|
|
if ($job === false) { |
228
|
|
|
throw new ApplicationLogicException('Could not find requested job'); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
$job->setStatus(JobQueue::STATUS_READY); |
232
|
|
|
$job->setUpdateVersion(WebRequest::postInt('updateVersion')); |
233
|
|
|
$job->setAcknowledged(null); |
234
|
|
|
$job->setError(null); |
235
|
|
|
$job->save(); |
236
|
|
|
|
237
|
|
|
/** @var Request $request */ |
238
|
|
|
$request = Request::getById($job->getRequest(), $database); |
239
|
|
|
$request->setStatus(RequestStatus::JOBQUEUE); |
240
|
|
|
$request->save(); |
241
|
|
|
|
242
|
|
|
Logger::enqueuedJobQueue($database, $request); |
243
|
|
|
Logger::backgroundJobRequeued($database, $job); |
244
|
|
|
|
245
|
|
|
$this->redirect('jobQueue', 'view', array('id' => $jobId)); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
protected function prepareMaps() |
249
|
|
|
{ |
250
|
|
|
$taskNameMap = JobQueue::getTaskDescriptions(); |
251
|
|
|
|
252
|
|
|
$statusDecriptionMap = array( |
253
|
|
|
JobQueue::STATUS_CANCELLED => 'The job was cancelled', |
254
|
|
|
JobQueue::STATUS_COMPLETE => 'The job completed successfully', |
255
|
|
|
JobQueue::STATUS_FAILED => 'The job encountered an error', |
256
|
|
|
JobQueue::STATUS_READY => 'The job is ready to be picked up by the next job runner execution', |
257
|
|
|
JobQueue::STATUS_RUNNING => 'The job is being run right now by the job runner', |
258
|
|
|
JobQueue::STATUS_WAITING => 'The job has been picked up by a job runner', |
259
|
|
|
JobQueue::STATUS_HELD => 'The job has manually held from processing', |
260
|
|
|
); |
261
|
|
|
$this->assign('taskNameMap', $taskNameMap); |
262
|
|
|
$this->assign('statusDescriptionMap', $statusDecriptionMap); |
263
|
|
|
} |
264
|
|
|
} |
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.