Skip to content

Commit 73a6ed7

Browse files
Merge pull request #96 from stackkit/bugfix/95-job-deletion
#95 job deletion
2 parents 2282462 + 64595e9 commit 73a6ed7

9 files changed

+49
-24
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
composer.lock
33
.idea/
44
.phpunit.result.cache
5+
.phpunit.cache

src/CloudTasksApi.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* @method static Task createTask(string $queueName, Task $task)
1414
* @method static void deleteTask(string $taskName)
1515
* @method static Task getTask(string $taskName)
16-
* @method static int|null getRetryUntilTimestamp(string $taskName)
16+
* @method static int|null getRetryUntilTimestamp(Task $task)
1717
*/
1818
class CloudTasksApi extends Facade
1919
{

src/CloudTasksApiConcrete.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,8 @@ public function getTask(string $taskName): Task
5050
return $this->client->getTask($taskName);
5151
}
5252

53-
public function getRetryUntilTimestamp(string $taskName): ?int
53+
public function getRetryUntilTimestamp(Task $task): ?int
5454
{
55-
$task = $this->getTask($taskName);
56-
5755
$attempt = $task->getFirstAttempt();
5856

5957
if (!$attempt instanceof Attempt) {

src/CloudTasksApiContract.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ public function getRetryConfig(string $queueName): RetryConfig;
1313
public function createTask(string $queueName, Task $task): Task;
1414
public function deleteTask(string $taskName): void;
1515
public function getTask(string $taskName): Task;
16-
public function getRetryUntilTimestamp(string $taskName): ?int;
16+
public function getRetryUntilTimestamp(Task $task): ?int;
1717
}

src/CloudTasksApiFake.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function getTask(string $taskName): Task
4949
}
5050

5151

52-
public function getRetryUntilTimestamp(string $taskName): ?int
52+
public function getRetryUntilTimestamp(Task $task): ?int
5353
{
5454
return null;
5555
}

src/CloudTasksJob.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,31 @@ public function timeoutAt(): ?int
103103

104104
public function delete(): void
105105
{
106+
// Laravel automatically calls delete() after a job is processed successfully. However, this is
107+
// not what we want to happen in Cloud Tasks because Cloud Tasks will also delete the task upon
108+
// a 200 OK status, which means a task is deleted twice, possibly resulting in errors. So if the
109+
// task was processed successfully (no errors or failures) then we will not delete the task
110+
// manually and will let Cloud Tasks do it.
111+
$successful =
112+
// If the task has failed, we should be able to delete it permanently
113+
$this->hasFailed() === false
114+
// If the task has errored, it should be released, which in process deletes the errored task
115+
&& $this->hasError() === false;
116+
117+
if ($successful) {
118+
return;
119+
}
120+
106121
parent::delete();
107122

108123
$this->cloudTasksQueue->delete($this);
109124
}
110125

126+
public function hasError(): bool
127+
{
128+
return data_get($this->job, 'internal.errored') === true;
129+
}
130+
111131
public function release($delay = 0)
112132
{
113133
parent::release();

src/TaskHandler.php

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Stackkit\LaravelGoogleCloudTasksQueue;
44

5+
use Google\ApiCore\ApiException;
56
use Google\Cloud\Tasks\V2\CloudTasksClient;
67
use Google\Cloud\Tasks\V2\RetryConfig;
78
use Illuminate\Bus\Queueable;
@@ -122,6 +123,24 @@ private function handleTask(array $task): void
122123

123124
$this->loadQueueRetryConfig($job);
124125

126+
$taskName = request()->header('X-Cloudtasks-Taskname');
127+
$fullTaskName = $this->client->taskName(
128+
$this->config['project'],
129+
$this->config['location'],
130+
$job->getQueue() ?: $this->config['queue'],
131+
$taskName,
132+
);
133+
134+
try {
135+
$apiTask = CloudTasksApi::getTask($fullTaskName);
136+
} catch (ApiException $e) {
137+
if (in_array($e->getStatus(), ['NOT_FOUND', 'PRECONDITION_FAILED'])) {
138+
abort(404);
139+
}
140+
141+
throw $e;
142+
}
143+
125144
// If the task has a [X-CloudTasks-TaskRetryCount] header higher than 0, then
126145
// we know the job was created using an earlier version of the package. This
127146
// job does not have the attempts tracked internally yet.
@@ -138,20 +157,7 @@ private function handleTask(array $task): void
138157
// max retry duration has been set. If that duration
139158
// has passed, it should stop trying altogether.
140159
if ($job->attempts() > 0) {
141-
$taskName = request()->header('X-Cloudtasks-Taskname');
142-
143-
if (!is_string($taskName)) {
144-
throw new UnexpectedValueException('Expected task name to be a string.');
145-
}
146-
147-
$fullTaskName = $this->client->taskName(
148-
$this->config['project'],
149-
$this->config['location'],
150-
$job->getQueue() ?: $this->config['queue'],
151-
$taskName,
152-
);
153-
154-
$job->setRetryUntil(CloudTasksApi::getRetryUntilTimestamp($fullTaskName));
160+
$job->setRetryUntil(CloudTasksApi::getRetryUntilTimestamp($apiTask));
155161
}
156162

157163
$job->setAttempts($job->attempts() + 1);

tests/CloudTasksApiTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public function test_get_retry_until_timestamp()
184184
// The queue max retry duration is 5 seconds. The max retry until timestamp is calculated from the
185185
// first attempt, so we expect it to be [timestamp first attempt] + 5 seconds.
186186
$expected = $createdTask->getFirstAttempt()->getDispatchTime()->getSeconds() + 5;
187-
$actual = CloudTasksApi::getRetryUntilTimestamp($createdTask->getName());
187+
$actual = CloudTasksApi::getRetryUntilTimestamp($createdTask);
188188
$this->assertSame($expected, $actual);
189189
}
190190
}

tests/QueueTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public function jobs_can_be_released()
242242

243243
// Assert
244244
Event::assertNotDispatched($this->getJobReleasedAfterExceptionEvent());
245-
CloudTasksApi::assertDeletedTaskCount(1);
245+
CloudTasksApi::assertDeletedTaskCount(0); // it returned 200 OK so we dont delete it, but Google does
246246
$releasedJob = null;
247247
Event::assertDispatched(JobReleased::class, function (JobReleased $event) use (&$releasedJob) {
248248
$releasedJob = $event->job;
@@ -257,7 +257,7 @@ public function jobs_can_be_released()
257257

258258
$this->runFromPayload($releasedJob->getRawBody());
259259

260-
CloudTasksApi::assertDeletedTaskCount(2);
260+
CloudTasksApi::assertDeletedTaskCount(0);
261261
CloudTasksApi::assertTaskCreated(function (Task $task) {
262262
$body = $task->getHttpRequest()->getBody();
263263
$decoded = json_decode($body, true);
@@ -476,6 +476,6 @@ public function test_ignoring_jobs_with_deleted_models()
476476

477477
// Act
478478
Log::assertLogged('UserJob:John');
479-
CloudTasksApi::assertTaskDeleted($job->task->getName());
479+
CloudTasksApi::assertTaskNotDeleted($job->task->getName());
480480
}
481481
}

0 commit comments

Comments
 (0)