File tree Expand file tree Collapse file tree 7 files changed +115
-5
lines changed
tests/lib/Integration/Queue Expand file tree Collapse file tree 7 files changed +115
-5
lines changed Original file lin
10000
e number Diff line number Diff line change @@ -18,6 +18,9 @@ Update `zend-diactoros` dependency.
18
18
Fix using an alternative decoding type for update (` PATCH ` ) requests.
19
19
- [ #370 ] ( https://github.com/cloudcreativity/laravel-json-api/pull/370 )
20
20
Fix wrong validation error title when creating a custom validator.
21
+ - [ #358 ] ( https://github.com/cloudcreativity/laravel-json-api/issues/358 )
22
+ Queue listener could trigger a ` ModelNotFoundException ` when deserializing a job that had deleted a
23
+ model during its ` handle() ` method.
21
24
22
25
## [ 1.1.0] - 2019-04-12
23
26
Original file line number Diff line number Diff line change @@ -217,6 +217,43 @@ class ProcessPodcast implements ShouldQueue
217
217
}
218
218
```
219
219
220
+ ## Manually Marking Client Jobs as Complete
221
+
222
+ This package will, in most cases, automatically mark the stored representation of the job as complete.
223
+ We do this by listening the Laravel's queue events.
224
+
225
+ There is one scenario where we cannot do this: if your job deletes a model during its ` handle ` method.
226
+ This is because we cannot deserialize the job in our listener without causing a ` ModelNotFoundException ` .
227
+
228
+ In these scenarios, you will need to manually mark the stored representation of the job as complete.
229
+ Use the ` didComplete() ` method, which accepts one argument: a boolean indicating success (will be
230
+ ` true ` if not provided).
231
+
232
+ For example:
233
+
234
+ ``` php
235
+ namespace App\Jobs;
236
+
237
+ use CloudCreativity\LaravelJsonApi\Queue\ClientDispatchable;
238
+ use Illuminate\Contracts\Queue\ShouldQueue;
239
+
240
+ class RemovePodcast implements ShouldQueue
241
+ {
242
+
243
+ use ClientDispatchable;
244
+
245
+ // ...
246
+
247
+ public function handle()
248
+ {
249
+ // ...logic to remove a podcast.
250
+
251
+ $this->podcast->delete();
252
+ $this->didComplete();
253
+ }
254
+ }
255
+ ```
256
+
220
257
## Routing
221
258
222
259
The final step of setup is to enable asynchronous process routes on a resource. These
Original file line number Diff line number Diff line change @@ -94,4 +94,25 @@ public function didCreate($resource): void
94
94
$ this ->clientJob ->setResource ($ resource )->save ();
95
95
}
96
96
}
97
+
98
+ /**
99
+ * Mark the client job as completed.
100
+ *
101
+ * Although our queue listeners handle this for you in most cases, there
102
+ * are some scenarios where it is not possible to do this. E.g. if your
103
+ * job deletes a model that is one of its properties, a `ModelNotFoundException`
104
+ * will be triggered when our listener deserializes the job.
105
+ *
106
+ * Therefore this method is provided so that you can manually mark the
107
+ * client job as completed, if needed.
108
+ *
109
+ * @param bool $success
110
+ * @return void
111
+ */
112
+ public function didComplete (bool $ success = true ): void
113
+ {
114
+ if ($ this ->wasClientDispatched ()) {
115
+ $ this ->clientJob ->completed ($ success );
116
+ }
117
+ }
97
118
}
Original file line number Diff line number Diff line change @@ -168,6 +168,19 @@ public function processed($job): void
168
168
]);
169
169
}
170
170
171
+ /**
172
+ * @param bool $success
173
+ * @return void
174
+ */
175
+ public function completed (bool $ success = true ): void
176
+ {
177
+ $ this ->update ([
178
+ 'attempts ' => $ this ->attempts + 1 ,
179
+ 'completed_at ' => Carbon::now (),
180
+ 'failed ' => !$ success ,
181
+ ]);
182
+ }
183
+
171
184
/**
172
185
* @return Api
173
186
*/
Original file line number Diff line number Diff line change 19
19
20
20
use CloudCreativity \LaravelJsonApi \Contracts \Queue \AsynchronousProcess ;
21
21
use Illuminate \Contracts \Queue \Job ;
22
+ use Illuminate \Database \Eloquent \ModelNotFoundException ;
22
23
use Illuminate \Queue \Events \JobFailed ;
23
24
use Illuminate \Queue \Events \JobProcessed ;
24
25
@@ -55,7 +56,15 @@ private function deserialize(Job $job)
55
56
$ data = $ this ->payload ($ job )['data ' ] ?? [];
56
57
$ command = $ data ['command ' ] ?? null ;
57
58
58
- return is_string ($ command ) ? unserialize ($ command ) : null ;
59
+ if (!is_string ($ command )) {
60
+ return null ;
61
+ }
62
+
63
+ try {
64
<
F438
/td>+ return unserialize ($ command ) ?: null ;
65
+ } catch (ModelNotFoundException $ ex ) {
66
+ return null ;
67
+ }
59
68
}
60
69
61
70
/**
Original file line number Diff line number Diff line change @@ -34,7 +34,7 @@ protected function setUp(): void
34
34
Carbon::setTestNow ('2018-10-23 12:00:00.123456 ' );
35
35
}
36
36
37
- public function testCompletes ()
37
+ public function testCompletes (): void
38
38
{
39
39
$ job = new TestJob ();
40
40
$ job ->clientJob = factory (ClientJob::class)->create ();
@@ -53,7 +53,7 @@ public function testCompletes()
53
53
$ this ->assertInstanceOf (Download::class, $ clientJob ->getResource ());
54
54
}
55
55
56
- public function testFails ()
56
+ public function testFails (): void
57
57
{
58
58
$ job = new TestJob ();
59
59
$ job ->ex = true ;
@@ -73,4 +73,20 @@ public function testFails()
73
73
'failed ' => true ,
74
74
]);
75
75
}
76
+
77
+ public function testDoesNotCauseException (): void
78
+ {
79
+ $ job = new TestJob ();
80
+ $ job ->model = factory (Download::class)->create ();
81
+ $ job ->clientJob = factory (ClientJob::class)->create ();
82
+
83
+ dispatch ($ job );
84
+
85
+ $ this ->assertDatabaseHas ('json_api_client_jobs ' , [
8
EF5E
6
+ 'uuid ' => $ job ->clientJob ->getKey (),
87
+ 'attempts ' => 1 ,
88
+ 'completed_at ' => Carbon::now ()->format ('Y-m-d H:i:s ' ),
89
+ 'failed ' => false ,
90
+ ]);
91
+ }
76
92
}
Original file line number Diff line number Diff line change @@ -44,18 +44,29 @@ class TestJob implements ShouldQueue
44
44
*/
45
45
public $ tries = 2 ;
46
46
47
+ /**
48
+ * @var Download|null
49
+ */
50
+ public $ model ;
51
+
47
52
/**
48
53
* Execute the job.
49
54
*
50
- * @return Download
55
+ * @return Download|null
51
56
* @throws \Exception
52
57
*/
53
- public function handle (): Download
58
+ public function handle (): ? Download
54
59
{
55
60
if ($ this ->ex ) {
56
61
throw new \LogicException ('Boom. ' );
57
62
}
58
63
64
+ if ($ this ->model ) {
65
+ $ this ->model ->delete ();
66
+ $ this ->didComplete ();
67
+ return null ;
68
+ }
69
+
59
70
$ download = factory (Download::class)->create ();
60
71
$ this ->didCreate ($ download );
61
72
You can’t perform that action at this time.
0 commit comments