1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Dtc\QueueBundle\Controller; |
4
|
|
|
|
5
|
|
|
use Dtc\QueueBundle\Doctrine\DoctrineJobManager; |
6
|
|
|
use Dtc\QueueBundle\Exception\UnsupportedException; |
7
|
|
|
use Dtc\QueueBundle\Model\BaseJob; |
8
|
|
|
use Dtc\QueueBundle\Model\Worker; |
9
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
10
|
|
|
use Symfony\Component\HttpFoundation\Request; |
11
|
|
|
use Symfony\Component\HttpFoundation\StreamedResponse; |
12
|
|
|
|
13
|
|
|
class QueueController |
14
|
|
|
{ |
15
|
|
|
use ControllerTrait; |
16
|
|
|
|
17
|
|
|
private $container; |
18
|
|
|
|
19
|
7 |
|
public function __construct(ContainerInterface $container) |
20
|
|
|
{ |
21
|
7 |
|
$this->container = $container; |
22
|
7 |
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Summary stats. |
26
|
|
|
*/ |
27
|
1 |
|
public function status() |
28
|
|
|
{ |
29
|
1 |
|
$params = []; |
30
|
1 |
|
$jobManager = $this->container->get('dtc_queue.manager.job'); |
31
|
|
|
|
32
|
1 |
|
$params['status'] = $jobManager->getStatus(); |
33
|
1 |
|
$this->addCssJs($params); |
34
|
|
|
|
35
|
1 |
|
return $this->render('@DtcQueue/Queue/status.html.twig', $params); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* List jobs in system by default. |
40
|
|
|
* |
41
|
|
|
* @throws UnsupportedException|\Exception |
42
|
|
|
*/ |
43
|
1 |
|
public function jobsAll() |
44
|
|
|
{ |
45
|
1 |
|
$this->validateManagerType('dtc_queue.manager.job'); |
46
|
1 |
|
$this->checkDtcGridBundle(); |
47
|
|
|
|
48
|
1 |
|
$class1 = $this->container->getParameter('dtc_queue.class.job'); |
49
|
1 |
|
$class2 = $this->container->getParameter('dtc_queue.class.job_archive'); |
50
|
1 |
|
$label1 = 'Non-Archived Jobs'; |
51
|
1 |
|
$label2 = 'Archived Jobs'; |
52
|
|
|
|
53
|
1 |
|
$params = $this->getDualGridParams($class1, $class2, $label1, $label2); |
54
|
|
|
|
55
|
1 |
|
return $this->render('@DtcQueue/Queue/grid.html.twig', $params); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @throws UnsupportedException |
60
|
|
|
*/ |
61
|
1 |
|
public function archive(Request $request) |
62
|
|
|
{ |
63
|
1 |
|
return $this->streamResults($request, 'archiveAllJobs'); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @return StreamedResponse |
68
|
|
|
* |
69
|
|
|
* @throws UnsupportedException |
70
|
|
|
*/ |
71
|
|
|
public function resetStalled(Request $request) |
72
|
|
|
{ |
73
|
|
|
return $this->streamResults($request, 'resetStalledJobs'); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @return StreamedResponse |
78
|
|
|
* |
79
|
|
|
* @throws UnsupportedException |
80
|
|
|
*/ |
81
|
|
|
public function pruneStalled(Request $request) |
82
|
|
|
{ |
83
|
|
|
return $this->streamResults($request, 'pruneStalledJobs'); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param $functionName |
88
|
|
|
* |
89
|
|
|
* @return StreamedResponse |
90
|
|
|
* |
91
|
|
|
* @throws UnsupportedException |
92
|
|
|
*/ |
93
|
1 |
|
protected function streamResults(Request $request, $functionName) |
94
|
|
|
{ |
95
|
1 |
|
$jobManager = $this->container->get('dtc_queue.manager.job'); |
96
|
1 |
|
if (!$jobManager instanceof DoctrineJobManager) { |
97
|
|
|
throw new UnsupportedException('$jobManager must be instance of '.DoctrineJobManager::class); |
98
|
|
|
} |
99
|
|
|
|
100
|
1 |
|
$streamingResponse = new StreamedResponse($this->getStreamFunction($request, $functionName)); |
101
|
1 |
|
$streamingResponse->headers->set('Content-Type', 'application/x-ndjson'); |
102
|
1 |
|
$streamingResponse->headers->set('X-Accel-Buffering', 'no'); |
103
|
|
|
|
104
|
1 |
|
return $streamingResponse; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param string $functionName |
109
|
|
|
* |
110
|
|
|
* @return \Closure |
111
|
|
|
*/ |
112
|
1 |
|
protected function getStreamFunction(Request $request, $functionName) |
113
|
|
|
{ |
114
|
1 |
|
$jobManager = $this->container->get('dtc_queue.manager.job'); |
115
|
1 |
|
$workerName = $request->get('workerName'); |
116
|
1 |
|
$methodName = $request->get('method'); |
117
|
1 |
|
$total = null; |
118
|
1 |
|
$callback = function ($count, $totalCount) use (&$total) { |
119
|
|
|
if (null !== $totalCount && null === $total) { |
120
|
|
|
$total = $totalCount; |
121
|
|
|
echo json_encode(['total' => $total]); |
122
|
|
|
echo "\n"; |
123
|
|
|
flush(); |
124
|
|
|
|
125
|
|
|
return; |
126
|
|
|
} |
127
|
|
|
echo json_encode(['count' => $count]); |
128
|
|
|
echo "\n"; |
129
|
|
|
flush(); |
130
|
1 |
|
}; |
131
|
|
|
|
132
|
1 |
|
return function () use ($jobManager, $callback, $workerName, $methodName, $functionName, &$total) { |
133
|
|
|
switch ($functionName) { |
134
|
|
|
case 'archiveAllJobs': |
135
|
|
|
$total = $jobManager->countLiveJobs($workerName, $methodName); |
136
|
|
|
echo json_encode(['total' => $total]); |
137
|
|
|
echo "\n"; |
138
|
|
|
flush(); |
139
|
|
|
if ($total > 0) { |
140
|
|
|
$jobManager->archiveAllJobs($workerName, $methodName, $callback); |
141
|
|
|
} |
142
|
|
|
break; |
143
|
|
|
default: |
144
|
|
|
$jobManager->$functionName($workerName, $methodName, $callback); |
145
|
|
|
break; |
146
|
|
|
} |
147
|
1 |
|
}; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* List jobs in system by default. |
152
|
|
|
* |
153
|
|
|
* @throws UnsupportedException|\Exception |
154
|
|
|
*/ |
155
|
1 |
|
public function jobs() |
156
|
|
|
{ |
157
|
1 |
|
$this->validateManagerType('dtc_queue.manager.job'); |
158
|
1 |
|
$this->checkDtcGridBundle(); |
159
|
1 |
|
$managerType = $this->container->getParameter('dtc_queue.manager.job'); |
160
|
1 |
|
$rendererFactory = $this->container->get('dtc_grid.renderer.factory'); |
161
|
1 |
|
$renderer = $rendererFactory->create('datatables'); |
162
|
1 |
|
$gridSource = $this->container->get('dtc_queue.grid_source.jobs_waiting.'.('mongodb' === $managerType ? 'odm' : $managerType)); |
163
|
1 |
|
$renderer->bind($gridSource); |
164
|
1 |
|
$params = $renderer->getParams(); |
165
|
1 |
|
$this->addCssJs($params); |
166
|
|
|
|
167
|
1 |
|
$params['worker_methods'] = $this->container->get('dtc_queue.manager.job')->getWorkersAndMethods(); |
168
|
1 |
|
$params['prompt_message'] = 'This will archive all non-running jobs'; |
169
|
|
|
|
170
|
1 |
|
return $this->render('@DtcQueue/Queue/jobs.html.twig', $params); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* List jobs in system by default. |
175
|
|
|
* |
176
|
|
|
* @throws UnsupportedException|\Exception |
177
|
|
|
*/ |
178
|
1 |
|
public function jobsRunning() |
179
|
|
|
{ |
180
|
1 |
|
$this->validateManagerType('dtc_queue.manager.job'); |
181
|
1 |
|
$this->checkDtcGridBundle(); |
182
|
1 |
|
$managerType = $this->container->getParameter('dtc_queue.manager.job'); |
183
|
1 |
|
$rendererFactory = $this->container->get('dtc_grid.renderer.factory'); |
184
|
1 |
|
$renderer = $rendererFactory->create('datatables'); |
185
|
1 |
|
$gridSource = $this->container->get('dtc_queue.grid_source.jobs_running.'.('mongodb' === $managerType ? 'odm' : $managerType)); |
186
|
1 |
|
$renderer->bind($gridSource); |
187
|
1 |
|
$params = $renderer->getParams(); |
188
|
1 |
|
$this->addCssJs($params); |
189
|
|
|
|
190
|
1 |
|
$params['worker_methods'] = $this->container->get('dtc_queue.manager.job')->getWorkersAndMethods(BaseJob::STATUS_RUNNING); |
191
|
1 |
|
$params['prompt_message'] = 'This will prune all stalled jobs'; |
192
|
|
|
|
193
|
1 |
|
return $this->render('@DtcQueue/Queue/jobs_running.html.twig', $params); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @param string $class1 |
198
|
|
|
* @param string $class2 |
199
|
|
|
* @param string $label1 |
200
|
|
|
* @param string $label2 |
201
|
|
|
* |
202
|
|
|
* @return array |
203
|
|
|
* |
204
|
|
|
* @throws \Exception |
205
|
|
|
*/ |
206
|
2 |
|
protected function getDualGridParams($class1, $class2, $label1, $label2) |
207
|
|
|
{ |
208
|
2 |
|
$rendererFactory = $this->container->get('dtc_grid.renderer.factory'); |
209
|
2 |
|
$renderer = $rendererFactory->create('datatables'); |
210
|
2 |
|
$gridSource = $this->container->get('dtc_grid.manager.source')->get($class1); |
211
|
2 |
|
$renderer->bind($gridSource); |
212
|
2 |
|
$params = $renderer->getParams(); |
213
|
|
|
|
214
|
2 |
|
$renderer2 = $rendererFactory->create('datatables'); |
215
|
2 |
|
$gridSource = $this->container->get('dtc_grid.manager.source')->get($class2); |
216
|
2 |
|
$renderer2->bind($gridSource); |
217
|
2 |
|
$params2 = $renderer2->getParams(); |
218
|
|
|
|
219
|
2 |
|
$params['archive_grid'] = $params2['dtc_grid']; |
220
|
|
|
|
221
|
2 |
|
$params['dtc_queue_grid_label1'] = $label1; |
222
|
2 |
|
$params['dtc_queue_grid_label2'] = $label2; |
223
|
2 |
|
$this->addCssJs($params); |
224
|
|
|
|
225
|
2 |
|
return $params; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* List jobs in system by default. |
230
|
|
|
* |
231
|
|
|
* @throws UnsupportedException|\Exception |
232
|
|
|
*/ |
233
|
1 |
|
public function runs() |
234
|
|
|
{ |
235
|
1 |
|
$this->validateRunManager(); |
236
|
1 |
|
$this->checkDtcGridBundle(); |
237
|
1 |
|
$class1 = $this->container->getParameter('dtc_queue.class.run'); |
238
|
1 |
|
$class2 = $this->container->getParameter('dtc_queue.class.run_archive'); |
239
|
1 |
|
$label1 = 'Live Runs'; |
240
|
1 |
|
$label2 = 'Archived Runs'; |
241
|
|
|
|
242
|
1 |
|
$params = $this->getDualGridParams($class1, $class2, $label1, $label2); |
243
|
|
|
|
244
|
1 |
|
return $this->render('@DtcQueue/Queue/grid.html.twig', $params); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* List registered workers in the system. |
249
|
|
|
*/ |
250
|
1 |
|
public function workers() |
251
|
|
|
{ |
252
|
1 |
|
$workerManager = $this->container->get('dtc_queue.manager.worker'); |
253
|
1 |
|
$workers = $workerManager->getWorkers(); |
254
|
|
|
|
255
|
1 |
|
$workerList = []; |
256
|
1 |
|
foreach ($workers as $workerName => $worker) { |
257
|
|
|
/* @var Worker $worker */ |
|
|
|
|
258
|
|
|
$workerList[$workerName] = get_class($worker); |
259
|
|
|
} |
260
|
1 |
|
$params = ['workers' => $workerList]; |
261
|
1 |
|
$this->addCssJs($params); |
262
|
|
|
|
263
|
1 |
|
return $this->render('@DtcQueue/Queue/workers.html.twig', $params); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* Validates that DtcGridBundle exists. |
268
|
|
|
* |
269
|
|
|
* @throws UnsupportedException |
270
|
|
|
*/ |
271
|
4 |
|
protected function checkDtcGridBundle() |
272
|
|
|
{ |
273
|
4 |
|
if (!class_exists('Dtc\GridBundle\DtcGridBundle')) { |
274
|
|
|
throw new UnsupportedException('DtcGridBundle (mmucklo/grid-bundle) needs to be installed.'); |
275
|
|
|
} |
276
|
4 |
|
} |
277
|
|
|
} |
278
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.