-
Notifications
You must be signed in to change notification settings - Fork 11k
/
CallQueuedHandler.php
177 lines (155 loc) · 4.58 KB
/
CallQueuedHandler.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<?php
namespace Illuminate\Queue;
use Exception;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Queue\Job;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Pipeline\Pipeline;
use ReflectionClass;
class CallQueuedHandler
{
/**
* The bus dispatcher implementation.
*
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected $dispatcher;
/**
* The container instance.
*
* @var \Illuminate\Contracts\Container\Container
*/
protected $container;
/**
* Create a new handler instance.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $dispatcher
* @param \Illuminate\Contracts\Container\Container $container
* @return void
*/
public function __construct(Dispatcher $dispatcher, Container $container)
{
$this->container = $container;
$this->dispatcher = $dispatcher;
}
/**
* Handle the queued job.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @param array $data
* @return void
*/
public function call(Job $job, array $data)
{
try {
$command = $this->setJobInstanceIfNecessary(
$job, unserialize($data['command'])
);
} catch (ModelNotFoundException $e) {
return $this->handleModelNotFound($job, $e);
}
$this->dispatchThroughMiddleware($job, $command);
if (! $job->hasFailed() && ! $job->isReleased()) {
$this->ensureNextJobInChainIsDispatched($command);
}
if (! $job->isDeletedOrReleased()) {
$job->delete();
}
}
/**
* Dispatch the given job / command through its specified middleware.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @param mixed $command
* @return mixed
*/
protected function dispatchThroughMiddleware(Job $job, $command)
{
return (new Pipeline($this->container))->send($command)
->through(array_merge(method_exists($command, 'middleware') ? $command->middleware() : [], $command->middleware ?? []))
->then(function ($command) use ($job) {
return $this->dispatcher->dispatchNow(
$command, $this->resolveHandler($job, $command)
);
});
}
/**
* Resolve the handler for the given command.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @param mixed $command
* @return mixed
*/
protected function resolveHandler($job, $command)
{
$handler = $this->dispatcher->getCommandHandler($command) ?: null;
if ($handler) {
$this->setJobInstanceIfNecessary($job, $handler);
}
return $handler;
}
/**
* Set the job instance of the given class if necessary.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @param mixed $instance
* @return mixed
*/
protected function setJobInstanceIfNecessary(Job $job, $instance)
{
if (in_array(InteractsWithQueue::class, class_uses_recursive($instance))) {
$instance->setJob($job);
}
return $instance;
}
/**
* Ensure the next job in the chain is dispatched if applicable.
*
* @param mixed $command
* @return void
*/
protected function ensureNextJobInChainIsDispatched($command)
{
if (method_exists($command, 'dispatchNextJobInChain')) {
$command->dispatchNextJobInChain();
}
}
/**
* Handle a model not found exception.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @param \Exception $e
* @return void
*/
protected function handleModelNotFound(Job $job, $e)
{
$class = $job->resolveName();
try {
$shouldDelete = (new ReflectionClass($class))
->getDefaultProperties()['deleteWhenMissingModels'] ?? false;
} catch (Exception $e) {
$shouldDelete = false;
}
if ($shouldDelete) {
return $job->delete();
}
return $job->fail($e);
}
/**
* Call the failed method on the job instance.
*
* The exception that caused the failure will be passed.
*
* @param array $data
* @param \Exception $e
* @return void
*/
public function failed(array $data, $e)
{
$command = unserialize($data['command']);
if (method_exists($command, 'failed')) {
$command->failed($e);
}
}
}