Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 73a6ed7

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

File tree

9 files changed

+49
-24
lines changed

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)

AltStyle によって変換されたページ (->オリジナル) /