Skip to content

3.x #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 43 commits into from
Oct 22, 2022
Merged

3.x #76

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ce16256
Update CHANGELOG.md
marickvantuil Jun 24, 2022
aeb3d7c
Update publish test to work with new Artisan command output
marickvantuil Jul 20, 2022
7b0f6ae
Merge pull request #61 from stackkit/bugfix/failing-test-new-artisan-…
marickvantuil Jul 20, 2022
1338a0b
Support encryption, avoid double __unserialize call
dshafik Jul 29, 2022
d5715db
Add test for encrypted jobs
marickvantuil Aug 13, 2022
39646cc
Merge pull request #62 from dshafik/patch-1
marickvantuil Aug 13, 2022
ea75521
Update CHANGELOG.md
marickvantuil Aug 13, 2022
89fba0d
Fix test
marickvantuil Aug 15, 2022
1c8ee02
Merge pull request #64 from stackkit/feature/fix-encrypt-test
marickvantuil Aug 15, 2022
e22e15b
Fix job dispatched before commit with afterCommit
marickvantuil Aug 27, 2022
2a85fd4
Add request validation to TaskHandler
marickvantuil Sep 2, 2022
7353af9
Add enqueueUsing fallback for Laravel 6x and 7x
marickvantuil Sep 2, 2022
13d3475
Fix validation assertions for older Laravel versions
marickvantuil Sep 2, 2022
bb6c876
Merge pull request #68 from stackkit/bugfix/dispatch-after-commit
marickvantuil Sep 2, 2022
36cecdc
Update CHANGELOG.md
marickvantuil Sep 2, 2022
1db3586
Respect after_commit when set through config
marickvantuil Sep 2, 2022
d54ba2e
Merge pull request #69 from stackkit/bugfix/dispatch-after-commit
marickvantuil Sep 2, 2022
8d6e8b2
Add initial draft of job releasing
marickvantuil Jul 23, 2022
8f41ea1
Track job attempts internally
marickvantuil Jul 24, 2022
eecf3f8
Prevent monitoring dashboard from creating multiple tasks
marickvantuil Sep 2, 2022
6932b21
Remove X-CloudTasks-TaskRetryCount usages
marickvantuil Sep 2, 2022
251b9d8
Update tests that fail jobs multiple times
marickvantuil Sep 10, 2022
a5f5843
Add fallback JobReleasedAfterException event
marickvantuil Sep 11, 2022
a3e2c55
Add JobReleased event and tests
marickvantuil Sep 11, 2022
728537d
Add initial version of job releasing in dashboard
marickvantuil Sep 11, 2022
2ab4fbf
Fix test
marickvantuil Sep 11, 2022
c387678
Add extra release delay test
marickvantuil Sep 11, 2022
8a19e95
Expand test suite
marickvantuil Sep 11, 2022
e45ba17
Test $deleteWhenMissingModels
marickvantuil Sep 16, 2022
281a077
Provide fallback for older style jobs and ensure their attempt number…
marickvantuil Sep 16, 2022
c3b98bd
Fix test
marickvantuil Sep 16, 2022
71a92fe
Run all tests in Github Actions
marickvantuil Sep 16, 2022
e3e01c6
Use delay on Laravel 7x and below, backoff on 8.x and up
marickvantuil Sep 16, 2022
71f6721
Skip unsupported exponential backoff on 7.x and below
marickvantuil Sep 16, 2022
90b68f6
Make dashboard build
marickvantuil Sep 30, 2022
069c30e
Merge pull request #70 from stackkit/feature/job-releasing
marickvantuil Sep 30, 2022
0e891dc
Update CHANGELOG.md
marickvantuil Oct 15, 2022
931f04f
#73 Handle jobs that are not CloudTaskJobs gracefully
Tarpsvo Oct 20, 2022
74442a6
Fix event job check
marickvantuil Oct 22, 2022
ed3dd75
Optimalization: get events dispatcher once
marickvantuil Oct 22, 2022
ade9282
Merge pull request #74 from Tarpsvo/master
marickvantuil Oct 22, 2022
b4f9e8e
Update CHANGELOG.md
marickvantuil Oct 22, 2022
b0fdb29
Merge pull request #75 from stackkit/feature/changelog
marickvantuil Oct 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,41 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 3.3.1 - 2022-10-22

**Fixed**

