Skip to content

Commit c30151a

Browse files
committed
Make it possible to pass headers to task
1 parent ff0c7b1 commit c30151a

File tree

3 files changed

+180
-92
lines changed

3 files changed

+180
-92
lines changed

README.md

Lines changed: 123 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<p align="center">
2-
<img src="/assets/logo.png" width="400">
2+
<img src="/assets/logo.png" width="400">
33
</p>
44
<p align="center">
55
<img src="https://github.com/stackkit/laravel-google-cloud-tasks-queue/workflows/Run%20tests/badge.svg?branch=master" alt="Build Status">
@@ -12,59 +12,60 @@
1212
This package allows Google Cloud Tasks to be used as the queue driver.
1313

1414
<p align="center">
15-
<img src="/assets/cloud-tasks-home.png" width="100%">
15+
<img src="/assets/cloud-tasks-home.png" width="100%">
1616
</p>
1717

1818
<details>
19-
<summary>
20-
Requirements
21-
</summary>
19+
<summary>
20+
Requirements
21+
</summary>
2222

23-
<br>
24-
This package requires Laravel 10 or higher and supports MySQL 8 and PostgreSQL 15. Might support older database versions too, but package hasn't been tested for it.
23+
<br>
24+
This package requires Laravel 10 or higher and supports MySQL 8 and PostgreSQL 15. Might support older database versions too, but package hasn't been tested for it.
2525