- Fixes [#73](https://github.com/stackkit/laravel-google-cloud-tasks-queue/issues/73) Cannot access protected property Illuminate\Queue\Jobs\SyncJob::$job

## 3.3.0 - 2022-10-15

**Added**

- Jobs can now be released back onto the queue.

## 3.2.1 - 2022-09-02

**Fixed**

- Jobs were dispatched before a DB commit if `after_commit` or `afterCommit()` was used. This has now been corrected.

**Added**

- Request validation for the TaskHandler endpoint.

## 3.2.0 - 2022-08-13

**Added**

- Added support for jobs that use the `Illuminate\Contracts\Queue\ShouldBeEncrypted` contract

## 3.1.4 - 2022-06-24

**Fixed**

- Fixed usage of incorrect header to set count retries ([#55](https://github.com/stackkit/laravel-google-cloud-tasks-queue/discussions/55))
- Fix getRetryUntilTimestamp not working due to incomplete task name ([#56](https://github.com/stackkit/laravel-google-cloud-tasks-queue/discussions/56))

## 3.1.3 - 2022-06-19

**Fixed**
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Please check the table below for supported Laravel and PHP versions:
// does not respond by this deadline then the request is cancelled and the attempt
// is marked as a DEADLINE_EXCEEDED failure.
'dispatch_deadline' => null,
'backoff' => 0,
],
```

Expand All @@ -79,13 +80,19 @@ Please check the table below on what the values mean and what their value should
</details>
<details>
<summary>
How it works
How it works & Differences
</summary>
<br>
Using Cloud Tasks as a Laravel queue driver is fundamentally different than other Laravel queue drivers, like Redis.

Typically a Laravel queue has a worker that listens to incoming jobs using the `queue:work` / `queue:listen` command.
With Cloud Tasks, this is not the case. Instead, Cloud Tasks will schedule the job for you and make an HTTP request to your application with the job payload. There is no need to run a `queue:work/listen` command.

#### Good to know

- The "Min backoff" and "Max backoff" options in Cloud Tasks are ignored. This is intentional: Laravel has its own backoff feature (which is more powerful than what Cloud Tasks offers) and therefore I have chosen that over the Cloud Tasks one.
- Similarly to the backoff feature, I have also chosen to let the package do job retries the 'Laravel way'. In Cloud Tasks, when a task throws an exception, Cloud Tasks will decide for itself when to retry the task (based on the backoff values). It will also manage its own state and knows how many times a task has been retried. This is different from Laravel. In typical Laravel queues, when a job throws an exception, the job is deleted and released back onto the queue. In order to support Laravel's backoff feature, this package must behave the same way about job retries.

</details>
<details>
<summary>Dashboard (beta)</summary>
Expand Down
18 changes: 18 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,23 @@
"Stackkit\\LaravelGoogleCloudTasksQueue\\CloudTasksServiceProvider"
]
}
},
"scripts": {
"l9": [
"composer require laravel/framework:9.* orchestra/testbench:7.* --no-interaction --no-update",
"composer update --prefer-stable --prefer-dist --no-interaction --no-suggest"
],
"l8": [
"composer require laravel/framework:8.* orchestra/testbench:6.* --no-interaction --no-update",
"composer update --prefer-stable --prefer-dist --no-interaction --no-suggest"
],
"l7": [
"composer require laravel/framework:7.* orchestra/testbench:5.* --no-interaction --no-update",
"composer update --prefer-stable --prefer-dist --no-interaction --no-suggest"
],
"l6": [
"composer require laravel/framework:6.* orchestra/testbench:4.* --no-interaction --no-update",
"composer update --prefer-stable --prefer-dist --no-interaction --no-suggest"
]
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file removed dashboard/dist/crossword.png
Binary file not shown.
Binary file removed dashboard/dist/dot-grid.png
Binary file not shown.
4 changes: 2 additions & 2 deletions dashboard/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script type="module" crossorigin src="/assets/index.5a46c6a0.js"></script>
<script type="module" crossorigin src="/assets/index.ea68d73f.js"></script>
<link rel="modulepreload" href="/assets/vendor.433de25e.js">
<link rel="stylesheet" href="/assets/index.1002db9a.css">
<link rel="stylesheet" href="/assets/index.d8eef428.css">
</head>
<body class="bg-gray-100">
<div id="app"></div>
Expand Down
4 changes: 2 additions & 2 deletions dashboard/dist/manifest.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"index.html": {
"file": "assets/index.5a46c6a0.js",
"file": "assets/index.ea68d73f.js",
"src": "index.html",
"isEntry": true,
"imports": [
"_vendor.433de25e.js"
],
"css": [
"assets/index.1002db9a.css"
"assets/index.d8eef428.css"
]
},
"_vendor.433de25e.js": {
Expand Down
Binary file removed dashboard/dist/pw_maze_white.png
Binary file not shown.
2 changes: 1 addition & 1 deletion dashboard/src/components/Status.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function ucfirst(input) {
.task-queued, .task-scheduled {
@apply bg-gray-100 text-gray-500
}
.task-running {
.task-running, .task-released {
@apply bg-blue-100 text-blue-800
}
</style>
8 changes: 8 additions & 0 deletions dashboard/src/components/Task.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const titles = {
successful: 'Successful',
error: 'An error occurred',
failed: 'Failed permanently',
released: 'Released',
}
</script>

Expand Down Expand Up @@ -60,6 +61,13 @@ const titles = {
Scheduled: {{ event['scheduled_at'] }} (UTC)
</span>
</div>
<div v-if="event['delay']">
<span
class="bg-gray-200 text-gray-800 text-xs font-medium mr-2 inline-block mb-1 px-1.5 py-0.5 rounded dark:bg-blue-200 dark:text-blue-800"
>
Delay: {{ event['delay'] }} seconds
</span>
</div>
</h3>
<Popper
:content="event.datetime"
Expand Down
5 changes: 1 addition & 4 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
stopOnFailure="false">
<testsuites>
<testsuite name="Testsuite">
<file>./tests/ConfigTest.php</file>
<file>./tests/TaskHandlerTest.php</file>
<file>./tests/CloudTasksApiTest.php</file>
<file>./tests/CloudTasksDashboardTest.php</file>
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<php>
Expand Down
5 changes: 5 additions & 0 deletions src/CloudTasksApiFake.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,9 @@ public function assertTaskCreated(Closure $closure): void

Assert::assertTrue($count > 0, 'Task was not created.');
}

public function assertCreatedTaskCount(int $count): void
{
Assert::assertCount($count, $this->createdTasks);
}
}
2 changes: 1 addition & 1 deletion src/CloudTasksConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ public function connect(array $config)
};
}

return new CloudTasksQueue($config, app(CloudTasksClient::class));
return new CloudTasksQueue($config, app(CloudTasksClient::class), $config['after_commit'] ?? null);
}
}
52 changes: 44 additions & 8 deletions src/CloudTasksJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
namespace Stackkit\LaravelGoogleCloudTasksQueue;

use Illuminate\Container\Container;
use Illuminate\Queue\Jobs\Job as LaravelJob;
use Illuminate\Contracts\Queue\Job as JobContract;
use Illuminate\Queue\Jobs\Job as LaravelJob;
use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased;
use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleasedAfterException;
use function Safe\json_encode;

class CloudTasksJob extends LaravelJob implements JobContract
{
private array $job;
private ?int $attempts;
/**
* The Cloud Tasks raw job payload (request payload).
*
* @var array
*/
public array $job;

private ?int $maxTries;
public ?int $retryUntil = null;

Expand All @@ -24,9 +31,14 @@ public function __construct(array $job, CloudTasksQueue $cloudTasksQueue)
$this->job = $job;
$this->container = Container::getInstance();
$this->cloudTasksQueue = $cloudTasksQueue;
/** @var \stdClass $command */
$command = unserialize($job['data']['command']);
$this->queue = $command->queue;

$command = TaskHandler::getCommandProperties($job['data']['command']);
$this->queue = $command['queue'] ?? config('queue.connections.' .config('queue.default') . '.queue');
}

public function job()
{
return $this->job;
}

public function getJobId(): string
Expand All @@ -46,12 +58,12 @@ public function getRawBody(): string

public function attempts(): ?int
{
return $this->attempts;
return $this->job['internal']['attempts'];
}

public function setAttempts(int $attempts): void
{
$this->attempts = $attempts;
$this->job['internal']['attempts'] = $attempts;
}

public function setMaxTries(int $maxTries): void
Expand Down Expand Up @@ -95,4 +107,28 @@ public function delete(): void

$this->cloudTasksQueue->delete($this);
}

public function release($delay = 0)
{
parent::release();

$this->cloudTasksQueue->release($this, $delay);

$properties = TaskHandler::getCommandProperties($this->job['data']['command']);
$connection = $properties['connection'] ?? config('queue.default');

// The package uses the JobReleasedAfterException provided by Laravel to grab
// the payload of the released job in tests to easily run and test a released
// job. Because the event is only accessible in Laravel 9.x, we create an
// identical event to hook into for Laravel versions older than 9.x
if (version_compare(app()->version(), '9.0.0', '<')) {
if (data_get($this->job, 'internal.errored')) {
app('events')->dispatch(new JobReleasedAfterException($connection, $this));
}
}

if (! data_get($this->job, 'internal.errored')) {
app('events')->dispatch(new JobReleased($connection, $this, $delay));
}
}
}
Loading