26-
Please check the [Laravel support policy](https://laravel.com/docs/master/releases#support-policy) table for supported Laravel and PHP versions.
26+
Please check the [Laravel support policy](https://laravel.com/docs/master/releases#support-policy) table for supported
27+
Laravel and PHP versions.
2728
</details>
2829
<details>
29-
<summary>Installation</summary>
30-
<br>
31-
32-
Require the package using Composer
33-
34-
```console
35-
composer require stackkit/laravel-google-cloud-tasks-queue
36-
```
37-
38-
Publish the service provider:
39-
40-
```console
41-
php artisan vendor:publish --provider=cloud-tasks
42-
```
43-
44-
Add a new queue connection to `config/queue.php`
45-
46-
```php
47-
'cloudtasks' => [
48-
'driver' => 'cloudtasks',
49-
'project' => env('STACKKIT_CLOUD_TASKS_PROJECT', ''),
50-
'location' => env('STACKKIT_CLOUD_TASKS_LOCATION', ''),
51-
'queue' => env('STACKKIT_CLOUD_TASKS_QUEUE', 'default'),
52-
53-
// Required when using AppEngine
54-
'app_engine' => env('STACKKIT_APP_ENGINE_TASK', false),
55-
'app_engine_service' => env('STACKKIT_APP_ENGINE_SERVICE', ''),
56-
57-
// Required when not using AppEngine
58-
'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''),
59-
'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''),
60-
61-
// Optional: The deadline in seconds for requests sent to the worker. If the worker
62-
// does not respond by this deadline then the request is cancelled and the attempt
63-
// is marked as a DEADLINE_EXCEEDED failure.
64-
'dispatch_deadline' => null,
65-
'backoff' => 0,
66-
],
67-
```
30+
<summary>Installation</summary>
31+
<br>
32+
33+
Require the package using Composer
34+
35+
```console
36+
composer require stackkit/laravel-google-cloud-tasks-queue
37+
```
38+
39+
Publish the service provider:
40+
41+
```console
42+
php artisan vendor:publish --provider=cloud-tasks
43+
```
44+
45+
Add a new queue connection to `config/queue.php`
46+
47+
```php
48+
'cloudtasks' => [
49+
'driver' => 'cloudtasks',
50+
'project' => env('STACKKIT_CLOUD_TASKS_PROJECT', ''),
51+
'location' => env('STACKKIT_CLOUD_TASKS_LOCATION', ''),
52+
'queue' => env('STACKKIT_CLOUD_TASKS_QUEUE', 'default'),
53+
54+
// Required when using AppEngine
55+
'app_engine' => env('STACKKIT_APP_ENGINE_TASK', false),
56+
'app_engine_service' => env('STACKKIT_APP_ENGINE_SERVICE', ''),
57+
58+
// Required when not using AppEngine
59+
'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''),
60+
'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''),
61+
62+
// Optional: The deadline in seconds for requests sent to the worker. If the worker
63+
// does not respond by this deadline then the request is cancelled and the attempt
64+
// is marked as a DEADLINE_EXCEEDED failure.
65+
'dispatch_deadline' => null,
66+
'backoff' => 0,
67+
],
68+
```
6869

6970
If you are using separate services for dispatching and handling tasks, you may want to change the following settings:
7071

@@ -75,99 +76,131 @@ If you are using separate services for dispatching and handling tasks, you may w
7576
'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false),
7677
```
7778

78-
```dotenv
79-
QUEUE_CONNECTION=cloudtasks
80-
```
79+
```dotenv
80+
QUEUE_CONNECTION=cloudtasks
81+
```
8182

8283
Now that the package is installed, the final step is to set the correct environment variables.
8384

8485
Please check the table below on what the values mean and what their value should be.
8586

86-
| Environment variable | Description |Example
87-
---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|---
88-
| `STACKKIT_CLOUD_TASKS_PROJECT` | The project your queue belongs to. |`my-project`
89-
| `STACKKIT_CLOUD_TASKS_LOCATION` | The region where the project is hosted. |`europe-west6`
90-
| `STACKKIT_CLOUD_TASKS_QUEUE` | The default queue a job will be added to. |`emails`
91-
| **App Engine**
92-
| `STACKKIT_APP_ENGINE_TASK` (optional) | Set to true to use App Engine task (else a Http task will be used). Defaults to false. |`true`
93-
| `STACKKIT_APP_ENGINE_SERVICE` (optional) | The App Engine service to handle the task (only if using App Engine task). |`api`
94-
| **Non- App Engine apps**
95-
| `STACKKIT_CLOUD_TASKS_SERVICE_EMAIL` (optional) | The email address of the service account. Important, it should have the correct roles. See the section below which roles. |`[email protected]`
96-
| `STACKKIT_CLOUD_TASKS_HANDLER` (optional) | The URL that Cloud Tasks will call to process a job. This should be the URL to your Laravel app. By default we will use the URL that dispatched the job. |`https://<your website>.com`
87+
| Environment variable | Description | Example
88+
---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------
89+
| `STACKKIT_CLOUD_TASKS_PROJECT` | The project your queue belongs to. | `my-project`
90+
| `STACKKIT_CLOUD_TASKS_LOCATION` | The region where the project is hosted. | `europe-west6`
91+
| `STACKKIT_CLOUD_TASKS_QUEUE` | The default queue a job will be added to. | `emails`
92+
| **App Engine**
93+
| `STACKKIT_APP_ENGINE_TASK` (optional) | Set to true to use App Engine task (else a Http task will be used). Defaults to false. | `true`
94+
| `STACKKIT_APP_ENGINE_SERVICE` (optional) | The App Engine service to handle the task (only if using App Engine task). | `api`
95+
| **Non- App Engine apps**
96+
| `STACKKIT_CLOUD_TASKS_SERVICE_EMAIL` (optional) | The email address of the service account. Important, it should have the correct roles. See the section below which roles. | `[email protected]`
97+
| `STACKKIT_CLOUD_TASKS_HANDLER` (optional) | The URL that Cloud Tasks will call to process a job. This should be the URL to your Laravel app. By default we will use the URL that dispatched the job. | `https://<your website>.com`
98+
9799
</details>
100+
101+
### How to
102+
103+
#### Passing headers to a task
104+
105+
You can pass headers to a task by using the `withHeaders` method on the queue connection.
106+
107+
```php
108+
use Illuminate\Queue\Queue;
109+
110+
Queue::connection()->setTaskHeaders([
111+
'X-My-Header' => 'My-Value',
112+
]);
113+
```
114+
115+
If necessary, the current job being dispatched is also available:
116+
117+
```php
118+
use Illuminate\Queue\Queue;
119+
120+
Queue::connection()->setTaskHeaders(fn (array $job) => [
121+
'X-My-Header' => $job['displayName']
122+
]);
123+
```
124+
98125
<details>
99126
<summary>
100-
How it works & Differences
127+
How it works & Differences
101128
</summary>
102-
<br>
103-
Using Cloud Tasks as a Laravel queue driver is fundamentally different than other Laravel queue drivers, like Redis.
129+
<br>
130+
Using Cloud Tasks as a Laravel queue driver is fundamentally different than other Laravel queue drivers, like Redis.
104131

105132
Typically a Laravel queue has a worker that listens to incoming jobs using the `queue:work` / `queue:listen` command.
106-
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.
133+
With Cloud Tasks, this is not the case. Instead, Cloud Tasks will schedule the job for you and make an HTTP request to
134+
your application with the job payload. There is no need to run a `queue:work/listen` command.
107135

108136
#### Good to know
109137

110-
- Backoff, retries, max tries, retryUntil are all handled by Laravel. All these options are ignored in the Cloud Tasks configuration.
138+
- Backoff, retries, max tries, retryUntil are all handled by Laravel. All these options are ignored in the Cloud Tasks
139+
configuration.
111140

112141
</details>
113142
<details>
114-
<summary>Dashboard (beta)</summary>
115-
<br>
116-
The package comes with a beautiful dashboard that can be used to monitor all queued jobs.
143+
<summary>Dashboard (beta)</summary>
144+
<br>
145+
The package comes with a beautiful dashboard that can be used to monitor all queued jobs.
117146

118147

119-
<img src="/assets/dashboard.png" width="100%">
148+
<img src="/assets/dashboard.png" width="100%">
120149

121-
---
150+
---
122151

123152
_Experimental_
124153

125154
The dashboard works by storing all outgoing tasks in a database table. When Cloud Tasks calls the application and this
126155
package handles the task, we will automatically update the tasks' status, attempts
127156
and possible errors.
128157

129-
There is probably a (small) performance penalty because each task dispatch and handling does extra database read and writes.
158+
There is probably a (small) performance penalty because each task dispatch and handling does extra database read and
159+
writes.
130160
Also, the dashboard has not been tested with high throughput queues.
131161

132-
---
162+
---
133163

134164

135165
To make use of it, enable it through the `.env` file:
136166

137-
```dotenv
138-
STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED=true
139-
STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD=MySecretLoginPasswordPleaseChangeThis
140-
```
167+
```dotenv
168+
STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED=true
169+
STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD=MySecretLoginPasswordPleaseChangeThis
170+
```
141171

142172
Then publish its assets and migrations:
143173

144-
```console
145-
php artisan vendor:publish --tag=cloud-tasks
146-
php artisan migrate
147-
```
174+
```console
175+
php artisan vendor:publish --tag=cloud-tasks
176+
php artisan migrate
177+
```
148178

149179
The dashboard is accessible at the URI: /cloud-tasks
150180

151181
</details>
152182
<details>
153-
<summary>Authentication</summary>
154-
<br>
183+
<summary>Authentication</summary>
184+
<br>
155185

156186
Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable with a path to the credentials file.
157187

158188
More info: https://cloud.google.com/docs/authentication/production
159189

160-
If you're not using your master service account (which has all abilities), you must add the following roles to make it works:
190+
If you're not using your master service account (which has all abilities), you must add the following roles to make it
191+
works:
192+
161193
1. App Engine Viewer
162194
2. Cloud Tasks Enqueuer
163195
3. Cloud Tasks Viewer
164196
4. Cloud Tasks Task Deleter
165197
5. Service Account User
198+
166199
</details>
167200
<details>
168-
<summary>Security</summary>
169-
<br>
170-
The job handler requires each request to have an OpenID token. In the installation step we set the service account email, and with that service account, Cloud Tasks will generate an OpenID token and send it along with the job payload to the handler.
201+
<summary>Security</summary>
202+
<br>
203+
The job handler requires each request to have an OpenID token. In the installation step we set the service account email, and with that service account, Cloud Tasks will generate an OpenID token and send it along with the job payload to the handler.
171204

172205
This package verifies that the token is digitally signed by Google. Only Google Tasks will be able to call your handler.
173206

@@ -176,7 +209,7 @@ More information about OpenID Connect:
176209
https://developers.google.com/identity/protocols/oauth2/openid-connect
177210
</details>
178211
<details>
179-
<summary>Upgrading</summary>
180-
<br>
181-
Read [UPGRADING.MD](UPGRADING.md) on how to update versions.
212+
<summary>Upgrading</summary>
213+
<br>
214+
Read [UPGRADING.MD](UPGRADING.md) on how to update versions.
182215
</details>

src/CloudTasksQueue.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Stackkit\LaravelGoogleCloudTasksQueue;
66

7+
use Closure;
78
use Google\Cloud\Tasks\V2\AppEngineHttpRequest;
89
use Google\Cloud\Tasks\V2\AppEngineRouting;
910
use Google\Cloud\Tasks\V2\Client\CloudTasksClient;
@@ -15,7 +16,6 @@
1516
use Google\Protobuf\Timestamp;
1617
use Illuminate\Contracts\Queue\Queue as QueueContract;
1718
use Illuminate\Queue\Queue as LaravelQueue;
18-
use Illuminate\Support\Carbon;
1919
use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated;
2020

2121
use function Safe\json_decode;
@@ -24,6 +24,8 @@
2424

2525
class CloudTasksQueue extends LaravelQueue implements QueueContract
2626
{
27+
private Closure | array $headers = [];
28+
2729
public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false)
2830
{
2931
//
@@ -184,13 +186,16 @@ private function enrichPayloadWithInternalData(
184186

185187
public function addPayloadToTask(array $payload, Task $task): Task
186188
{
189+
$headers = value($this->headers, $payload) ?: [];
190+
187191
if (!empty($this->config['app_engine'])) {
188192
$path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH);
189193

190194
$appEngineRequest = new AppEngineHttpRequest();
191195
$appEngineRequest->setRelativeUri($path);
192196
$appEngineRequest->setHttpMethod(HttpMethod::POST);
193197
$appEngineRequest->setBody(json_encode($payload));
198+
$appEngineRequest->setHeaders($headers);
194199

195200
if (!empty($service = $this->config['app_engine_service'])) {
196201
$routing = new AppEngineRouting();
@@ -202,9 +207,9 @@ public function addPayloadToTask(array $payload, Task $task): Task
202207
} else {
203208
$httpRequest = new HttpRequest();
204209
$httpRequest->setUrl($this->getHandler());
205-
206210
$httpRequest->setBody(json_encode($payload));
207211
$httpRequest->setHttpMethod(HttpMethod::POST);
212+
$httpRequest->setHeaders($headers);
208213

209214
$token = new OidcToken;
210215
$token->setServiceAccountEmail($this->config['service_account_email']);
@@ -251,4 +256,9 @@ public function getHandler(): string
251256

252257
return $handler.'/'. config('cloud-tasks.uri');
253258
}
259+
260+
public function setTaskHeaders(Closure | array $headers): void
261+
{
262+
$this->headers = $headers;
263+
}
254264
}

0 commit comments

Comments
 (0)