From c1f2b2d61288b5737e8342e791efa7680fd4e72a Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Thu, 18 Jan 2024 21:55:27 +0100 Subject: [PATCH 01/46] Drop support for Laravel 6, 7, 8 and 9 --- .github/workflows/run-tests.yml | 11 ------- README.md | 2 +- composer.json | 18 +----------- src/CloudTasksJob.php | 11 ------- src/CloudTasksQueue.php | 33 --------------------- src/Events/JobReleasedAfterException.php | 37 ------------------------ src/TaskHandler.php | 6 ++-- tests/CloudTasksDashboardTest.php | 16 ++++------ tests/QueueTest.php | 28 +++++------------- tests/TaskHandlerTest.php | 34 +++++++--------------- tests/TestCase.php | 13 +-------- 11 files changed, 29 insertions(+), 180 deletions(-) delete mode 100644 src/Events/JobReleasedAfterException.php diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 404a31c..bf0c7a2 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -67,17 +67,6 @@ jobs: - { queue: 'github-actions-laravel10-php83', laravel: '10.*', php: '8.3', 'testbench': '8.*'} - { queue: 'github-actions-laravel10-php82', laravel: '10.*', php: '8.2', 'testbench': '8.*'} - { queue: 'github-actions-laravel10-php81', laravel: '10.*', php: '8.1', 'testbench': '8.*'} - - { queue: 'github-actions-laravel9-php83', laravel: '9.*', php: '8.3', 'testbench': '7.*'} - - { queue: 'github-actions-laravel9-php82', laravel: '9.*', php: '8.2', 'testbench': '7.*'} - - { queue: 'github-actions-laravel9-php81', laravel: '9.*', php: '8.1', 'testbench': '7.*'} - - { queue: 'github-actions-laravel9-php80', laravel: '9.*', php: '8.0', 'testbench': '7.*'} - - { queue: 'github-actions-laravel8-php81', laravel: '8.*', php: '8.1', 'testbench': '6.*'} - - { queue: 'github-actions-laravel8-php80', laravel: '8.*', php: '8.0', 'testbench': '6.*'} - - { queue: 'github-actions-laravel8-php74', laravel: '8.*', php: '7.4', 'testbench': '6.*'} - - { queue: 'github-actions-laravel7-php80', laravel: '7.*', php: '8.0', 'testbench': '5.*' } - - { queue: 'github-actions-laravel7-php74', laravel: '7.*', php: '7.4', 'testbench': '5.*' } - - { queue: 'github-actions-laravel6-php80', laravel: '6.*', php: '8.0', 'testbench': '4.*' } - - { queue: 'github-actions-laravel6-php74', laravel: '6.*', php: '7.4', 'testbench': '4.*' } name: PHP ${{ matrix.payload.php }} - Laravel ${{ matrix.payload.laravel }} - DB ${{ matrix.db }} diff --git a/README.md b/README.md index 2cf957b..af48a0d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ This package allows Google Cloud Tasks to be used as the queue driver.
- This package requires Laravel 6 or higher and supports MySQL 8 and PostgreSQL 14. Might support older database versions too, but package hasn't been tested for it. + 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. Please check the [Laravel support policy](https://laravel.com/docs/master/releases#support-policy) table for supported Laravel and PHP versions. diff --git a/composer.json b/composer.json index cf4f0ba..f4d259e 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "thecodingmachine/safe": "^1.0|^2.0" }, "require-dev": { - "orchestra/testbench": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "orchestra/testbench": "^8.0", "nunomaduro/larastan": "^1.0 || ^2.0", "thecodingmachine/phpstan-safe-rule": "^1.2", "laravel/legacy-factories": "^1.3" @@ -45,21 +45,5 @@ "composer require laravel/framework:10.* orchestra/testbench:8.* --no-interaction --no-update", "composer update --prefer-stable --prefer-dist --no-interaction" ], - "l9": [ - "composer require laravel/framework:9.* orchestra/testbench:7.* --no-interaction --no-update", - "composer update --prefer-stable --prefer-dist --no-interaction" - ], - "l8": [ - "composer require laravel/framework:8.* orchestra/testbench:6.* --no-interaction --no-update", - "composer update --prefer-stable --prefer-dist --no-interaction" - ], - "l7": [ - "composer require laravel/framework:7.* orchestra/testbench:5.* --no-interaction --no-update", - "composer update --prefer-stable --prefer-dist --no-interaction" - ], - "l6": [ - "composer require laravel/framework:6.* orchestra/testbench:4.* --no-interaction --no-update", - "composer update --prefer-stable --prefer-dist --no-interaction" - ] } } diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 9e804cf..3cd63bc 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -6,7 +6,6 @@ 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 @@ -137,16 +136,6 @@ public function release($delay = 0) $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)); } diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index ccb7798..be2249a 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -48,25 +48,6 @@ public function size($queue = null) return 0; } - /** - * Fallback method for Laravel 6x and 7x - * - * @param \Closure|string|object $job - * @param string $payload - * @param string $queue - * @param \DateTimeInterface|\DateInterval|int|null $delay - * @param callable $callback - * @return mixed - */ - protected function enqueueUsing($job, $payload, $queue, $delay, $callback) - { - if (method_exists(parent::class, 'enqueueUsing')) { - return parent::enqueueUsing($job, $payload, $queue, $delay, $callback); - } - - return $callback($payload, $queue, $delay); - } - /** * Push a new job onto the queue. * @@ -141,11 +122,6 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = json_decode($payload, true); - // Laravel 7+ jobs have a uuid, but Laravel 6 doesn't have it. - // Since we are using and expecting the uuid in some places - // we will add it manually here if it's not present yet. - $payload = $this->withUuid($payload); - // Since 3.x tasks are released back onto the queue after an exception has // been thrown. This means we lose the native [X-CloudTasks-TaskRetryCount] header // value and need to manually set and update the number of times a task has been attempted. @@ -202,15 +178,6 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) return $payload['uuid']; } - private function withUuid(array $payload): array - { - if (!isset($payload['uuid'])) { - $payload['uuid'] = (string)Str::uuid(); - } - - return $payload; - } - private function taskName(string $queueName, array $payload): string { $displayName = $this->sanitizeTaskName($payload['displayName']); diff --git a/src/Events/JobReleasedAfterException.php b/src/Events/JobReleasedAfterException.php deleted file mode 100644 index 603fbe3..0000000 --- a/src/Events/JobReleasedAfterException.php +++ /dev/null @@ -1,37 +0,0 @@ -job = $job; - $this->connectionName = $connectionName; - } -} diff --git a/src/TaskHandler.php b/src/TaskHandler.php index f8786ec..09b33f2 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -200,9 +200,9 @@ public function getWorkerOptions(): WorkerOptions { $options = new WorkerOptions(); - $prop = version_compare(app()->version(), '8.0.0', '<') ? 'delay' : 'backoff'; - - $options->$prop = $this->config['backoff'] ?? 0; + if (isset($this->config['backoff'])) { + $options->backoff = $this->config['backoff']; + } return $options; } diff --git a/tests/CloudTasksDashboardTest.php b/tests/CloudTasksDashboardTest.php index c8820c9..04e6dd3 100644 --- a/tests/CloudTasksDashboardTest.php +++ b/tests/CloudTasksDashboardTest.php @@ -527,17 +527,11 @@ public function test_publish() // Act & Assert $expectedPublishBase = dirname(__DIR__); - if (version_compare(app()->version(), '9.0.0', '>=')) { - $this->artisan('vendor:publish --tag=cloud-tasks --force') - ->expectsOutputToContain('Publishing [cloud-tasks] assets.') - ->expectsOutputToContain('Copying file [' . $expectedPublishBase . '/config/cloud-tasks.php] to [config/cloud-tasks.php]') - ->expectsOutputToContain('Copying directory [' . $expectedPublishBase . '/dashboard/dist] to [public/vendor/cloud-tasks]'); - } else { - $this->artisan('vendor:publish --tag=cloud-tasks --force') - ->expectsOutput('Copied File [' . $expectedPublishBase . '/config/cloud-tasks.php] To [/config/cloud-tasks.php]') - ->expectsOutput('Copied Directory [' . $expectedPublishBase . '/dashboard/dist] To [/public/vendor/cloud-tasks]') - ->expectsOutput('Publishing complete.'); - } + $this->artisan('vendor:publish --tag=cloud-tasks --force') + ->expectsOutputToContain('Publishing [cloud-tasks] assets.') + ->expectsOutputToContain('Copying file [' . $expectedPublishBase . '/config/cloud-tasks.php] to [config/cloud-tasks.php]') + ->expectsOutputToContain('Copying directory [' . $expectedPublishBase . '/dashboard/dist] to [public/vendor/cloud-tasks]'); + } /** diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 5338afe..c094f0a 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -10,6 +10,7 @@ use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; use Illuminate\Queue\Events\JobQueued; +use Illuminate\Queue\Events\JobReleasedAfterException; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; @@ -176,10 +177,6 @@ public function it_posts_the_task_the_correct_queue() */ public function it_can_dispatch_after_commit_inline() { - if (version_compare(app()->version(), '8.0.0', '<')) { - $this->markTestSkipped('Not supported by Laravel 7.x and below.'); - } - // Arrange CloudTasksApi::fake(); Event::fake(); @@ -202,10 +199,6 @@ public function it_can_dispatch_after_commit_inline() */ public function it_can_dispatch_after_commit_through_config() { - if (version_compare(app()->version(), '8.0.0', '<')) { - $this->markTestSkipped('Not supported by Laravel 7.x and below.'); - } - // Arrange CloudTasksApi::fake(); Event::fake(); @@ -233,7 +226,7 @@ public function jobs_can_be_released() CloudTasksApi::fake(); OpenIdVerificator::fake(); Event::fake([ - $this->getJobReleasedAfterExceptionEvent(), + JobReleasedAfterException::class, JobReleased::class, ]); @@ -241,7 +234,7 @@ public function jobs_can_be_released() $this->dispatch(new JobThatWillBeReleased())->run(); // Assert - Event::assertNotDispatched($this->getJobReleasedAfterExceptionEvent()); + Event::assertNotDispatched(JobReleasedAfterException::class); CloudTasksApi::assertDeletedTaskCount(0); // it returned 200 OK so we dont delete it, but Google does $releasedJob = null; Event::assertDispatched(JobReleased::class, function (JobReleased $event) use (&$releasedJob) { @@ -275,7 +268,7 @@ public function jobs_can_be_released_with_a_delay() CloudTasksApi::fake(); OpenIdVerificator::fake(); Event::fake([ - $this->getJobReleasedAfterExceptionEvent(), + JobReleasedAfterException::class, JobReleased::class, ]); Carbon::setTestNow(now()->addDay()); @@ -302,7 +295,7 @@ public function test_default_backoff() // Arrange CloudTasksApi::fake(); OpenIdVerificator::fake(); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); // Act $this->dispatch(new FailingJob())->run(); @@ -321,7 +314,7 @@ public function test_backoff_from_queue_config() $this->setConfigValue('backoff', 123); CloudTasksApi::fake(); OpenIdVerificator::fake(); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); // Act $this->dispatch(new FailingJob())->run(); @@ -340,12 +333,11 @@ public function test_backoff_from_job() Carbon::setTestNow(now()->addDay()); CloudTasksApi::fake(); OpenIdVerificator::fake(); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); // Act $failingJob = new FailingJob(); - $prop = version_compare(app()->version(), '8.0.0', '<') ? 'delay' : 'backoff'; - $failingJob->$prop = 123; + $failingJob->backoff = 123; $this->dispatch($failingJob)->run(); // Assert @@ -358,10 +350,6 @@ public function test_backoff_from_job() /** @test */ public function test_exponential_backoff_from_job_method() { - if (version_compare(app()->version(), '8.0.0', '<')) { - $this->markTestSkipped('Not supported by Laravel 7.x and below.'); - } - // Arrange Carbon::setTestNow(now()->addDay()); CloudTasksApi::fake(); diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 089ba4e..1c26ba5 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -8,6 +8,7 @@ use Google\Protobuf\Duration; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; +use Illuminate\Queue\Events\JobReleasedAfterException; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; @@ -328,9 +329,6 @@ public function test_unlimited_max_attempts() */ public function test_max_attempts_in_combination_with_retry_until() { - // Laravel 5, 6, 7: check both max_attempts and retry_until before failing a job. - // Laravel 8+: if retry_until, only check that - // Arrange OpenIdVerificator::fake(); CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( @@ -354,15 +352,7 @@ public function test_max_attempts_in_combination_with_retry_until() $releasedJob->run(); # Max attempts was reached - # Laravel 5, 6, 7: fail because max attempts was reached - # Laravel 8+: don't fail because retryUntil has not yet passed. - - if (version_compare(app()->version(), '8.0.0', '<')) { - $this->assertEquals('failed', $task->fresh()->status); - return; - } else { - $this->assertEquals('error', $task->fresh()->status); - } + $this->assertEquals('error', $task->fresh()->status); CloudTasksApi::shouldReceive('getRetryUntilTimestamp')->andReturn(time() - 1); $releasedJob->run(); @@ -375,10 +365,6 @@ public function test_max_attempts_in_combination_with_retry_until() */ public function it_can_handle_encrypted_jobs() { - if (version_compare(app()->version(), '8.0.0', '<')) { - $this->markTestSkipped('Not supported by Laravel 7.x and below.'); - } - // Arrange OpenIdVerificator::fake(); Log::swap(new LogFake()); @@ -406,7 +392,7 @@ public function failing_jobs_are_released() CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( (new RetryConfig())->setMaxAttempts(3) ); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); // Act $job = $this->dispatch(new FailingJob()); @@ -420,7 +406,7 @@ public function failing_jobs_are_released() CloudTasksApi::assertDeletedTaskCount(1); CloudTasksApi::assertCreatedTaskCount(2); CloudTasksApi::assertTaskDeleted($job->task->getName()); - Event::assertDispatched($this->getJobReleasedAfterExceptionEvent(), function ($event) { + Event::assertDispatched(JobReleasedAfterException::class, function ($event) { return $event->job->attempts() === 1; }); } @@ -432,21 +418,21 @@ public function attempts_are_tracked_internally() { // Arrange OpenIdVerificator::fake(); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); // Act & Assert $job = $this->dispatch(new FailingJob()); $job->run(); $releasedJob = null; - Event::assertDispatched($this->getJobReleasedAfterExceptionEvent(), function ($event) use (&$releasedJob) { + Event::assertDispatched(JobReleasedAfterException::class, function ($event) use (&$releasedJob) { $releasedJob = $event->job->getRawBody(); return $event->job->attempts() === 1; }); $this->runFromPayload($releasedJob); - Event::assertDispatched($this->getJobReleasedAfterExceptionEvent(), function ($event) { + Event::assertDispatched(JobReleasedAfterException::class, function ($event) { return $event->job->attempts() === 2; }); } @@ -458,14 +444,14 @@ public function attempts_are_copied_from_x_header() { // Arrange OpenIdVerificator::fake(); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); // Act & Assert $job = $this->dispatch(new FailingJob()); request()->headers->set('X-CloudTasks-TaskRetryCount', 6); $job->run(); - Event::assertDispatched($this->getJobReleasedAfterExceptionEvent(), function ($event) { + Event::assertDispatched(JobReleasedAfterException::class, function ($event) { return $event->job->attempts() === 7; }); } @@ -477,7 +463,7 @@ public function retried_jobs_get_a_new_name() { // Arrange OpenIdVerificator::fake(); - Event::fake($this->getJobReleasedAfterExceptionEvent()); + Event::fake(JobReleasedAfterException::class); CloudTasksApi::fake(); // Act & Assert diff --git a/tests/TestCase.php b/tests/TestCase.php index 048d6a9..28b1632 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -11,7 +11,6 @@ use Illuminate\Queue\Events\JobReleasedAfterException; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; -use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleasedAfterException as PackageJobReleasedAfterException; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; @@ -35,7 +34,7 @@ protected function setUp(): void $this->defaultHeaders['Authorization'] = 'Bearer ' . encrypt(time() + 10); Event::listen( - $this->getJobReleasedAfterExceptionEvent(), + JobReleasedAfterException::class, function ($event) { $this->releasedJobPayload = $event->job->getRawBody(); } @@ -247,16 +246,6 @@ protected function assertDatabaseCount($table, int $count, $connection = null) $this->assertEquals($count, DB::connection($connection)->table($table)->count()); } - public function getJobReleasedAfterExceptionEvent(): string - { - // The JobReleasedAfterException event is not available in Laravel versions - // below 9.x so instead for those versions we throw our own event which - // is identical to the Laravel one. - return version_compare(app()->version(), '9.0.0', '<') - ? PackageJobReleasedAfterException::class - : JobReleasedAfterException::class; - } - public function withTaskType(string $taskType): void { switch ($taskType) { From cb4bdc01694af451cb66d8fb1cd7daf04224947d Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 12 Feb 2024 22:05:46 +0100 Subject: [PATCH 02/46] Move $tries and retryUntil() to Laravel --- src/CloudTasksApi.php | 2 - src/CloudTasksApiConcrete.php | 39 -------- src/CloudTasksApiContract.php | 3 - src/CloudTasksApiFake.php | 17 ---- src/CloudTasksJob.php | 33 ------- src/TaskHandler.php | 37 -------- tests/CloudTasksApiTest.php | 61 ------------ tests/CloudTasksDashboardTest.php | 12 +-- tests/QueueTest.php | 9 +- tests/Support/FailingJob.php | 2 + .../FailingJobWithExponentialBackoff.php | 2 + tests/Support/FailingJobWithMaxTries.php | 8 ++ .../FailingJobWithMaxTriesAndRetryUntil.php | 15 +++ tests/Support/FailingJobWithRetryUntil.php | 13 +++ tests/Support/JobThatWillBeReleased.php | 2 + tests/Support/SimpleJob.php | 2 + tests/TaskHandlerTest.php | 95 ++++++------------- tests/TestCase.php | 2 +- 18 files changed, 81 insertions(+), 273 deletions(-) create mode 100644 tests/Support/FailingJobWithMaxTries.php create mode 100644 tests/Support/FailingJobWithMaxTriesAndRetryUntil.php create mode 100644 tests/Support/FailingJobWithRetryUntil.php diff --git a/src/CloudTasksApi.php b/src/CloudTasksApi.php index c113bf4..f18cc4e 100644 --- a/src/CloudTasksApi.php +++ b/src/CloudTasksApi.php @@ -9,11 +9,9 @@ use Illuminate\Support\Facades\Facade; /** - * @method static RetryConfig getRetryConfig(string $queueName) * @method static Task createTask(string $queueName, Task $task) * @method static void deleteTask(string $taskName) * @method static Task getTask(string $taskName) - * @method static int|null getRetryUntilTimestamp(Task $task) */ class CloudTasksApi extends Facade { diff --git a/src/CloudTasksApiConcrete.php b/src/CloudTasksApiConcrete.php index d63b8ed..8b3b1ab 100644 --- a/src/CloudTasksApiConcrete.php +++ b/src/CloudTasksApiConcrete.php @@ -4,10 +4,8 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Exception; use Google\Cloud\Tasks\V2\Attempt; use Google\Cloud\Tasks\V2\CloudTasksClient; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; use Google\Protobuf\Duration; use Google\Protobuf\Timestamp; @@ -24,17 +22,6 @@ public function __construct(CloudTasksClient $client) $this->client = $client; } - public function getRetryConfig(string $queueName): RetryConfig - { - $retryConfig = $this->client->getQueue($queueName)->getRetryConfig(); - - if (! $retryConfig instanceof RetryConfig) { - throw new Exception('Queue does not have a retry config.'); - } - - return $retryConfig; - } - public function createTask(string $queueName, Task $task): Task { return $this->client->createTask($queueName, $task); @@ -49,30 +36,4 @@ public function getTask(string $taskName): Task { return $this->client->getTask($taskName); } - - public function getRetryUntilTimestamp(Task $task): ?int - { - $attempt = $task->getFirstAttempt(); - - if (!$attempt instanceof Attempt) { - return null; - } - - $queueName = implode('/', array_slice(explode('/', $task->getName()), 0, 6)); - - $retryConfig = $this->getRetryConfig($queueName); - - $maxRetryDuration = $retryConfig->getMaxRetryDuration(); - $dispatchTime = $attempt->getDispatchTime(); - - if (! $maxRetryDuration instanceof Duration || ! $dispatchTime instanceof Timestamp) { - return null; - } - - $maxDurationInSeconds = (int) $maxRetryDuration->getSeconds(); - - $firstAttemptTimestamp = $dispatchTime->toDateTime()->getTimestamp(); - - return $firstAttemptTimestamp + $maxDurationInSeconds; - } } diff --git a/src/CloudTasksApiContract.php b/src/CloudTasksApiContract.php index aa0880b..6eab9bc 100644 --- a/src/CloudTasksApiContract.php +++ b/src/CloudTasksApiContract.php @@ -4,14 +4,11 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; interface CloudTasksApiContract { - public function getRetryConfig(string $queueName): RetryConfig; public function createTask(string $queueName, Task $task): Task; public function deleteTask(string $taskName): void; public function getTask(string $taskName): Task; - public function getRetryUntilTimestamp(Task $task): ?int; } diff --git a/src/CloudTasksApiFake.php b/src/CloudTasksApiFake.php index f1af5da..6c3cb58 100644 --- a/src/CloudTasksApiFake.php +++ b/src/CloudTasksApiFake.php @@ -17,17 +17,6 @@ class CloudTasksApiFake implements CloudTasksApiContract public array $createdTasks = []; public array $deletedTasks = []; - public function getRetryConfig(string $queueName): RetryConfig - { - $retryConfig = new RetryConfig(); - - $retryConfig - ->setMinBackoff((new Duration(['seconds' => 0]))) - ->setMaxBackoff((new Duration(['seconds' => 0]))); - - return $retryConfig; - } - public function createTask(string $queueName, Task $task): Task { $this->createdTasks[] = compact('queueName', 'task'); @@ -46,12 +35,6 @@ public function getTask(string $taskName): Task ->setName($taskName); } - - public function getRetryUntilTimestamp(Task $task): ?int - { - return null; - } - public function assertTaskDeleted(string $taskName): void { Assert::assertTrue( diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 3cd63bc..5953bf7 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -17,9 +17,6 @@ class CloudTasksJob extends LaravelJob implements JobContract */ public array $job; - private ?int $maxTries; - public ?int $retryUntil = null; - /** * @var CloudTasksQueue */ @@ -65,41 +62,11 @@ public function setAttempts(int $attempts): void $this->job['internal']['attempts'] = $attempts; } - public function setMaxTries(int $maxTries): void - { - if ($maxTries === -1) { - $maxTries = 0; - } - - $this->maxTries = $maxTries; - } - - public function maxTries(): ?int - { - return $this->maxTries; - } - public function setQueue(string $queue): void { $this->queue = $queue; } - public function setRetryUntil(?int $retryUntil): void - { - $this->retryUntil = $retryUntil; - } - - public function retryUntil(): ?int - { - return $this->retryUntil; - } - - // timeoutAt was renamed to retryUntil in 8.x but we still support this. - public function timeoutAt(): ?int - { - return $this->retryUntil; - } - public function delete(): void { // Laravel automatically calls delete() after a job is processed successfully. However, this is diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 09b33f2..4e9866f 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -4,7 +4,6 @@ use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\CloudTasksClient; -use Google\Cloud\Tasks\V2\RetryConfig; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Queue\WorkerOptions; use Illuminate\Support\Str; @@ -12,7 +11,6 @@ use Safe\Exceptions\JsonException; use UnexpectedValueException; use stdClass; - use function Safe\json_decode; class TaskHandler @@ -32,11 +30,6 @@ class TaskHandler */ private $queue; - /** - * @var RetryConfig - */ - private $retryConfig = null; - public function __construct(CloudTasksClient $client) { $this->client = $client; @@ -128,8 +121,6 @@ private function handleTask(array $task): void { $job = new CloudTasksJob($task, $this->queue); - $this->loadQueueRetryConfig($job); - $fullTaskName = $this->client->taskName( $this->config['project'], $this->config['location'], @@ -147,39 +138,11 @@ private function handleTask(array $task): void throw $e; } - // If the task has a [X-CloudTasks-TaskRetryCount] header higher than 0, then - // we know the job was created using an earlier version of the package. This - // job does not have the attempts tracked internally yet. - $taskRetryCountHeader = request()->header('X-CloudTasks-TaskRetryCount') ?? request()->header('X-AppEngine-TaskRetryCount'); - if ($taskRetryCountHeader && (int)$taskRetryCountHeader > 0) { - $job->setAttempts((int)$taskRetryCountHeader); - } else { - $job->setAttempts($task['internal']['attempts']); - } - - $job->setMaxTries($this->retryConfig->getMaxAttempts()); - - // If the job is being attempted again we also check if a - // max retry duration has been set. If that duration - // has passed, it should stop trying altogether. - if ($job->attempts() > 0) { - $job->setRetryUntil(CloudTasksApi::getRetryUntilTimestamp($apiTask)); - } - $job->setAttempts($job->attempts() + 1); app('queue.worker')->process($this->config['connection'], $job, $this->getWorkerOptions()); } - private function loadQueueRetryConfig(CloudTasksJob $job): void - { - $queue = $job->getQueue() ?: $this->config['queue']; - - $queueName = $this->client->queueName($this->config['project'], $this->config['location'], $queue); - - $this->retryConfig = CloudTasksApi::getRetryConfig($queueName); - } - public static function getCommandProperties(string $command): array { if (Str::startsWith($command, 'O:')) { diff --git a/tests/CloudTasksApiTest.php b/tests/CloudTasksApiTest.php index 5b5a1c2..e8769e5 100644 --- a/tests/CloudTasksApiTest.php +++ b/tests/CloudTasksApiTest.php @@ -8,7 +8,6 @@ use Google\Cloud\Tasks\V2\CloudTasksClient; use Google\Cloud\Tasks\V2\HttpMethod; use Google\Cloud\Tasks\V2\HttpRequest; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; use Google\Protobuf\Timestamp; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; @@ -42,26 +41,6 @@ protected function setUp(): void } - /** - * @test - */ - public function test_get_retry_config() - { - // Act - $retryConfig = CloudTasksApi::getRetryConfig( - $this->client->queueName( - env('CI_CLOUD_TASKS_PROJECT_ID'), - env('CI_CLOUD_TASKS_LOCATION'), - env('CI_CLOUD_TASKS_QUEUE') - ) - ); - - // Assert - $this->assertInstanceOf(RetryConfig::class, $retryConfig); - $this->assertEquals(2, $retryConfig->getMaxAttempts()); - $this->assertEquals(5, $retryConfig->getMaxRetryDuration()->getSeconds()); - } - /** * @test */ @@ -147,44 +126,4 @@ public function test_delete_task() $this->expectExceptionMessage('NOT_FOUND'); CloudTasksApi::getTask($task->getName()); } - - /** - * @test - */ - public function test_get_retry_until_timestamp() - { - // Arrange - $httpRequest = new HttpRequest(); - $httpRequest->setHttpMethod(HttpMethod::GET); - $httpRequest->setUrl('https://httpstat.us/500'); - - $cloudTask = new Task(); - $cloudTask->setHttpRequest($httpRequest); - - $createdTask = CloudTasksApi::createTask( - $this->client->queueName( - env('CI_CLOUD_TASKS_PROJECT_ID'), - env('CI_CLOUD_TASKS_LOCATION'), - env('CI_CLOUD_TASKS_CUSTOM_QUEUE', env('CI_CLOUD_TASKS_QUEUE')) - ), - $cloudTask, - ); - - $secondsSlept = 0; - while ($createdTask->getFirstAttempt() === null) { - $createdTask = CloudTasksApi::getTask($createdTask->getName()); - sleep(1); - $secondsSlept += 1; - - if ($secondsSlept >= 180) { - $this->fail('Task took too long to get executed.'); - } - } - - // The queue max retry duration is 5 seconds. The max retry until timestamp is calculated from the - // first attempt, so we expect it to be [timestamp first attempt] + 5 seconds. - $expected = $createdTask->getFirstAttempt()->getDispatchTime()->getSeconds() + 5; - $actual = CloudTasksApi::getRetryUntilTimestamp($createdTask); - $this->assertSame($expected, $actual); - } } diff --git a/tests/CloudTasksDashboardTest.php b/tests/CloudTasksDashboardTest.php index 04e6dd3..b29e0bc 100644 --- a/tests/CloudTasksDashboardTest.php +++ b/tests/CloudTasksDashboardTest.php @@ -10,6 +10,7 @@ use Stackkit\LaravelGoogleCloudTasksQueue\OpenIdVerificator; use Stackkit\LaravelGoogleCloudTasksQueue\StackkitCloudTask; use Tests\Support\FailingJob; +use Tests\Support\FailingJobWithMaxTries; use Tests\Support\JobThatWillBeReleased; use Tests\Support\SimpleJob; @@ -421,11 +422,8 @@ public function when_a_job_fails_it_will_be_updated_in_the_dashboard(array $test \Illuminate\Support\Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(3) - ); - $job = $this->dispatch(new FailingJob()); + $job = $this->dispatch(new FailingJobWithMaxTries()); $releasedJob = $job->runAndGetReleasedJob(); $releasedJob = $releasedJob->runAndGetReleasedJob(); $releasedJob->run(); @@ -458,9 +456,6 @@ public function when_a_job_is_released_it_will_be_updated_in_the_dashboard(array \Illuminate\Support\Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(3) - ); $this->dispatch(new JobThatWillBeReleased())->run(); @@ -494,9 +489,6 @@ public function job_release_delay_is_added_to_the_metadata(array $test) \Illuminate\Support\Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(3) - ); $this->dispatch(new JobThatWillBeReleased(15))->run(); diff --git a/tests/QueueTest.php b/tests/QueueTest.php index c094f0a..bcf4062 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -381,15 +381,14 @@ public function test_failing_method_on_job() { // Arrange CloudTasksApi::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(1) - ); - OpenIdVerificator::fake(); Log::swap(new LogFake()); // Act - $this->dispatch(new FailingJob())->run(); + $this->dispatch(new FailingJob()) + ->runAndGetReleasedJob() + ->runAndGetReleasedJob() + ->runAndGetReleasedJob(); // Assert Log::assertLogged('FailingJob:failed'); diff --git a/tests/Support/FailingJob.php b/tests/Support/FailingJob.php index 5fbbffc..3fad0d3 100644 --- a/tests/Support/FailingJob.php +++ b/tests/Support/FailingJob.php @@ -12,6 +12,8 @@ class FailingJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public $tries = 3; + /** * Create a new job instance. * diff --git a/tests/Support/FailingJobWithExponentialBackoff.php b/tests/Support/FailingJobWithExponentialBackoff.php index aec644d..7d19f8d 100644 --- a/tests/Support/FailingJobWithExponentialBackoff.php +++ b/tests/Support/FailingJobWithExponentialBackoff.php @@ -12,6 +12,8 @@ class FailingJobWithExponentialBackoff implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public $tries = 5; + public function handle() { throw new \Error('simulating a failing job'); diff --git a/tests/Support/FailingJobWithMaxTries.php b/tests/Support/FailingJobWithMaxTries.php new file mode 100644 index 0000000..bd950df --- /dev/null +++ b/tests/Support/FailingJobWithMaxTries.php @@ -0,0 +1,8 @@ +addMinutes(5); + } +} diff --git a/tests/Support/FailingJobWithRetryUntil.php b/tests/Support/FailingJobWithRetryUntil.php new file mode 100644 index 0000000..74b1027 --- /dev/null +++ b/tests/Support/FailingJobWithRetryUntil.php @@ -0,0 +1,13 @@ +addMinutes(5); + } +} diff --git a/tests/Support/JobThatWillBeReleased.php b/tests/Support/JobThatWillBeReleased.php index bbd2d98..a2b7d61 100644 --- a/tests/Support/JobThatWillBeReleased.php +++ b/tests/Support/JobThatWillBeReleased.php @@ -14,6 +14,8 @@ class JobThatWillBeReleased implements ShouldQueue private int $releaseDelay; + public $tries = 3; + /** * Create a new job instance. * diff --git a/tests/Support/SimpleJob.php b/tests/Support/SimpleJob.php index 34e1912..5eae133 100644 --- a/tests/Support/SimpleJob.php +++ b/tests/Support/SimpleJob.php @@ -13,6 +13,8 @@ class SimpleJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public $tries = 3; + /** * Create a new job instance. * diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 1c26ba5..900dfb4 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -20,6 +20,9 @@ use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; use Tests\Support\EncryptedJob; use Tests\Support\FailingJob; +use Tests\Support\FailingJobWithMaxTries; +use Tests\Support\FailingJobWithMaxTriesAndRetryUntil; +use Tests\Support\FailingJobWithRetryUntil; use Tests\Support\SimpleJob; use UnexpectedValueException; @@ -222,10 +225,7 @@ public function after_max_attempts_it_will_log_to_failed_table() { // Arrange OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(3) - ); - $job = $this->dispatch(new FailingJob()); + $job = $this->dispatch(new FailingJobWithMaxTries()); // Act & Assert $this->assertDatabaseCount('failed_jobs', 0); @@ -248,10 +248,6 @@ public function after_max_attempts_it_will_delete_the_task() // Arrange OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(3) - ); - $job = $this->dispatch(new FailingJob()); // Act & Assert @@ -273,16 +269,18 @@ public function after_max_attempts_it_will_delete_the_task() /** * @test + * + * @testWith [{"now": "2020-01-01 00:00:00", "try_at": "2020-01-01 00:00:00", "should_fail": false}] + * [{"now": "2020-01-01 00:00:00", "try_at": "2020-01-01 00:04:59", "should_fail": false}] + * [{"now": "2020-01-01 00:00:00", "try_at": "2020-01-01 00:05:00", "should_fail": true}] */ - public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the_task() + public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the_task(array $args) { // Arrange + $this->travelTo($args['now']); + OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxRetryDuration(new Duration(['seconds' => 30])) - ); - CloudTasksApi::partialMock()->shouldReceive('getRetryUntilTimestamp')->andReturn(1); - $job = $this->dispatch(new FailingJob()); + $job = $this->dispatch(new FailingJobWithRetryUntil()); // Act $releasedJob = $job->runAndGetReleasedJob(); @@ -293,13 +291,11 @@ public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the $this->assertDatabaseCount('failed_jobs', 0); // Act - CloudTasksApi::partialMock()->shouldReceive('getRetryUntilTimestamp')->andReturn(1); + $this->travelTo($args['try_at']); $releasedJob->run(); // Assert - CloudTasksApi::assertDeletedTaskCount(2); - CloudTasksApi::assertTaskDeleted($job->task->getName()); - $this->assertDatabaseCount('failed_jobs', 1); + $this->assertDatabaseCount('failed_jobs', $args['should_fail'] ? 1 : 0); } /** @@ -309,10 +305,6 @@ public function test_unlimited_max_attempts() { // Arrange OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - // -1 is a valid option in Cloud Tasks to indicate there is no max. - (new RetryConfig())->setMaxAttempts(-1) - ); // Act $job = $this->dispatch(new FailingJob()); @@ -331,33 +323,28 @@ public function test_max_attempts_in_combination_with_retry_until() { // Arrange OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig()) - ->setMaxAttempts(3) - ->setMaxRetryDuration(new Duration(['seconds' => 3])) - ); - CloudTasksApi::partialMock()->shouldReceive('getRetryUntilTimestamp')->andReturn(time() + 10)->byDefault(); - $job = $this->dispatch(new FailingJob()); + $this->travelTo('2020-01-01 00:00:00'); - // Act & Assert - $releasedJob = $job->runAndGetReleasedJob(); - $releasedJob = $releasedJob->runAndGetReleasedJob(); + $job = $this->dispatch(new FailingJobWithMaxTriesAndRetryUntil()); - # After 2 attempts both Laravel versions should report the same: 2 errors and 0 failures. - $task = StackkitCloudTask::whereTaskUuid($job->payloadAsArray('uuid'))->firstOrFail(); - $this->assertEquals(2, $task->getNumberOfAttempts()); - $this->assertEquals('error', $task->status); + // When retryUntil is specified, the maxAttempts is ignored. - $releasedJob->run(); - - # Max attempts was reached - $this->assertEquals('error', $task->fresh()->status); + // Act & Assert - CloudTasksApi::shouldReceive('getRetryUntilTimestamp')->andReturn(time() - 1); - $releasedJob->run(); + // The max attempts is 3, but the retryUntil is set to 5 minutes from now. + // So when we attempt the job 10 times, it should still not fail. + foreach (range(1, 10) as $attempt) { + $job = $job->runAndGetReleasedJob(); + CloudTasksApi::assertDeletedTaskCount($attempt); + CloudTasksApi::assertTaskDeleted($job->task->getName()); + $this->assertDatabaseCount('failed_jobs', 0); + } - $this->assertEquals('failed', $task->fresh()->status); + // Now we travel to 5 minutes from now, and the job should fail. + $this->travelTo('2020-01-01 00:05:00'); + $job->run(); + $this->assertDatabaseCount('failed_jobs', 1); } /** @@ -389,9 +376,6 @@ public function failing_jobs_are_released() { // Arrange OpenIdVerificator::fake(); - CloudTasksApi::partialMock()->shouldReceive('getRetryConfig')->andReturn( - (new RetryConfig())->setMaxAttempts(3) - ); Event::fake(JobReleasedAfterException::class); // Act @@ -437,25 +421,6 @@ public function attempts_are_tracked_internally() }); } - /** - * @test - */ - public function attempts_are_copied_from_x_header() - { - // Arrange - OpenIdVerificator::fake(); - Event::fake(JobReleasedAfterException::class); - - // Act & Assert - $job = $this->dispatch(new FailingJob()); - request()->headers->set('X-CloudTasks-TaskRetryCount', 6); - $job->run(); - - Event::assertDispatched(JobReleasedAfterException::class, function ($event) { - return $event->job->attempts() === 7; - }); - } - /** * @test */ diff --git a/tests/TestCase.php b/tests/TestCase.php index 28b1632..bdd1733 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -19,7 +19,7 @@ class TestCase extends \Orchestra\Testbench\TestCase use DatabaseTransactions; /** - * @var \Mockery\Mock|CloudTasksClient $client + * @var CloudTasksClient $client */ public $client; From 8dceed7c81801fc6174ef45aa497318f8b863598 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 12 Feb 2024 22:25:07 +0100 Subject: [PATCH 03/46] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index af48a0d..b69f11e 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,7 @@ With Cloud Tasks, this is not the case. Instead, Cloud Tasks will schedule the j #### 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. +- Backoff, retries, max tries, retryUntil are all handled by Laravel. All these options are ignored in the Cloud Tasks configuration.
From 1f05570079cf2c6aa75a8dae1db2eaecaae360f5 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 12 Feb 2024 22:51:22 +0100 Subject: [PATCH 04/46] Install Laravel Pint --- composer.json | 3 ++- config/cloud-tasks.php | 2 +- factories/StackkitCloudTaskFactory.php | 2 +- src/CloudTasks.php | 9 ++----- src/CloudTasksApi.php | 1 - src/CloudTasksApiConcrete.php | 5 +--- src/CloudTasksApiContract.php | 2 ++ src/CloudTasksApiController.php | 22 +++++++-------- src/CloudTasksApiFake.php | 9 +++---- src/CloudTasksJob.php | 7 +++-- src/CloudTasksQueue.php | 34 +++++++++++------------ src/CloudTasksServiceProvider.php | 23 ++++++++-------- src/Config.php | 37 +++++++++++--------------- src/DashboardService.php | 3 ++- src/Entities/StatRow.php | 2 ++ src/Events/JobReleased.php | 9 ------- src/Events/TaskCreated.php | 1 + src/LogFake.php | 7 +++-- src/OpenIdVerificatorConcrete.php | 2 +- src/OpenIdVerificatorFake.php | 4 +-- src/StackkitCloudTask.php | 13 +++++---- src/TaskHandler.php | 6 ++--- tests/CloudTasksApiTest.php | 6 ++--- tests/CloudTasksDashboardTest.php | 27 +++++++++---------- tests/QueueTest.php | 10 ++++--- tests/Support/EncryptedJob.php | 2 +- tests/Support/SimpleJob.php | 1 - tests/Support/UserJob.php | 3 +-- tests/TaskHandlerTest.php | 9 ++++--- tests/TestCase.php | 32 +++++++++++----------- 30 files changed, 139 insertions(+), 154 deletions(-) diff --git a/composer.json b/composer.json index 1eec0a3..dfb337b 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "orchestra/testbench": "^8.0", "nunomaduro/larastan": "^1.0 || ^2.0", "thecodingmachine/phpstan-safe-rule": "^1.2", - "laravel/legacy-factories": "^1.3" + "laravel/legacy-factories": "^1.3", + "laravel/pint": "^1.13" }, "autoload": { "psr-4": { diff --git a/config/cloud-tasks.php b/config/cloud-tasks.php index c8cbdca..1885df2 100644 --- a/config/cloud-tasks.php +++ b/config/cloud-tasks.php @@ -5,6 +5,6 @@ return [ 'dashboard' => [ 'enabled' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED', false), - 'password' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD', 'MyPassword1!') + 'password' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD', 'MyPassword1!'), ], ]; diff --git a/factories/StackkitCloudTaskFactory.php b/factories/StackkitCloudTaskFactory.php index ac0991e..926ce94 100644 --- a/factories/StackkitCloudTaskFactory.php +++ b/factories/StackkitCloudTaskFactory.php @@ -6,9 +6,9 @@ /** @var \Illuminate\Database\Eloquent\Factory $factory */ +use Faker\Generator as Faker; use Illuminate\Support\Str; use Stackkit\LaravelGoogleCloudTasksQueue\StackkitCloudTask; -use Faker\Generator as Faker; $factory->define(StackkitCloudTask::class, function (Faker $faker) { return [ diff --git a/src/CloudTasks.php b/src/CloudTasks.php index b9ca554..70d512d 100644 --- a/src/CloudTasks.php +++ b/src/CloudTasks.php @@ -3,7 +3,6 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Carbon\Carbon; -use Closure; use Throwable; final class CloudTasks @@ -18,7 +17,7 @@ public static function check($request) { $token = $request->bearerToken(); - if (!$token) { + if (! $token) { return false; } @@ -27,14 +26,12 @@ public static function check($request) return $expireTimestamp > Carbon::now()->timestamp; } catch (Throwable $e) { - return false; + return false; } } /** * Determine if the dashboard is enabled. - * - * @return bool */ public static function dashboardEnabled(): bool { @@ -43,8 +40,6 @@ public static function dashboardEnabled(): bool /** * Determine if the dashboard is disabled. - * - * @return bool */ public static function dashboardDisabled(): bool { diff --git a/src/CloudTasksApi.php b/src/CloudTasksApi.php index f18cc4e..e0c04a2 100644 --- a/src/CloudTasksApi.php +++ b/src/CloudTasksApi.php @@ -4,7 +4,6 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; use Illuminate\Support\Facades\Facade; diff --git a/src/CloudTasksApiConcrete.php b/src/CloudTasksApiConcrete.php index 8b3b1ab..4e09517 100644 --- a/src/CloudTasksApiConcrete.php +++ b/src/CloudTasksApiConcrete.php @@ -4,16 +4,13 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\Cloud\Tasks\V2\Attempt; use Google\Cloud\Tasks\V2\CloudTasksClient; use Google\Cloud\Tasks\V2\Task; -use Google\Protobuf\Duration; -use Google\Protobuf\Timestamp; class CloudTasksApiConcrete implements CloudTasksApiContract { /** - * @var CloudTasksClient $client + * @var CloudTasksClient */ private $client; diff --git a/src/CloudTasksApiContract.php b/src/CloudTasksApiContract.php index 6eab9bc..8e8aca3 100644 --- a/src/CloudTasksApiContract.php +++ b/src/CloudTasksApiContract.php @@ -9,6 +9,8 @@ interface CloudTasksApiContract { public function createTask(string $queueName, Task $task): Task; + public function deleteTask(string $taskName): void; + public function getTask(string $taskName): Task; } diff --git a/src/CloudTasksApiController.php b/src/CloudTasksApiController.php index 1d3a771..7726b7a 100644 --- a/src/CloudTasksApiController.php +++ b/src/CloudTasksApiController.php @@ -2,13 +2,14 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; +use const STR_PAD_LEFT; + use Exception; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Stackkit\LaravelGoogleCloudTasksQueue\Entities\StatRow; -use const STR_PAD_LEFT; class CloudTasksApiController { @@ -16,13 +17,13 @@ public function login(): ?string { $password = config('cloud-tasks.dashboard.password'); - if (!is_string($password)) { + if (! is_string($password)) { return null; } $validPassword = hash_equals($password, request('password')); - if (!$validPassword) { + if (! $validPassword) { return null; } @@ -31,9 +32,9 @@ public function login(): ?string public function dashboard(): array { - $dbDriver = config('database.connections.' . config('database.default') . '.driver'); + $dbDriver = config('database.connections.'.config('database.default').'.driver'); - if (!in_array($dbDriver, ['mysql', 'pgsql'])) { + if (! in_array($dbDriver, ['mysql', 'pgsql'])) { throw new Exception('Unsupported database driver for Cloud Tasks dashboard.'); } @@ -59,12 +60,12 @@ public function dashboard(): array DB::raw('CASE WHEN status = \'failed\' THEN 1 ELSE 0 END AS failed'), DB::raw(' CASE - WHEN ' . $groupBy['this_minute'] . ' = \'' . now()->utc()->format('H:i') . '\' THEN \'this_minute\' - WHEN ' . $groupBy['this_hour'] . ' = \'' . now()->utc()->format('H') . '\' THEN \'this_hour\' + WHEN '.$groupBy['this_minute'].' = \''.now()->utc()->format('H:i').'\' THEN \'this_minute\' + WHEN '.$groupBy['this_hour'].' = \''.now()->utc()->format('H').'\' THEN \'this_hour\' ELSE \'today\' END AS time_preset - ') + '), ] ) ->groupBy( @@ -74,7 +75,7 @@ public function dashboard(): array ] ) ->get() - ->map(fn($row) => StatRow::createFromObject($row)) + ->map(fn ($row) => StatRow::createFromObject($row)) ->toArray(); $response = [ @@ -156,8 +157,7 @@ public function tasks() $maxId = $tasks->max('id'); - return $tasks->map(function (StackkitCloudTask $task) use ($maxId) - { + return $tasks->map(function (StackkitCloudTask $task) use ($maxId) { return [ 'uuid' => $task->task_uuid, 'id' => str_pad((string) $task->id, strlen($maxId), '0', STR_PAD_LEFT), diff --git a/src/CloudTasksApiFake.php b/src/CloudTasksApiFake.php index 6c3cb58..1614efe 100644 --- a/src/CloudTasksApiFake.php +++ b/src/CloudTasksApiFake.php @@ -5,16 +5,13 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Closure; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; -use Google\Protobuf\Duration; -use Illuminate\Support\Arr; -use Illuminate\Support\Str; use PHPUnit\Framework\Assert; class CloudTasksApiFake implements CloudTasksApiContract { public array $createdTasks = []; + public array $deletedTasks = []; public function createTask(string $queueName, Task $task): Task @@ -39,7 +36,7 @@ public function assertTaskDeleted(string $taskName): void { Assert::assertTrue( in_array($taskName, $this->deletedTasks), - 'The task [' . $taskName . '] should have been deleted but it is not.' + 'The task ['.$taskName.'] should have been deleted but it is not.' ); } @@ -47,7 +44,7 @@ public function assertTaskNotDeleted(string $taskName): void { Assert::assertTrue( ! in_array($taskName, $this->deletedTasks), - 'The task [' . $taskName . '] should not have been deleted but it was.' + 'The task ['.$taskName.'] should not have been deleted but it was.' ); } diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 5953bf7..77eb862 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -6,14 +6,13 @@ use Illuminate\Contracts\Queue\Job as JobContract; use Illuminate\Queue\Jobs\Job as LaravelJob; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; + use function Safe\json_encode; class CloudTasksJob extends LaravelJob implements JobContract { /** * The Cloud Tasks raw job payload (request payload). - * - * @var array */ public array $job; @@ -27,9 +26,9 @@ public function __construct(array $job, CloudTasksQueue $cloudTasksQueue) $this->job = $job; $this->container = Container::getInstance(); $this->cloudTasksQueue = $cloudTasksQueue; - + $command = TaskHandler::getCommandProperties($job['data']['command']); - $this->queue = $command['queue'] ?? config('queue.connections.' .config('queue.default') . '.queue'); + $this->queue = $command['queue'] ?? config('queue.connections.'.config('queue.default').'.queue'); } public function job() diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index be2249a..c5da5e5 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -14,7 +14,6 @@ use Illuminate\Contracts\Queue\Queue as QueueContract; use Illuminate\Queue\Queue as LaravelQueue; use Illuminate\Support\Carbon; -use Illuminate\Support\Str; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; use function Safe\json_decode; @@ -39,7 +38,7 @@ public function __construct(array $config, CloudTasksClient $client, $dispatchAf /** * Get the size of the queue. * - * @param string|null $queue + * @param string|null $queue * @return int */ public function size($queue = null) @@ -51,9 +50,9 @@ public function size($queue = null) /** * Push a new job onto the queue. * - * @param string|object $job - * @param mixed $data - * @param string|null $queue + * @param string|object $job + * @param mixed $data + * @param string|null $queue * @return void */ public function push($job, $data = '', $queue = null) @@ -72,9 +71,8 @@ function ($payload, $queue) { /** * Push a raw payload onto the queue. * - * @param string $payload - * @param string|null $queue - * @param array $options + * @param string $payload + * @param string|null $queue * @return string */ public function pushRaw($payload, $queue = null, array $options = []) @@ -87,10 +85,10 @@ public function pushRaw($payload, $queue = null, array $options = []) /** * Push a new job onto the queue after a delay. * - * @param \DateTimeInterface|\DateInterval|int $delay - * @param string|object $job - * @param mixed $data - * @param string|null $queue + * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|object $job + * @param mixed $data + * @param string|null $queue * @return void */ public function later($delay, $job, $data = '', $queue = null) @@ -109,9 +107,9 @@ function ($payload, $queue, $delay) { /** * Push a job to Cloud Tasks. * - * @param string|null $queue - * @param string $payload - * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|null $queue + * @param string $payload + * @param \DateTimeInterface|\DateInterval|int $delay * @return string */ protected function pushToCloudTasks($queue, $payload, $delay = 0) @@ -163,7 +161,7 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) // The deadline for requests sent to the app. If the app does not respond by // this deadline then the request is cancelled and the attempt is marked as // a failure. Cloud Tasks will retry the task according to the RetryConfig. - if (!empty($this->config['dispatch_deadline'])) { + if (! empty($this->config['dispatch_deadline'])) { $task->setDispatchDeadline(new Duration(['seconds' => $this->config['dispatch_deadline']])); } @@ -186,7 +184,7 @@ private function taskName(string $queueName, array $payload): string $this->config['project'], $this->config['location'], $queueName, - $displayName . '-' . $payload['uuid'] . '-' . Carbon::now()->getTimeStampMs(), + $displayName.'-'.$payload['uuid'].'-'.Carbon::now()->getTimeStampMs(), ); } @@ -203,7 +201,7 @@ private function sanitizeTaskName(string $taskName) private function withAttempts(array $payload): array { - if (!isset($payload['internal']['attempts'])) { + if (! isset($payload['internal']['attempts'])) { $payload['internal']['attempts'] = 0; } diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index d22a281..66f8dfb 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -10,6 +10,7 @@ use Illuminate\Support\ServiceProvider as LaravelServiceProvider; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; + use function Safe\file_get_contents; use function Safe\json_decode; @@ -52,10 +53,10 @@ private function registerConnector(): void private function registerConfig(): void { $this->publishes([ - __DIR__ . '/../config/cloud-tasks.php' => config_path('cloud-tasks.php'), + __DIR__.'/../config/cloud-tasks.php' => config_path('cloud-tasks.php'), ], ['cloud-tasks']); - $this->mergeConfigFrom(__DIR__ . '/../config/cloud-tasks.php', 'cloud-tasks'); + $this->mergeConfigFrom(__DIR__.'/../config/cloud-tasks.php', 'cloud-tasks'); } private function registerViews(): void @@ -65,7 +66,7 @@ private function registerViews(): void // return; } - $this->loadViewsFrom(__DIR__ . '/../views', 'cloud-tasks'); + $this->loadViewsFrom(__DIR__.'/../views', 'cloud-tasks'); } private function registerAssets(): void @@ -75,7 +76,7 @@ private function registerAssets(): void } $this->publishes([ - __DIR__ . '/../dashboard/dist' => public_path('vendor/cloud-tasks'), + __DIR__.'/../dashboard/dist' => public_path('vendor/cloud-tasks'), ], ['cloud-tasks']); } @@ -86,7 +87,7 @@ private function registerMigrations(): void } $this->loadMigrationsFrom([ - __DIR__ . '/../migrations', + __DIR__.'/../migrations', ]); } @@ -139,7 +140,7 @@ private function registerDashboard(): void }); $events->listen(JobFailed::class, function (JobFailed $event) { - if (!$event->job instanceof CloudTasksJob) { + if (! $event->job instanceof CloudTasksJob) { return; } @@ -152,7 +153,7 @@ private function registerDashboard(): void }); $events->listen(JobProcessing::class, function (JobProcessing $event) { - if (!$event->job instanceof CloudTasksJob) { + if (! $event->job instanceof CloudTasksJob) { return; } @@ -162,7 +163,7 @@ private function registerDashboard(): void }); $events->listen(JobProcessed::class, function (JobProcessed $event) { - if (!$event->job instanceof CloudTasksJob) { + if (! $event->job instanceof CloudTasksJob) { return; } @@ -174,7 +175,7 @@ private function registerDashboard(): void }); $events->listen(JobExceptionOccurred::class, function (JobExceptionOccurred $event) { - if (!$event->job instanceof CloudTasksJob) { + if (! $event->job instanceof CloudTasksJob) { return; } @@ -186,7 +187,7 @@ private function registerDashboard(): void }); $events->listen(JobFailed::class, function ($event) { - if (!$event->job instanceof CloudTasksJob) { + if (! $event->job instanceof CloudTasksJob) { return; } @@ -196,7 +197,7 @@ private function registerDashboard(): void }); $events->listen(JobReleased::class, function (JobReleased $event) { - if (!$event->job instanceof CloudTasksJob) { + if (! $event->job instanceof CloudTasksJob) { return; } diff --git a/src/Config.php b/src/Config.php index 9819d6e..f481348 100644 --- a/src/Config.php +++ b/src/Config.php @@ -10,7 +10,7 @@ class Config { /** - * @param Closure|string $handler + * @param Closure|string $handler */ public static function getHandler($handler): string { @@ -27,48 +27,43 @@ public static function getHandler($handler): string // (still) set to localhost. That will never work because Cloud Tasks // should always call a public address / hostname to process tasks. if (in_array($parse['host'], ['localhost', '127.0.0.1', '::1'])) { - throw new Exception( - sprintf( - 'Unable to push task to Cloud Tasks because the handler URL is set to a local host: %s. ' . - 'This does not work because Google is not able to call the given local URL. ' . - 'If you are developing on locally, consider using Ngrok or Expose for Laravel to expose your local ' . - 'application to the internet.', - $handler - ) - ); + throw new Exception(sprintf( + 'Unable to push task to Cloud Tasks because the handler URL is set to a local host: %s. '. + 'This does not work because Google is not able to call the given local URL. '. + 'If you are developing on locally, consider using Ngrok or Expose for Laravel to expose your local '. + 'application to the internet.', + $handler + )); } // When the application is running behind a proxy and the TrustedProxy middleware has not been set up yet, // an error like [HttpRequest.url must start with 'https'] could be thrown. Since the handler URL must // always be https, we will provide a little extra information on how to fix this. if ($parse['scheme'] !== 'https') { - throw new Exception( - sprintf( - 'Unable to push task to Cloud Tasks because the hander URL is not https. Google Cloud Tasks ' . - 'will only call safe (https) URLs. If you are running Laravel behind a proxy (e.g. Ngrok, Expose), make sure it is ' . - 'as a trusted proxy. To quickly fix this, add the following to the [app/Http/Middleware/TrustProxies] middleware: ' . - 'protected $proxies = \'*\';' - ) - ); + throw new Exception(sprintf( + 'Unable to push task to Cloud Tasks because the hander URL is not https. Google Cloud Tasks '. + 'will only call safe (https) URLs. If you are running Laravel behind a proxy (e.g. Ngrok, Expose), make sure it is '. + 'as a trusted proxy. To quickly fix this, add the following to the [app/Http/Middleware/TrustProxies] middleware: '. + 'protected $proxies = \'*\';' + )); } $trimmedHandlerUrl = rtrim($handler, '/'); - if (!str_ends_with($trimmedHandlerUrl, '/handle-task')) { + if (! str_ends_with($trimmedHandlerUrl, '/handle-task')) { return "$trimmedHandlerUrl/handle-task"; } return $trimmedHandlerUrl; } catch (UrlException $e) { throw new Exception( - 'Unable to push task to Cloud Tasks because the task handler URL (' . $handler . ') is ' . + 'Unable to push task to Cloud Tasks because the task handler URL ('.$handler.') is '. 'malformed. Please inspect the URL closely for any mistakes.' ); } } /** - * @param array $config * @return string|null The audience as an hash or null if not needed */ public static function getAudience(array $config): ?string diff --git a/src/DashboardService.php b/src/DashboardService.php index 4dc5cec..7ae32da 100644 --- a/src/DashboardService.php +++ b/src/DashboardService.php @@ -10,6 +10,7 @@ use Illuminate\Queue\Events\JobFailed; use Illuminate\Support\Facades\DB; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; + use function Safe\json_decode; class DashboardService @@ -61,7 +62,7 @@ public function add(string $queue, Task $task): void 'task_uuid' => $uuid, 'name' => $this->getTaskName($task), 'queue' => $queue, - 'payload' => $this->getTaskBody($task), + 'payload' => $this->getTaskBody($task), 'status' => $status, 'metadata' => $metadata->toJson(), 'created_at' => now()->utc(), diff --git a/src/Entities/StatRow.php b/src/Entities/StatRow.php index a92d18a..244c7c9 100644 --- a/src/Entities/StatRow.php +++ b/src/Entities/StatRow.php @@ -5,7 +5,9 @@ class StatRow { public int $count; + public int $failed; + public string $time_preset; public static function createFromObject(object $row): StatRow diff --git a/src/Events/JobReleased.php b/src/Events/JobReleased.php index 614e45b..530f1e8 100644 --- a/src/Events/JobReleased.php +++ b/src/Events/JobReleased.php @@ -10,31 +10,22 @@ class JobReleased { /** * The connection name. - * - * @var string */ public string $connectionName; /** * The job instance. - * - * @var Job */ public Job $job; /** * The job delay in seconds. - * - * @var int */ public int $delay; /** * Create a new event instance. * - * @param string $connectionName - * @param Job $job - * @param int $delay * @return void */ public function __construct(string $connectionName, Job $job, int $delay = 0) diff --git a/src/Events/TaskCreated.php b/src/Events/TaskCreated.php index a05f415..9ab76aa 100644 --- a/src/Events/TaskCreated.php +++ b/src/Events/TaskCreated.php @@ -9,6 +9,7 @@ class TaskCreated { public string $queue; + public Task $task; public function task(Task $task): self diff --git a/src/LogFake.php b/src/LogFake.php index e4e86ff..c9a3476 100644 --- a/src/LogFake.php +++ b/src/LogFake.php @@ -5,7 +5,6 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use PHPUnit\Framework\Assert as PHPUnit; -use Psr\Log\LoggerInterface; class LogFake { @@ -52,7 +51,7 @@ public function debug(string $message, array $context = []): void } /** - * @param string $level + * @param string $level */ public function log($level, string $message, array $context = []): void { @@ -66,14 +65,14 @@ public function channel(): self public function assertLogged(string $message): void { - PHPUnit::assertTrue(in_array($message, $this->loggedMessages), 'The message [' . $message . '] was not logged.'); + PHPUnit::assertTrue(in_array($message, $this->loggedMessages), 'The message ['.$message.'] was not logged.'); } public function assertNotLogged(string $message): void { PHPUnit::assertTrue( ! in_array($message, $this->loggedMessages), - 'The message [' . $message . '] was logged.' + 'The message ['.$message.'] was logged.' ); } } diff --git a/src/OpenIdVerificatorConcrete.php b/src/OpenIdVerificatorConcrete.php index a3c1c4a..8e5541c 100644 --- a/src/OpenIdVerificatorConcrete.php +++ b/src/OpenIdVerificatorConcrete.php @@ -11,7 +11,7 @@ class OpenIdVerificatorConcrete extends Facade { public function verify(?string $token, array $config): void { - if (!$token) { + if (! $token) { throw new CloudTasksException('Missing [Authorization] header'); } diff --git a/src/OpenIdVerificatorFake.php b/src/OpenIdVerificatorFake.php index 79cedb6..5666e76 100644 --- a/src/OpenIdVerificatorFake.php +++ b/src/OpenIdVerificatorFake.php @@ -10,7 +10,7 @@ class OpenIdVerificatorFake { public function verify(?string $token, array $config): void { - if (!$token) { + if (! $token) { return; } @@ -19,7 +19,7 @@ public function verify(?string $token, array $config): void [ 'audience' => Config::getAudience($config), 'throwException' => true, - 'certsLocation' => __DIR__ . '/../tests/Support/self-signed-public-key-as-jwk.json', + 'certsLocation' => __DIR__.'/../tests/Support/self-signed-public-key-as-jwk.json', ] ); } diff --git a/src/StackkitCloudTask.php b/src/StackkitCloudTask.php index 4af02f1..87277d1 100644 --- a/src/StackkitCloudTask.php +++ b/src/StackkitCloudTask.php @@ -2,13 +2,15 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; +use const JSON_PRETTY_PRINT; + use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Carbon; -use const JSON_PRETTY_PRINT; -use function Safe\json_encode; + use function Safe\json_decode; +use function Safe\json_encode; /** * @property int $id @@ -31,7 +33,7 @@ public static function findByUuid(string $uuid): StackkitCloudTask } /** - * @param Builder $builder + * @param Builder $builder * @return Builder */ public function scopeNewestFirst(Builder $builder): Builder @@ -40,7 +42,7 @@ public function scopeNewestFirst(Builder $builder): Builder } /** - * @param Builder $builder + * @param Builder $builder * @return Builder */ public function scopeFailed(Builder $builder): Builder @@ -69,7 +71,7 @@ public function getNumberOfAttempts(): int } /** - * @param mixed $value + * @param mixed $value */ public function setMetadata(string $key, $value): void { @@ -101,6 +103,7 @@ public function getEvents(): array return collect($events)->map(function ($event) { /** @var array $event */ $event['diff'] = Carbon::parse($event['datetime'])->diffForHumans(); + return $event; })->toArray(); } diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 4e9866f..0280fc1 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -49,8 +49,8 @@ public function handle(?string $task = null): void } /** - * @param string|array|null $task - * @return array + * @param string|array|null $task + * * @throws JsonException */ private function captureTask($task): array @@ -89,7 +89,7 @@ private function loadQueueConnectionConfiguration(array $task): void { $command = self::getCommandProperties($task['data']['command']); $connection = $command['connection'] ?? config('queue.default'); - $baseConfig = config('queue.connections.' . $connection); + $baseConfig = config('queue.connections.'.$connection); $config = (new CloudTasksConnector())->connect($baseConfig)->config; // The connection name from the config may not be the actual connection name diff --git a/tests/CloudTasksApiTest.php b/tests/CloudTasksApiTest.php index e8769e5..e78c275 100644 --- a/tests/CloudTasksApiTest.php +++ b/tests/CloudTasksApiTest.php @@ -27,8 +27,8 @@ protected function setUp(): void ]; foreach ($requiredEnvs as $env) { - if (!env($env)) { - $this->fail('Missing [' . $env . '] environment variable.'); + if (! env($env)) { + $this->fail('Missing ['.$env.'] environment variable.'); } } @@ -67,7 +67,7 @@ public function test_create_task() // Assert $this->assertMatchesRegularExpression( - '/projects\/' . env('CI_CLOUD_TASKS_PROJECT_ID') . '\/locations\/' . env('CI_CLOUD_TASKS_LOCATION') . '\/queues\/' . env('CI_CLOUD_TASKS_QUEUE') . '\/tasks\/\d+$/', + '/projects\/'.env('CI_CLOUD_TASKS_PROJECT_ID').'\/locations\/'.env('CI_CLOUD_TASKS_LOCATION').'\/queues\/'.env('CI_CLOUD_TASKS_QUEUE').'\/tasks\/\d+$/', $taskName ); } diff --git a/tests/CloudTasksDashboardTest.php b/tests/CloudTasksDashboardTest.php index b29e0bc..2fbef76 100644 --- a/tests/CloudTasksDashboardTest.php +++ b/tests/CloudTasksDashboardTest.php @@ -2,7 +2,6 @@ namespace Tests; -use Google\Cloud\Tasks\V2\RetryConfig; use Illuminate\Routing\Route; use Illuminate\Routing\Router; use Illuminate\Support\Carbon; @@ -120,10 +119,10 @@ public function it_can_filter_only_failed_tasks() public function it_can_filter_tasks_created_at_exact_time() { // Arrange - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(15,4, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16,5, 0)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16,5, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16,6, 0)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(15, 4, 59)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 5, 0)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 5, 59)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 6, 0)]); // Act $response = $this->getJson('/cloud-tasks-api/tasks?time=16:05'); @@ -138,9 +137,9 @@ public function it_can_filter_tasks_created_at_exact_time() public function it_can_filter_tasks_created_at_exact_hour() { // Arrange - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(15,59, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16,5, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16,32, 32)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(15, 59, 59)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 5, 59)]); + factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 32, 32)]); // Act $response = $this->getJson('/cloud-tasks-api/tasks?hour=16'); @@ -229,7 +228,7 @@ public function it_returns_info_about_a_specific_task() $task = factory(StackkitCloudTask::class)->create(); // Act - $response = $this->getJson('/cloud-tasks-api/task/' . $task->task_uuid); + $response = $this->getJson('/cloud-tasks-api/task/'.$task->task_uuid); // Assert $this->assertEquals($task->id, $response['id']); @@ -521,8 +520,8 @@ public function test_publish() $this->artisan('vendor:publish --tag=cloud-tasks --force') ->expectsOutputToContain('Publishing [cloud-tasks] assets.') - ->expectsOutputToContain('Copying file [' . $expectedPublishBase . '/config/cloud-tasks.php] to [config/cloud-tasks.php]') - ->expectsOutputToContain('Copying directory [' . $expectedPublishBase . '/dashboard/dist] to [public/vendor/cloud-tasks]'); + ->expectsOutputToContain('Copying file ['.$expectedPublishBase.'/config/cloud-tasks.php] to [config/cloud-tasks.php]') + ->expectsOutputToContain('Copying directory ['.$expectedPublishBase.'/dashboard/dist] to [public/vendor/cloud-tasks]'); } @@ -547,7 +546,7 @@ public function when_dashboard_is_enabled_it_adds_the_necessary_routes() */ public function when_dashboard_is_enabled_it_adds_the_necessary_migrations() { - $this->assertTrue(in_array(dirname(__DIR__) . '/src/../migrations', app('migrator')->paths())); + $this->assertTrue(in_array(dirname(__DIR__).'/src/../migrations', app('migrator')->paths())); } /** @@ -595,7 +594,7 @@ public function dashboard_is_password_protected() public function can_enter_with_token() { // Arrange - $this->defaultHeaders['Authorization'] = 'Bearer ' . encrypt(time() + 10); + $this->defaultHeaders['Authorization'] = 'Bearer '.encrypt(time() + 10); // Act $response = $this->getJson('/cloud-tasks-api/dashboard'); @@ -610,7 +609,7 @@ public function can_enter_with_token() public function token_can_expire() { // Arrange - $this->defaultHeaders['Authorization'] = 'Bearer ' . encrypt(Carbon::create(2020, 5, 15, 15, 15, 15)->timestamp); + $this->defaultHeaders['Authorization'] = 'Bearer '.encrypt(Carbon::create(2020, 5, 15, 15, 15, 15)->timestamp); // Act & Assert Carbon::setTestNow(Carbon::create(2020, 5, 15, 15, 15, 14)); diff --git a/tests/QueueTest.php b/tests/QueueTest.php index bcf4062..e459991 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -5,7 +5,6 @@ namespace Tests; use Google\Cloud\Tasks\V2\HttpMethod; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; @@ -239,11 +238,13 @@ public function jobs_can_be_released() $releasedJob = null; Event::assertDispatched(JobReleased::class, function (JobReleased $event) use (&$releasedJob) { $releasedJob = $event->job; + return true; }); CloudTasksApi::assertTaskCreated(function (Task $task) { $body = $task->getHttpRequest()->getBody(); $decoded = json_decode($body, true); + return $decoded['data']['commandName'] === 'Tests\\Support\\JobThatWillBeReleased' && $decoded['internal']['attempts'] === 1; }); @@ -254,6 +255,7 @@ public function jobs_can_be_released() CloudTasksApi::assertTaskCreated(function (Task $task) { $body = $task->getHttpRequest()->getBody(); $decoded = json_decode($body, true); + return $decoded['data']['commandName'] === 'Tests\\Support\\JobThatWillBeReleased' && $decoded['internal']['attempts'] === 2; }); @@ -404,10 +406,10 @@ public function test_queue_before_and_after_hooks() // Act Queue::before(function (JobProcessing $event) { - logger('Queue::before:' . $event->job->payload()['data']['commandName']); + logger('Queue::before:'.$event->job->payload()['data']['commandName']); }); Queue::after(function (JobProcessed $event) { - logger('Queue::after:' . $event->job->payload()['data']['commandName']); + logger('Queue::after:'.$event->job->payload()['data']['commandName']); }); $this->dispatch(new SimpleJob())->run(); @@ -482,7 +484,7 @@ public function it_adds_a_task_name_based_on_the_display_name() CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool { $uuid = \Safe\json_decode($task->getHttpRequest()->getBody(), true)['uuid']; - return $task->getName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/Tests-Support-SimpleJob-' . $uuid . '-1685649757000'; + return $task->getName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/Tests-Support-SimpleJob-'.$uuid.'-1685649757000'; }); } } diff --git a/tests/Support/EncryptedJob.php b/tests/Support/EncryptedJob.php index 8f8e4ff..f1d7d18 100644 --- a/tests/Support/EncryptedJob.php +++ b/tests/Support/EncryptedJob.php @@ -9,7 +9,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -class EncryptedJob implements ShouldQueue, ShouldBeEncrypted +class EncryptedJob implements ShouldBeEncrypted, ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; diff --git a/tests/Support/SimpleJob.php b/tests/Support/SimpleJob.php index 5eae133..1a1f6d0 100644 --- a/tests/Support/SimpleJob.php +++ b/tests/Support/SimpleJob.php @@ -7,7 +7,6 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\Mail; class SimpleJob implements ShouldQueue { diff --git a/tests/Support/UserJob.php b/tests/Support/UserJob.php index de586e5..e6ed197 100644 --- a/tests/Support/UserJob.php +++ b/tests/Support/UserJob.php @@ -7,7 +7,6 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\Mail; class UserJob implements ShouldQueue { @@ -29,6 +28,6 @@ public function __construct(User $user) */ public function handle() { - logger('UserJob:' . $this->user->name); + logger('UserJob:'.$this->user->name); } } diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 900dfb4..8f2ba3f 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -3,9 +3,7 @@ namespace Tests; use Firebase\JWT\ExpiredException; -use Google\Cloud\Tasks\V2\RetryConfig; use Google\Cloud\Tasks\V2\Task; -use Google\Protobuf\Duration; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; use Illuminate\Queue\Events\JobReleasedAfterException; @@ -16,7 +14,6 @@ use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksException; use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; use Stackkit\LaravelGoogleCloudTasksQueue\OpenIdVerificator; -use Stackkit\LaravelGoogleCloudTasksQueue\StackkitCloudTask; use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; use Tests\Support\EncryptedJob; use Tests\Support\FailingJob; @@ -37,6 +34,7 @@ protected function setUp(): void /** * @test + * * @testWith [true] * [false] */ @@ -58,6 +56,7 @@ public function it_returns_responses_for_empty_payloads($debug) /** * @test + * * @testWith [true] * [false] */ @@ -89,6 +88,7 @@ public function it_returns_responses_for_invalid_json($debug) /** * @test + * * @testWith ["{\"invalid\": \"data\"}"] * ["{\"data\": \"\"}"] * ["{\"data\": \"test\"}"] @@ -411,6 +411,7 @@ public function attempts_are_tracked_internally() Event::assertDispatched(JobReleasedAfterException::class, function ($event) use (&$releasedJob) { $releasedJob = $event->job->getRawBody(); + return $event->job->attempts() === 1; }); @@ -442,10 +443,12 @@ public function retried_jobs_get_a_new_name() CloudTasksApi::assertCreatedTaskCount(2); CloudTasksApi::assertTaskCreated(function (Task $task): bool { [$timestamp] = array_reverse(explode('-', $task->getName())); + return $timestamp === '1685035628000'; }); CloudTasksApi::assertTaskCreated(function (Task $task): bool { [$timestamp] = array_reverse(explode('-', $task->getName())); + return $timestamp === '1685035629000'; }); } diff --git a/tests/TestCase.php b/tests/TestCase.php index bdd1733..3eca787 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -19,7 +19,7 @@ class TestCase extends \Orchestra\Testbench\TestCase use DatabaseTransactions; /** - * @var CloudTasksClient $client + * @var CloudTasksClient */ public $client; @@ -29,9 +29,9 @@ protected function setUp(): void { parent::setUp(); - $this->withFactories(__DIR__ . '/../factories'); + $this->withFactories(__DIR__.'/../factories'); - $this->defaultHeaders['Authorization'] = 'Bearer ' . encrypt(time() + 10); + $this->defaultHeaders['Authorization'] = 'Bearer '.encrypt(time() + 10); Event::listen( JobReleasedAfterException::class, @@ -47,8 +47,7 @@ function ($event) { * In a normal app environment these would be added to the 'providers' array in * the config/app.php file. * - * @param \Illuminate\Foundation\Application $app - * + * @param \Illuminate\Foundation\Application $app * @return array */ protected function getPackageProviders($app) @@ -65,14 +64,14 @@ protected function getPackageProviders($app) */ protected function defineDatabaseMigrations() { - $this->loadMigrationsFrom(__DIR__ . '/../migrations'); - $this->loadMigrationsFrom(__DIR__ . '/../vendor/orchestra/testbench-core/laravel/migrations'); + $this->loadMigrationsFrom(__DIR__.'/../migrations'); + $this->loadMigrationsFrom(__DIR__.'/../vendor/orchestra/testbench-core/laravel/migrations'); } /** * Define environment setup. * - * @param \Illuminate\Foundation\Application $app + * @param \Illuminate\Foundation\Application $app * @return void */ protected function getEnvironmentSetUp($app) @@ -84,13 +83,13 @@ protected function getEnvironmentSetUp($app) $app['config']->set('database.default', 'testbench'); $port = env('DB_DRIVER') === 'mysql' ? 3307 : 5432; $app['config']->set('database.connections.testbench', [ - 'driver' => env('DB_DRIVER', 'mysql'), + 'driver' => env('DB_DRIVER', 'mysql'), 'host' => '127.0.0.1', 'port' => $port, 'database' => 'cloudtasks', 'username' => 'cloudtasks', 'password' => 'cloudtasks', - 'prefix' => '', + 'prefix' => '', ]); $app['config']->set('cache.default', 'file'); @@ -119,7 +118,7 @@ protected function getEnvironmentSetUp($app) protected function setConfigValue($key, $value) { - $this->app['config']->set('queue.connections.my-cloudtasks-connection.' . $key, $value); + $this->app['config']->set('queue.connections.my-cloudtasks-connection.'.$key, $value); } public function dispatch($job) @@ -147,9 +146,12 @@ public function dispatch($job) dispatch($job); - return new class($payload, $task, $this) { + return new class($payload, $task, $this) + { public string $payload; + public Task $task; + public TestCase $testCase; public function __construct(string $payload, Task $task, TestCase $testCase) @@ -218,7 +220,7 @@ public function assertTaskExists(string $taskId): void $this->assertInstanceOf(Task::class, $task); } catch (ApiException $e) { - $this->fail('Task [' . $taskId . '] should exist but it does not (or something else went wrong).'); + $this->fail('Task ['.$taskId.'] should exist but it does not (or something else went wrong).'); } } @@ -234,11 +236,11 @@ protected function addIdTokenToHeader(?Closure $closure = null): void $base = $closure($base); } - $privateKey = file_get_contents(__DIR__ . '/../tests/Support/self-signed-private-key.txt'); + $privateKey = file_get_contents(__DIR__.'/../tests/Support/self-signed-private-key.txt'); $token = JWT::encode($base, $privateKey, 'RS256', 'abc123'); - request()->headers->set('Authorization', 'Bearer ' . $token); + request()->headers->set('Authorization', 'Bearer '.$token); } protected function assertDatabaseCount($table, int $count, $connection = null) From ff8f7b20be8c7ffd1042116553a82e120844d339 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 12 Feb 2024 22:57:50 +0100 Subject: [PATCH 05/46] Add strict_types --- ...16_171140_create_stackkit_cloud_tasks_table.php | 2 ++ pint.json | 7 +++++++ src/Authenticate.php | 2 ++ src/CloudTasks.php | 2 ++ src/CloudTasksApiController.php | 4 +++- src/CloudTasksConnector.php | 2 ++ src/CloudTasksException.php | 2 ++ src/CloudTasksJob.php | 2 ++ src/CloudTasksQueue.php | 2 ++ src/CloudTasksServiceProvider.php | 2 ++ src/Config.php | 2 ++ src/DashboardService.php | 2 ++ src/Entities/StatRow.php | 2 ++ src/Errors.php | 2 ++ src/StackkitCloudTask.php | 2 ++ src/TaskHandler.php | 2 ++ src/TaskMetadata.php | 2 ++ tests/CloudTasksDashboardTest.php | 14 ++++++++------ tests/ConfigHandlerTest.php | 2 ++ tests/Support/EncryptedJob.php | 2 ++ tests/Support/FailingJob.php | 2 ++ tests/Support/FailingJobWithExponentialBackoff.php | 2 ++ tests/Support/FailingJobWithMaxTries.php | 2 ++ .../FailingJobWithMaxTriesAndRetryUntil.php | 2 ++ tests/Support/FailingJobWithRetryUntil.php | 2 ++ tests/Support/JobThatWillBeReleased.php | 2 ++ tests/Support/SimpleJob.php | 2 ++ tests/Support/UserJob.php | 2 ++ tests/TaskHandlerTest.php | 2 ++ tests/TestCase.php | 2 ++ 30 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 pint.json diff --git a/migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php b/migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php index 2455a5a..a78f17c 100644 --- a/migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php +++ b/migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php @@ -1,5 +1,7 @@ map(function (StackkitCloudTask $task) use ($maxId) { return [ 'uuid' => $task->task_uuid, - 'id' => str_pad((string) $task->id, strlen($maxId), '0', STR_PAD_LEFT), + 'id' => str_pad((string) $task->id, strlen((string) $maxId), '0', STR_PAD_LEFT), 'name' => $task->name, 'status' => $task->status, 'attempts' => $task->getNumberOfAttempts(), diff --git a/src/CloudTasksConnector.php b/src/CloudTasksConnector.php index 8ff23e9..c91ec24 100644 --- a/src/CloudTasksConnector.php +++ b/src/CloudTasksConnector.php @@ -1,5 +1,7 @@ withTaskType($test['task_type']); - \Illuminate\Support\Carbon::setTestNow(now()); + Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); @@ -355,7 +357,7 @@ public function when_a_job_is_successful_it_will_be_updated_in_the_dashboard(arr // Arrange $this->withTaskType($test['task_type']); - \Illuminate\Support\Carbon::setTestNow(now()); + Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); @@ -386,7 +388,7 @@ public function when_a_job_errors_it_will_be_updated_in_the_dashboard(array $tes // Arrange $this->withTaskType($test['task_type']); - \Illuminate\Support\Carbon::setTestNow(now()); + Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); @@ -418,7 +420,7 @@ public function when_a_job_fails_it_will_be_updated_in_the_dashboard(array $test // Arrange $this->withTaskType($test['task_type']); - \Illuminate\Support\Carbon::setTestNow(now()); + Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); @@ -452,7 +454,7 @@ public function when_a_job_is_released_it_will_be_updated_in_the_dashboard(array // Arrange $this->withTaskType($test['task_type']); - \Illuminate\Support\Carbon::setTestNow(now()); + Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); @@ -485,7 +487,7 @@ public function job_release_delay_is_added_to_the_metadata(array $test) // Arrange $this->withTaskType($test['task_type']); - \Illuminate\Support\Carbon::setTestNow(now()); + Carbon::setTestNow(now()); CloudTasksApi::fake(); OpenIdVerificator::fake(); diff --git a/tests/ConfigHandlerTest.php b/tests/ConfigHandlerTest.php index 6c30e3c..7264aa3 100644 --- a/tests/ConfigHandlerTest.php +++ b/tests/ConfigHandlerTest.php @@ -1,5 +1,7 @@ Date: Wed, 14 Feb 2024 21:02:34 +0100 Subject: [PATCH 06/46] Pint --- src/CloudTasksQueue.php | 11 +++++------ src/DashboardService.php | 1 - src/TaskHandler.php | 19 +++++++++---------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index e516c04..f7518dd 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -79,7 +79,7 @@ function ($payload, $queue) { */ public function pushRaw($payload, $queue = null, array $options = []) { - $delay = !empty($options['delay']) ? $options['delay'] : 0; + $delay = ! empty($options['delay']) ? $options['delay'] : 0; return $this->pushToCloudTasks($queue, $payload, $delay); } @@ -130,14 +130,14 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $task = $this->createTask(); $task->setName($this->taskName($queue, $payload)); - if (!empty($this->config['app_engine'])) { + if (! empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); $appEngineRequest = new AppEngineHttpRequest(); $appEngineRequest->setRelativeUri($path); $appEngineRequest->setHttpMethod(HttpMethod::POST); $appEngineRequest->setBody(json_encode($payload)); - if (!empty($service = $this->config['app_engine_service'])) { + if (! empty($service = $this->config['app_engine_service'])) { $routing = new AppEngineRouting(); $routing->setService($service); $appEngineRequest->setAppEngineRouting($routing); @@ -159,7 +159,6 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $task->setHttpRequest($httpRequest); } - // The deadline for requests sent to the app. If the app does not respond by // this deadline then the request is cancelled and the attempt is marked as // a failure. Cloud Tasks will retry the task according to the RetryConfig. @@ -213,7 +212,7 @@ private function withAttempts(array $payload): array /** * Pop the next job off of the queue. * - * @param string|null $queue + * @param string|null $queue * @return \Illuminate\Contracts\Queue\Job|null */ public function pop($queue = null) @@ -243,7 +242,7 @@ public function delete(CloudTasksJob $job): void $config['project'], $config['location'], $queue, - (string)$headerTaskName + (string) $headerTaskName ); CloudTasksApi::deleteTask($taskName); diff --git a/src/DashboardService.php b/src/DashboardService.php index b2d7e6d..eb17c1d 100644 --- a/src/DashboardService.php +++ b/src/DashboardService.php @@ -5,7 +5,6 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Exception; -use Google\Cloud\Tasks\V2\HttpRequest; use Google\Cloud\Tasks\V2\Task; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Queue\Events\JobExceptionOccurred; diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 3720df3..c4cba6a 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -11,8 +11,7 @@ use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; use Safe\Exceptions\JsonException; -use UnexpectedValueException; -use stdClass; + use function Safe\json_decode; class TaskHandler @@ -57,7 +56,7 @@ public function handle(?string $task = null): void */ private function captureTask($task): array { - $task = $task ?: (string)(request()->getContent()); + $task = $task ?: (string) (request()->getContent()); try { $array = json_decode($task, true); @@ -66,12 +65,12 @@ private function captureTask($task): array } $validator = validator([ - 'json' => $task, - 'task' => $array, + 'json' => $task, + 'task' => $array, ], [ - 'json' => 'required|json', - 'task' => 'required|array', - 'task.data' => 'required|array', + 'json' => 'required|json', + 'task' => 'required|array', + 'task.data' => 'required|array', ]); try { @@ -148,11 +147,11 @@ private function handleTask(array $task): void public static function getCommandProperties(string $command): array { if (Str::startsWith($command, 'O:')) { - return (array)unserialize($command, ['allowed_classes' => false]); + return (array) unserialize($command, ['allowed_classes' => false]); } if (app()->bound(Encrypter::class)) { - return (array)unserialize( + return (array) unserialize( app(Encrypter::class)->decrypt($command), ['allowed_classes' => ['Illuminate\Support\Carbon']] ); From 678457b75d1605251d02d286ba02560a2d538b54 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 14 Feb 2024 21:05:55 +0100 Subject: [PATCH 07/46] Use larastan/larastan --- composer.json | 10 ++++++++-- phpstan.neon | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index dfb337b..f98b48e 100644 --- a/composer.json +++ b/composer.json @@ -16,10 +16,10 @@ }, "require-dev": { "orchestra/testbench": "^8.0", - "nunomaduro/larastan": "^1.0 || ^2.0", "thecodingmachine/phpstan-safe-rule": "^1.2", "laravel/legacy-factories": "^1.3", - "laravel/pint": "^1.13" + "laravel/pint": "^1.13", + "larastan/larastan": "^2.9" }, "autoload": { "psr-4": { @@ -45,6 +45,12 @@ "l10": [ "composer require laravel/framework:10.* orchestra/testbench:8.* --no-interaction --no-update", "composer update --prefer-stable --prefer-dist --no-interaction" + ], + "pint": [ + "pint" + ], + "larastan": [ + "@php -d memory_limit=-1 vendor/bin/phpstan" ] } } diff --git a/phpstan.neon b/phpstan.neon index b2e12de..5af5ae1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ includes: - - ./vendor/nunomaduro/larastan/extension.neon + - ./vendor/larastan/larastan/extension.neon - ./vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon parameters: paths: From 6e1547febf227df43925bf9cf316b11e10f37832 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 14 Feb 2024 21:17:15 +0100 Subject: [PATCH 08/46] Remove Vue dashboard --- dashboard/.env.production | 1 - dashboard/.gitignore | 4 - dashboard/.prettierignore | 6 - dashboard/.prettierrc.js | 6 - dashboard/.prettierrc.json | 4 - dashboard/README.md | 7 - dashboard/dist/assets/index.d8eef428.css | 1 - dashboard/dist/assets/index.ea68d73f.js | 1 - dashboard/dist/assets/vendor.433de25e.js | 100 - dashboard/dist/favicon.ico | Bin 4286 -> 0 bytes dashboard/dist/index.html | 16 - dashboard/dist/manifest.json | 16 - dashboard/index.html | 13 - dashboard/package-lock.json | 2829 ----------------- dashboard/package.json | 22 - dashboard/postcss.config.js | 6 - dashboard/public/favicon.ico | Bin 4286 -> 0 bytes dashboard/src/App.vue | 29 - dashboard/src/api.js | 84 - dashboard/src/assets/logo.png | Bin 6849 -> 0 bytes dashboard/src/components/Dashboard.vue | 107 - dashboard/src/components/Failed.vue | 29 - dashboard/src/components/FilterCard.vue | 80 - dashboard/src/components/Icon.vue | 38 - dashboard/src/components/Login.vue | 101 - dashboard/src/components/Menu.vue | 31 - dashboard/src/components/Overview.vue | 207 -- dashboard/src/components/Queued.vue | 29 - dashboard/src/components/Recent.vue | 29 - dashboard/src/components/Spinner.vue | 22 - dashboard/src/components/Status.vue | 37 - dashboard/src/components/Task.vue | 125 - dashboard/src/components/TaskRowSpinner.vue | 28 - dashboard/src/index.css | 3 - dashboard/src/main.js | 102 - dashboard/tailwind.config.js | 10 - dashboard/vite.config.js | 11 - factories/StackkitCloudTaskFactory.php | 22 - ...02_14_211616_create_cloud_tasks_table.php} | 14 +- src/Authenticate.php | 20 - src/CloudTasks.php | 50 - src/CloudTasksApiController.php | 188 -- src/CloudTasksServiceProvider.php | 96 +- src/DashboardService.php | 177 -- src/Entities/StatRow.php | 25 - tests/CloudTasksDashboardTest.php | 644 ---- views/layout.blade.php | 28 - 47 files changed, 9 insertions(+), 5389 deletions(-) delete mode 100644 dashboard/.env.production delete mode 100644 dashboard/.gitignore delete mode 100644 dashboard/.prettierignore delete mode 100644 dashboard/.prettierrc.js delete mode 100644 dashboard/.prettierrc.json delete mode 100644 dashboard/README.md delete mode 100644 dashboard/dist/assets/index.d8eef428.css delete mode 100644 dashboard/dist/assets/index.ea68d73f.js delete mode 100644 dashboard/dist/assets/vendor.433de25e.js delete mode 100644 dashboard/dist/favicon.ico delete mode 100644 dashboard/dist/index.html delete mode 100644 dashboard/dist/manifest.json delete mode 100644 dashboard/index.html delete mode 100644 dashboard/package-lock.json delete mode 100644 dashboard/package.json delete mode 100644 dashboard/postcss.config.js delete mode 100644 dashboard/public/favicon.ico delete mode 100644 dashboard/src/App.vue delete mode 100644 dashboard/src/api.js delete mode 100644 dashboard/src/assets/logo.png delete mode 100644 dashboard/src/components/Dashboard.vue delete mode 100644 dashboard/src/components/Failed.vue delete mode 100644 dashboard/src/components/FilterCard.vue delete mode 100644 dashboard/src/components/Icon.vue delete mode 100644 dashboard/src/components/Login.vue delete mode 100644 dashboard/src/components/Menu.vue delete mode 100644 dashboard/src/components/Overview.vue delete mode 100644 dashboard/src/components/Queued.vue delete mode 100644 dashboard/src/components/Recent.vue delete mode 100644 dashboard/src/components/Spinner.vue delete mode 100644 dashboard/src/components/Status.vue delete mode 100644 dashboard/src/components/Task.vue delete mode 100644 dashboard/src/components/TaskRowSpinner.vue delete mode 100644 dashboard/src/index.css delete mode 100644 dashboard/src/main.js delete mode 100644 dashboard/tailwind.config.js delete mode 100644 dashboard/vite.config.js delete mode 100644 factories/StackkitCloudTaskFactory.php rename migrations/{2021_10_16_171140_create_stackkit_cloud_tasks_table.php => 2024_02_14_211616_create_cloud_tasks_table.php} (71%) delete mode 100644 src/Authenticate.php delete mode 100644 src/CloudTasks.php delete mode 100644 src/CloudTasksApiController.php delete mode 100644 src/DashboardService.php delete mode 100644 src/Entities/StatRow.php delete mode 100644 tests/CloudTasksDashboardTest.php delete mode 100644 views/layout.blade.php diff --git a/dashboard/.env.production b/dashboard/.env.production deleted file mode 100644 index 292a14c..0000000 --- a/dashboard/.env.production +++ /dev/null @@ -1 +0,0 @@ -VITE_API_URL= diff --git a/dashboard/.gitignore b/dashboard/.gitignore deleted file mode 100644 index a84704d..0000000 --- a/dashboard/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules -.DS_Store -dist-ssr -*.local \ No newline at end of file diff --git a/dashboard/.prettierignore b/dashboard/.prettierignore deleted file mode 100644 index 85dd8c4..0000000 --- a/dashboard/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -# Ignore artifacts: -build -coverage -.vscode -node_modules -.idea diff --git a/dashboard/.prettierrc.js b/dashboard/.prettierrc.js deleted file mode 100644 index 0614ee7..0000000 --- a/dashboard/.prettierrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - trailingComma: 'es5', - tabWidth: 2, - semi: false, - singleQuote: true, -} diff --git a/dashboard/.prettierrc.json b/dashboard/.prettierrc.json deleted file mode 100644 index b2095be..0000000 --- a/dashboard/.prettierrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "semi": false, - "singleQuote": true -} diff --git a/dashboard/README.md b/dashboard/README.md deleted file mode 100644 index c0793a8..0000000 --- a/dashboard/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Vue 3 + Vite - -This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` - - - - -
- - - diff --git a/dashboard/dist/manifest.json b/dashboard/dist/manifest.json deleted file mode 100644 index 53f0594..0000000 --- a/dashboard/dist/manifest.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "index.html": { - "file": "assets/index.ea68d73f.js", - "src": "index.html", - "isEntry": true, - "imports": [ - "_vendor.433de25e.js" - ], - "css": [ - "assets/index.d8eef428.css" - ] - }, - "_vendor.433de25e.js": { - "file": "assets/vendor.433de25e.js" - } -} \ No newline at end of file diff --git a/dashboard/index.html b/dashboard/index.html deleted file mode 100644 index 4333263..0000000 --- a/dashboard/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Vite App - - -
- - - diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json deleted file mode 100644 index 61de1ad..0000000 --- a/dashboard/package-lock.json +++ /dev/null @@ -1,2829 +0,0 @@ -{ - "name": "cloud-tasks-dashboard", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "cloud-tasks-dashboard", - "version": "0.0.0", - "dependencies": { - "vue": "^3.2.25", - "vue-router": "^4.0.12", - "vue3-popper": "^1.4.1" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^2.0.0", - "autoprefixer": "^10.4.2", - "postcss": "^8.4.5", - "prettier": "2.5.1", - "tailwindcss": "^3.0.18", - "vite": "^2.7.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", - "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", - "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@vitejs/plugin-vue": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.1.0.tgz", - "integrity": "sha512-AZ78WxvFMYd8JmM/GBV6a6SGGTU0GgN/0/4T+FnMMsLzFEzTeAUwuraapy50ifHZsC+G5SvWs86bvaCPTneFlA==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "vite": "^2.5.10", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.29.tgz", - "integrity": "sha512-RePZ/J4Ub3sb7atQw6V6Rez+/5LCRHGFlSetT3N4VMrejqJnNPXKUt5AVm/9F5MJriy2w/VudEIvgscCfCWqxw==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.29", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.29.tgz", - "integrity": "sha512-y26vK5khdNS9L3ckvkqJk/78qXwWb75Ci8iYLb67AkJuIgyKhIOcR1E8RIt4mswlVCIeI9gQ+fmtdhaiTAtrBQ==", - "dependencies": { - "@vue/compiler-core": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.29.tgz", - "integrity": "sha512-X9+0dwsag2u6hSOP/XsMYqFti/edvYvxamgBgCcbSYuXx1xLZN+dS/GvQKM4AgGS4djqo0jQvWfIXdfZ2ET68g==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.29", - "@vue/compiler-dom": "3.2.29", - "@vue/compiler-ssr": "3.2.29", - "@vue/reactivity-transform": "3.2.29", - "@vue/shared": "3.2.29", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.29.tgz", - "integrity": "sha512-LrvQwXlx66uWsB9/VydaaqEpae9xtmlUkeSKF6aPDbzx8M1h7ukxaPjNCAXuFd3fUHblcri8k42lfimHfzMICA==", - "dependencies": { - "@vue/compiler-dom": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "node_modules/@vue/devtools-api": { - "version": "6.0.0-beta.21.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.21.1.tgz", - "integrity": "sha512-FqC4s3pm35qGVeXRGOjTsRzlkJjrBLriDS9YXbflHLsfA9FrcKzIyWnLXoNm+/7930E8rRakXuAc2QkC50swAw==" - }, - "node_modules/@vue/reactivity": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.29.tgz", - "integrity": "sha512-Ryhb6Gy62YolKXH1gv42pEqwx7zs3n8gacRVZICSgjQz8Qr8QeCcFygBKYfJm3o1SccR7U+bVBQDWZGOyG1k4g==", - "dependencies": { - "@vue/shared": "3.2.29" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.29.tgz", - "integrity": "sha512-YF6HdOuhdOw6KyRm59+3rML8USb9o8mYM1q+SH0G41K3/q/G7uhPnHGKvspzceD7h9J3VR1waOQ93CUZj7J7OA==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.29", - "@vue/shared": "3.2.29", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.29.tgz", - "integrity": "sha512-VMvQuLdzoTGmCwIKTKVwKmIL0qcODIqe74JtK1pVr5lnaE0l25hopodmPag3RcnIcIXe+Ye3B2olRCn7fTCgig==", - "dependencies": { - "@vue/reactivity": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.29.tgz", - "integrity": "sha512-YJgLQLwr+SQyORzTsBQLL5TT/5UiV83tEotqjL7F9aFDIQdFBTCwpkCFvX9jqwHoyi9sJqM9XtTrMcc8z/OjPA==", - "dependencies": { - "@vue/runtime-core": "3.2.29", - "@vue/shared": "3.2.29", - "csstype": "^2.6.8" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.29.tgz", - "integrity": "sha512-lpiYx7ciV7rWfJ0tPkoSOlLmwqBZ9FTmQm33S+T4g0j1fO/LmhJ9b9Ctl1o5xvIFVDk9QkSUWANZn7H2pXuxVw==", - "dependencies": { - "@vue/compiler-ssr": "3.2.29", - "@vue/shared": "3.2.29" - }, - "peerDependencies": { - "vue": "3.2.29" - } - }, - "node_modules/@vue/shared": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.29.tgz", - "integrity": "sha512-BjNpU8OK6Z0LVzGUppEk0CMYm/hKDnZfYdjSmPOs0N+TR1cLKJAkDwW8ASZUvaaSLEi6d3hVM7jnWnX+6yWnHw==" - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true - }, - "node_modules/autoprefixer": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", - "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.19.1", - "caniuse-lite": "^1.0.30001297", - "fraction.js": "^4.1.2", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001304", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz", - "integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "2.6.19", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", - "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" - }, - "node_modules/defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "node_modules/detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, - "dependencies": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.57", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz", - "integrity": "sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/esbuild": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.15.tgz", - "integrity": "sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "optionalDependencies": { - "esbuild-android-arm64": "0.13.15", - "esbuild-darwin-64": "0.13.15", - "esbuild-darwin-arm64": "0.13.15", - "esbuild-freebsd-64": "0.13.15", - "esbuild-freebsd-arm64": "0.13.15", - "esbuild-linux-32": "0.13.15", - "esbuild-linux-64": "0.13.15", - "esbuild-linux-arm": "0.13.15", - "esbuild-linux-arm64": "0.13.15", - "esbuild-linux-mips64le": "0.13.15", - "esbuild-linux-ppc64le": "0.13.15", - "esbuild-netbsd-64": "0.13.15", - "esbuild-openbsd-64": "0.13.15", - "esbuild-sunos-64": "0.13.15", - "esbuild-windows-32": "0.13.15", - "esbuild-windows-64": "0.13.15", - "esbuild-windows-arm64": "0.13.15" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz", - "integrity": "sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/esbuild-darwin-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz", - "integrity": "sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz", - "integrity": "sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz", - "integrity": "sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz", - "integrity": "sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/esbuild-linux-32": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz", - "integrity": "sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/esbuild-linux-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz", - "integrity": "sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/esbuild-linux-arm": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz", - "integrity": "sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz", - "integrity": "sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz", - "integrity": "sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz", - "integrity": "sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz", - "integrity": "sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ] - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz", - "integrity": "sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/esbuild-sunos-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz", - "integrity": "sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ] - }, - "node_modules/esbuild-windows-32": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz", - "integrity": "sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/esbuild-windows-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz", - "integrity": "sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz", - "integrity": "sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fraction.js": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", - "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/lilconfig": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", - "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", - "dependencies": { - "nanoid": "^3.1.30", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.1.tgz", - "integrity": "sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.4", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.6" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "2.66.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.66.1.tgz", - "integrity": "sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.18.tgz", - "integrity": "sha512-ihPTpEyA5ANgZbwKlgrbfnzOp9R5vDHFWmqxB1PT8NwOGCOFVVMl+Ps1cQQ369acaqqf1BEF77roCwK0lvNmTw==", - "dev": true, - "dependencies": { - "arg": "^5.0.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "cosmiconfig": "^7.0.1", - "detective": "^5.2.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "normalize-path": "^3.0.0", - "object-hash": "^2.2.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.0", - "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.21.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "autoprefixer": "^10.0.2", - "postcss": "^8.0.9" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/vite": { - "version": "2.7.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.7.13.tgz", - "integrity": "sha512-Mq8et7f3aK0SgSxjDNfOAimZGW9XryfHRa/uV0jseQSilg+KhYDSoNb9h1rknOy6SuMkvNDLKCYAYYUMCE+IgQ==", - "dev": true, - "dependencies": { - "esbuild": "^0.13.12", - "postcss": "^8.4.5", - "resolve": "^1.20.0", - "rollup": "^2.59.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": ">=12.2.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "less": "*", - "sass": "*", - "stylus": "*" - }, - "peerDependenciesMeta": { - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - } - } - }, - "node_modules/vue": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.29.tgz", - "integrity": "sha512-cFIwr7LkbtCRanjNvh6r7wp2yUxfxeM2yPpDQpAfaaLIGZSrUmLbNiSze9nhBJt5MrZ68Iqt0O5scwAMEVxF+Q==", - "dependencies": { - "@vue/compiler-dom": "3.2.29", - "@vue/compiler-sfc": "3.2.29", - "@vue/runtime-dom": "3.2.29", - "@vue/server-renderer": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "node_modules/vue-router": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.12.tgz", - "integrity": "sha512-CPXvfqe+mZLB1kBWssssTiWg4EQERyqJZes7USiqfW9B5N2x+nHlnsM1D3b5CaJ6qgCvMmYJnz+G0iWjNCvXrg==", - "dependencies": { - "@vue/devtools-api": "^6.0.0-beta.18" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue3-popper": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/vue3-popper/-/vue3-popper-1.4.1.tgz", - "integrity": "sha512-pmct5vumtvbK8MmUs4oFY+3Al1glU34QXWcIPK4WJhRo/Kp85kxD0j70cNofNBqHYwhY5D7xJ6Yhkwf/5x9w7Q==", - "dependencies": { - "@popperjs/core": "^2.9.2", - "debounce": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "vue": "^3.2.20" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", - "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==" - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@popperjs/core": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", - "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==" - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@vitejs/plugin-vue": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.1.0.tgz", - "integrity": "sha512-AZ78WxvFMYd8JmM/GBV6a6SGGTU0GgN/0/4T+FnMMsLzFEzTeAUwuraapy50ifHZsC+G5SvWs86bvaCPTneFlA==", - "dev": true, - "requires": {} - }, - "@vue/compiler-core": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.29.tgz", - "integrity": "sha512-RePZ/J4Ub3sb7atQw6V6Rez+/5LCRHGFlSetT3N4VMrejqJnNPXKUt5AVm/9F5MJriy2w/VudEIvgscCfCWqxw==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.29", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-dom": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.29.tgz", - "integrity": "sha512-y26vK5khdNS9L3ckvkqJk/78qXwWb75Ci8iYLb67AkJuIgyKhIOcR1E8RIt4mswlVCIeI9gQ+fmtdhaiTAtrBQ==", - "requires": { - "@vue/compiler-core": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "@vue/compiler-sfc": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.29.tgz", - "integrity": "sha512-X9+0dwsag2u6hSOP/XsMYqFti/edvYvxamgBgCcbSYuXx1xLZN+dS/GvQKM4AgGS4djqo0jQvWfIXdfZ2ET68g==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.29", - "@vue/compiler-dom": "3.2.29", - "@vue/compiler-ssr": "3.2.29", - "@vue/reactivity-transform": "3.2.29", - "@vue/shared": "3.2.29", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-ssr": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.29.tgz", - "integrity": "sha512-LrvQwXlx66uWsB9/VydaaqEpae9xtmlUkeSKF6aPDbzx8M1h7ukxaPjNCAXuFd3fUHblcri8k42lfimHfzMICA==", - "requires": { - "@vue/compiler-dom": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "@vue/devtools-api": { - "version": "6.0.0-beta.21.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.21.1.tgz", - "integrity": "sha512-FqC4s3pm35qGVeXRGOjTsRzlkJjrBLriDS9YXbflHLsfA9FrcKzIyWnLXoNm+/7930E8rRakXuAc2QkC50swAw==" - }, - "@vue/reactivity": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.29.tgz", - "integrity": "sha512-Ryhb6Gy62YolKXH1gv42pEqwx7zs3n8gacRVZICSgjQz8Qr8QeCcFygBKYfJm3o1SccR7U+bVBQDWZGOyG1k4g==", - "requires": { - "@vue/shared": "3.2.29" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.29.tgz", - "integrity": "sha512-YF6HdOuhdOw6KyRm59+3rML8USb9o8mYM1q+SH0G41K3/q/G7uhPnHGKvspzceD7h9J3VR1waOQ93CUZj7J7OA==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.29", - "@vue/shared": "3.2.29", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "@vue/runtime-core": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.29.tgz", - "integrity": "sha512-VMvQuLdzoTGmCwIKTKVwKmIL0qcODIqe74JtK1pVr5lnaE0l25hopodmPag3RcnIcIXe+Ye3B2olRCn7fTCgig==", - "requires": { - "@vue/reactivity": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "@vue/runtime-dom": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.29.tgz", - "integrity": "sha512-YJgLQLwr+SQyORzTsBQLL5TT/5UiV83tEotqjL7F9aFDIQdFBTCwpkCFvX9jqwHoyi9sJqM9XtTrMcc8z/OjPA==", - "requires": { - "@vue/runtime-core": "3.2.29", - "@vue/shared": "3.2.29", - "csstype": "^2.6.8" - } - }, - "@vue/server-renderer": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.29.tgz", - "integrity": "sha512-lpiYx7ciV7rWfJ0tPkoSOlLmwqBZ9FTmQm33S+T4g0j1fO/LmhJ9b9Ctl1o5xvIFVDk9QkSUWANZn7H2pXuxVw==", - "requires": { - "@vue/compiler-ssr": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "@vue/shared": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.29.tgz", - "integrity": "sha512-BjNpU8OK6Z0LVzGUppEk0CMYm/hKDnZfYdjSmPOs0N+TR1cLKJAkDwW8ASZUvaaSLEi6d3hVM7jnWnX+6yWnHw==" - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", - "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", - "dev": true, - "requires": { - "browserslist": "^4.19.1", - "caniuse-lite": "^1.0.30001297", - "fraction.js": "^4.1.2", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001304", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz", - "integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "csstype": { - "version": "2.6.19", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", - "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" - }, - "debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.57", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz", - "integrity": "sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "esbuild": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.15.tgz", - "integrity": "sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==", - "dev": true, - "requires": { - "esbuild-android-arm64": "0.13.15", - "esbuild-darwin-64": "0.13.15", - "esbuild-darwin-arm64": "0.13.15", - "esbuild-freebsd-64": "0.13.15", - "esbuild-freebsd-arm64": "0.13.15", - "esbuild-linux-32": "0.13.15", - "esbuild-linux-64": "0.13.15", - "esbuild-linux-arm": "0.13.15", - "esbuild-linux-arm64": "0.13.15", - "esbuild-linux-mips64le": "0.13.15", - "esbuild-linux-ppc64le": "0.13.15", - "esbuild-netbsd-64": "0.13.15", - "esbuild-openbsd-64": "0.13.15", - "esbuild-sunos-64": "0.13.15", - "esbuild-windows-32": "0.13.15", - "esbuild-windows-64": "0.13.15", - "esbuild-windows-arm64": "0.13.15" - } - }, - "esbuild-android-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz", - "integrity": "sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz", - "integrity": "sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz", - "integrity": "sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz", - "integrity": "sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz", - "integrity": "sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz", - "integrity": "sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz", - "integrity": "sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz", - "integrity": "sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz", - "integrity": "sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz", - "integrity": "sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz", - "integrity": "sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz", - "integrity": "sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz", - "integrity": "sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz", - "integrity": "sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz", - "integrity": "sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz", - "integrity": "sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.13.15", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz", - "integrity": "sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==", - "dev": true, - "optional": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fraction.js": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", - "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "lilconfig": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", - "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==" - }, - "node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", - "requires": { - "nanoid": "^3.1.30", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" - } - }, - "postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.1.tgz", - "integrity": "sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==", - "dev": true, - "requires": { - "lilconfig": "^2.0.4", - "yaml": "^1.10.2" - } - }, - "postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.6" - } - }, - "postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rollup": { - "version": "2.66.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.66.1.tgz", - "integrity": "sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "tailwindcss": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.18.tgz", - "integrity": "sha512-ihPTpEyA5ANgZbwKlgrbfnzOp9R5vDHFWmqxB1PT8NwOGCOFVVMl+Ps1cQQ369acaqqf1BEF77roCwK0lvNmTw==", - "dev": true, - "requires": { - "arg": "^5.0.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "cosmiconfig": "^7.0.1", - "detective": "^5.2.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "normalize-path": "^3.0.0", - "object-hash": "^2.2.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.0", - "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.21.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "vite": { - "version": "2.7.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.7.13.tgz", - "integrity": "sha512-Mq8et7f3aK0SgSxjDNfOAimZGW9XryfHRa/uV0jseQSilg+KhYDSoNb9h1rknOy6SuMkvNDLKCYAYYUMCE+IgQ==", - "dev": true, - "requires": { - "esbuild": "^0.13.12", - "fsevents": "~2.3.2", - "postcss": "^8.4.5", - "resolve": "^1.20.0", - "rollup": "^2.59.0" - } - }, - "vue": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.29.tgz", - "integrity": "sha512-cFIwr7LkbtCRanjNvh6r7wp2yUxfxeM2yPpDQpAfaaLIGZSrUmLbNiSze9nhBJt5MrZ68Iqt0O5scwAMEVxF+Q==", - "requires": { - "@vue/compiler-dom": "3.2.29", - "@vue/compiler-sfc": "3.2.29", - "@vue/runtime-dom": "3.2.29", - "@vue/server-renderer": "3.2.29", - "@vue/shared": "3.2.29" - } - }, - "vue-router": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.12.tgz", - "integrity": "sha512-CPXvfqe+mZLB1kBWssssTiWg4EQERyqJZes7USiqfW9B5N2x+nHlnsM1D3b5CaJ6qgCvMmYJnz+G0iWjNCvXrg==", - "requires": { - "@vue/devtools-api": "^6.0.0-beta.18" - } - }, - "vue3-popper": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/vue3-popper/-/vue3-popper-1.4.1.tgz", - "integrity": "sha512-pmct5vumtvbK8MmUs4oFY+3Al1glU34QXWcIPK4WJhRo/Kp85kxD0j70cNofNBqHYwhY5D7xJ6Yhkwf/5x9w7Q==", - "requires": { - "@popperjs/core": "^2.9.2", - "debounce": "^1.2.1" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - } - } -} diff --git a/dashboard/package.json b/dashboard/package.json deleted file mode 100644 index 412ac7e..0000000 --- a/dashboard/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "cloud-tasks-dashboard", - "version": "0.0.0", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "vue": "^3.2.25", - "vue-router": "^4.0.12", - "vue3-popper": "^1.4.1" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^2.0.0", - "autoprefixer": "^10.4.2", - "postcss": "^8.4.5", - "prettier": "2.5.1", - "tailwindcss": "^3.0.18", - "vite": "^2.7.2" - } -} diff --git a/dashboard/postcss.config.js b/dashboard/postcss.config.js deleted file mode 100644 index 33ad091..0000000 --- a/dashboard/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/dashboard/public/favicon.ico b/dashboard/public/favicon.ico deleted file mode 100644 index df36fcfb72584e00488330b560ebcf34a41c64c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S diff --git a/dashboard/src/App.vue b/dashboard/src/App.vue deleted file mode 100644 index eea59d2..0000000 --- a/dashboard/src/App.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - - diff --git a/dashboard/src/api.js b/dashboard/src/api.js deleted file mode 100644 index 82df227..0000000 --- a/dashboard/src/api.js +++ /dev/null @@ -1,84 +0,0 @@ -import { onUnmounted, watch } from 'vue' -import { onBeforeRouteUpdate } from 'vue-router' - -export async function callApi({ - endpoint, - router, - body = null, - method = 'GET', - login = false, -} = {}) { - const response = await fetch( - `${import.meta.env.VITE_API_URL || ''}/cloud-tasks-api/${endpoint}`, - { - method, - ...(body ? { body } : {}), - headers: { - ...(!login - ? { - Authorization: `Bearer ${localStorage.getItem( - 'cloud-tasks-token' - )}`, - } - : {}), - }, - } - ) - - if (response.status === 403 && !login) { - localStorage.removeItem('cloud-tasks-token') - router.push({ name: 'login' }) - } - - return login ? await response.text() : await response.json() -} - -export async function fetchTasks(into, query = {}, router) { - let paused = false - - const f = async function (into) { - if (paused) { - return - } - - const url = new URL(window.location.href) - const queryParams = new URLSearchParams(url.search) - - for (const [name, value] of Object.entries(query)) { - queryParams.append(name, value) - } - - paused = true - into.value = await callApi({ - endpoint: `tasks?${queryParams.toString()}`, - router, - }) - paused = false - } - - f(into) - let interval = setInterval(() => f(into), 3000) - let visibilityChangeListener = null - - // immediately re-fetch results if results have been filtered. - onBeforeRouteUpdate(function () { - setTimeout(() => f(into)) - }) - - const onVisibilityChange = function () { - if (document.visibilityState === 'visible') { - f(into) - clearInterval(interval) - interval = setInterval(() => f(into), 3000) - } else if (document.visibilityState === 'hidden') { - clearInterval(interval) - } - } - document.addEventListener('visibilitychange', onVisibilityChange) - - onUnmounted(() => { - clearInterval(interval) - document.removeEventListener('visibilitychange', onVisibilityChange) - paused = false - }) -} diff --git a/dashboard/src/assets/logo.png b/dashboard/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b5053b0837ebea6e87a2d339a43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6849 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 -import { onMounted, ref } from 'vue' -import { useRouter } from 'vue-router' -import { callApi } from '../api' - -const router = useRouter() -const dashboard = ref({ - recent: { - this_minute: '...', - this_hour: '...', - today: '...', - }, - failed: { - this_minute: '...', - this_hour: '...', - today: '...', - }, -}) - -onMounted(async () => { - dashboard.value = await callApi({ - endpoint: 'dashboard', - router, - }) -}) - - - diff --git a/dashboard/src/components/Failed.vue b/dashboard/src/components/Failed.vue deleted file mode 100644 index 5009a2c..0000000 --- a/dashboard/src/components/Failed.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - diff --git a/dashboard/src/components/FilterCard.vue b/dashboard/src/components/FilterCard.vue deleted file mode 100644 index a24526b..0000000 --- a/dashboard/src/components/FilterCard.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - diff --git a/dashboard/src/components/Icon.vue b/dashboard/src/components/Icon.vue deleted file mode 100644 index a29e556..0000000 --- a/dashboard/src/components/Icon.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/dashboard/src/components/Login.vue b/dashboard/src/components/Login.vue deleted file mode 100644 index 17f04f8..0000000 --- a/dashboard/src/components/Login.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - - - diff --git a/dashboard/src/components/Menu.vue b/dashboard/src/components/Menu.vue deleted file mode 100644 index 3458e78..0000000 --- a/dashboard/src/components/Menu.vue +++ /dev/null @@ -1,31 +0,0 @@ - diff --git a/dashboard/src/components/Overview.vue b/dashboard/src/components/Overview.vue deleted file mode 100644 index 8679fd0..0000000 --- a/dashboard/src/components/Overview.vue +++ /dev/null @@ -1,207 +0,0 @@ - - - - - diff --git a/dashboard/src/components/Queued.vue b/dashboard/src/components/Queued.vue deleted file mode 100644 index 03335e7..0000000 --- a/dashboard/src/components/Queued.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - diff --git a/dashboard/src/components/Recent.vue b/dashboard/src/components/Recent.vue deleted file mode 100644 index 58c4855..0000000 --- a/dashboard/src/components/Recent.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - diff --git a/dashboard/src/components/Spinner.vue b/dashboard/src/components/Spinner.vue deleted file mode 100644 index c2a0d55..0000000 --- a/dashboard/src/components/Spinner.vue +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/dashboard/src/components/Status.vue b/dashboard/src/components/Status.vue deleted file mode 100644 index b1beb73..0000000 --- a/dashboard/src/components/Status.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - - - diff --git a/dashboard/src/components/Task.vue b/dashboard/src/components/Task.vue deleted file mode 100644 index 031dd73..0000000 --- a/dashboard/src/components/Task.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - - - diff --git a/dashboard/src/components/TaskRowSpinner.vue b/dashboard/src/components/TaskRowSpinner.vue deleted file mode 100644 index a877678..0000000 --- a/dashboard/src/components/TaskRowSpinner.vue +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/dashboard/src/index.css b/dashboard/src/index.css deleted file mode 100644 index b5c61c9..0000000 --- a/dashboard/src/index.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/dashboard/src/main.js b/dashboard/src/main.js deleted file mode 100644 index 4b958dd..0000000 --- a/dashboard/src/main.js +++ /dev/null @@ -1,102 +0,0 @@ -import { createApp } from 'vue/dist/vue.esm-bundler' -import App from './App.vue' -import './index.css' -import { createRouter, createWebHistory } from 'vue-router' -import Popper from 'vue3-popper' - -// 1. Define route components. -// These can be imported from other files -import Login from './components/Login.vue' -import Dashboard from './components/Dashboard.vue' -import Recent from './components/Recent.vue' -import Queued from './components/Queued.vue' -import Failed from './components/Failed.vue' -import Task from './components/Task.vue' - -// 2. Define some routes -// Each route should map to a component. -// We'll talk about nested routes later. -const routes = [ - { - name: 'home', - path: '/', - component: Dashboard, - }, - { - name: 'login', - path: '/login', - component: Login, - }, - { - name: 'recent', - path: '/recent', - component: Recent, - meta: { - route: 'recent', - }, - }, - { - name: 'recent-task', - path: '/recent/:uuid', - component: Task, - meta: { - route: 'recent', - }, - }, - { - name: 'queued', - path: '/queued', - component: Queued, - meta: { - route: 'queued', - }, - }, - { - name: 'queued-task', - path: '/queued/:uuid', - component: Task, - meta: { - route: 'queued', - }, - }, - { - name: 'failed', - path: '/failed', - component: Failed, - meta: { - route: 'failed', - }, - }, - { - name: 'failed-task', - path: '/failed/:uuid', - component: Task, - meta: { - route: 'failed', - }, - }, -] - -// 3. Create the router instance and pass the `routes` option -// You can pass in additional options here, but let's -// keep it simple for now. -let routerBasePath = null -if ('CloudTasks' in window) { - routerBasePath = `/${window.CloudTasks.path}` -} - -const router = createRouter({ - // 4. Provide the history implementation to use. We are using the hash history for simplicity here. - history: createWebHistory(routerBasePath), - routes, // short for `routes: routes`, -}) - -router.beforeEach((to, from, next) => { - const authenticated = localStorage.hasOwnProperty('cloud-tasks-token') - if (!authenticated && to.name !== 'login') { - return next({ name: 'login' }) - } - return next() -}) - -createApp(App).use(router).component('Popper', Popper).mount('#app') diff --git a/dashboard/tailwind.config.js b/dashboard/tailwind.config.js deleted file mode 100644 index c3d7982..0000000 --- a/dashboard/tailwind.config.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - content: [ - "./index.html", - "./src/**/*.{vue,js,ts,jsx,tsx}", - ], - theme: { - extend: {}, - }, - plugins: [], -} diff --git a/dashboard/vite.config.js b/dashboard/vite.config.js deleted file mode 100644 index 3cbd7b6..0000000 --- a/dashboard/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue()], - build: { - manifest: true, - target: 'es2015', - }, -}) diff --git a/factories/StackkitCloudTaskFactory.php b/factories/StackkitCloudTaskFactory.php deleted file mode 100644 index 926ce94..0000000 --- a/factories/StackkitCloudTaskFactory.php +++ /dev/null @@ -1,22 +0,0 @@ -define(StackkitCloudTask::class, function (Faker $faker) { - return [ - 'status' => 'queued', - 'queue' => 'barbequeue', - 'task_uuid' => (string) Str::uuid(), - 'name' => 'SimpleJob', - 'metadata' => '{}', - 'payload' => '{}', - ]; -}); diff --git a/migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php b/migrations/2024_02_14_211616_create_cloud_tasks_table.php similarity index 71% rename from migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php rename to migrations/2024_02_14_211616_create_cloud_tasks_table.php index a78f17c..8b44394 100644 --- a/migrations/2021_10_16_171140_create_stackkit_cloud_tasks_table.php +++ b/migrations/2024_02_14_211616_create_cloud_tasks_table.php @@ -6,7 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateStackkitCloudTasksTable extends Migration +class CreateCloudTasksTable extends Migration { /** * Run the migrations. @@ -15,17 +15,17 @@ class CreateStackkitCloudTasksTable extends Migration */ public function up() { - Schema::create('stackkit_cloud_tasks', function (Blueprint $table) { + Schema::dropIfExists('stackkit_cloud_tasks'); + + Schema::create('cloud_tasks', function (Blueprint $table) { $table->increments('id'); $table->string('queue'); - $table->string('task_uuid'); + $table->string('task_name'); $table->string('name'); $table->string('status'); - $table->text('metadata'); - $table->text('payload'); $table->timestamps(); - $table->index('task_uuid'); + $table->index('task_name'); $table->index('queue'); $table->index('status'); }); @@ -38,6 +38,6 @@ public function up() */ public function down() { - Schema::dropIfExists('stackkit_cloud_tasks'); + Schema::dropIfExists('cloud_tasks'); } } diff --git a/src/Authenticate.php b/src/Authenticate.php deleted file mode 100644 index fa7b3cf..0000000 --- a/src/Authenticate.php +++ /dev/null @@ -1,20 +0,0 @@ -json('', 403); - } -} diff --git a/src/CloudTasks.php b/src/CloudTasks.php deleted file mode 100644 index 8451668..0000000 --- a/src/CloudTasks.php +++ /dev/null @@ -1,50 +0,0 @@ -bearerToken(); - - if (! $token) { - return false; - } - - try { - $expireTimestamp = decrypt($token); - - return $expireTimestamp > Carbon::now()->timestamp; - } catch (Throwable $e) { - return false; - } - } - - /** - * Determine if the dashboard is enabled. - */ - public static function dashboardEnabled(): bool - { - return config('cloud-tasks.dashboard.enabled') === true; - } - - /** - * Determine if the dashboard is disabled. - */ - public static function dashboardDisabled(): bool - { - return self::dashboardEnabled() === false; - } -} diff --git a/src/CloudTasksApiController.php b/src/CloudTasksApiController.php deleted file mode 100644 index e3762f2..0000000 --- a/src/CloudTasksApiController.php +++ /dev/null @@ -1,188 +0,0 @@ -getTimestamp() + 900); - } - - public function dashboard(): array - { - $dbDriver = config('database.connections.'.config('database.default').'.driver'); - - if (! in_array($dbDriver, ['mysql', 'pgsql'])) { - throw new Exception('Unsupported database driver for Cloud Tasks dashboard.'); - } - - $groupBy = [ - 'mysql' => [ - 'this_minute' => 'DATE_FORMAT(created_at, \'%H:%i\')', - 'this_hour' => 'DATE_FORMAT(created_at, \'%H\')', - ], - 'pgsql' => [ - 'this_minute' => 'TO_CHAR(created_at :: TIME, \'HH24:MI\')', - 'this_hour' => 'TO_CHAR(created_at :: TIME, \'HH24\')', - ], - ][$dbDriver]; - - /** - * @var array $stats - */ - $stats = DB::table((new StackkitCloudTask())->getTable()) - ->where('created_at', '>=', now()->utc()->startOfDay()) - ->select( - [ - DB::raw('COUNT(id) as count'), - DB::raw('CASE WHEN status = \'failed\' THEN 1 ELSE 0 END AS failed'), - DB::raw(' - CASE - WHEN '.$groupBy['this_minute'].' = \''.now()->utc()->format('H:i').'\' THEN \'this_minute\' - WHEN '.$groupBy['this_hour'].' = \''.now()->utc()->format('H').'\' THEN \'this_hour\' - - ELSE \'today\' - END AS time_preset - '), - ] - ) - ->groupBy( - [ - 'failed', - 'time_preset', - ] - ) - ->get() - ->map(fn ($row) => StatRow::createFromObject($row)) - ->toArray(); - - $response = [ - 'recent' => [ - 'this_minute' => 0, - 'this_hour' => 0, - 'this_day' => 0, - ], - 'failed' => [ - 'this_minute' => 0, - 'this_hour' => 0, - 'this_day' => 0, - ], - ]; - - foreach ($stats as $row) { - $response['recent']['this_day'] += $row->count; - - if ($row->time_preset === 'this_minute') { - $response['recent']['this_minute'] += $row->count; - $response['recent']['this_hour'] += $row->count; - } - - if ($row->time_preset === 'this_hour') { - $response['recent']['this_hour'] += $row->count; - } - - if ($row->failed === 0) { - continue; - } - - $response['failed']['this_day'] += $row->count; - - if ($row->time_preset === 'this_minute') { - $response['failed']['this_minute'] += $row->count; - $response['failed']['this_hour'] += $row->count; - } - - if ($row->time_preset === 'this_hour') { - $response['failed']['this_hour'] += $row->count; - } - } - - return $response; - } - - /** - * @return Collection - */ - public function tasks() - { - Carbon::setTestNowAndTimezone(now()->utc()); - - $tasks = StackkitCloudTask::query() - ->newestFirst() - ->where('created_at', '>=', now()->utc()->startOfDay()) - ->when(request('filter') === 'failed', function (Builder $builder) { - return $builder->where('status', 'failed'); - }) - ->when(request('time'), function (Builder $builder) { - [$hour, $minute] = explode(':', request('time')); - - return $builder - ->where('created_at', '>=', now()->setTime((int) $hour, (int) $minute, 0)) - ->where('created_at', '<=', now()->setTime((int) $hour, (int) $minute, 59)); - }) - ->when(request('hour'), function (Builder $builder, $hour) { - return $builder->where('created_at', '>=', now()->setTime((int) $hour, 0, 0)) - ->where('created_at', '<=', now()->setTime((int) $hour, 59, 59)); - }) - ->when(request('queue'), function (Builder $builder, $queue) { - return $builder->where('queue', $queue); - }) - ->when(request('status'), function (Builder $builder, $status) { - return $builder->where('status', $status); - }) - ->limit(100) - ->get(); - - $maxId = $tasks->max('id'); - - return $tasks->map(function (StackkitCloudTask $task) use ($maxId) { - return [ - 'uuid' => $task->task_uuid, - 'id' => str_pad((string) $task->id, strlen((string) $maxId), '0', STR_PAD_LEFT), - 'name' => $task->name, - 'status' => $task->status, - 'attempts' => $task->getNumberOfAttempts(), - 'created' => $task->created_at ? $task->created_at->diffForHumans() : null, - 'queue' => $task->queue, - ]; - }); - } - - public function task(string $uuid): array - { - $task = StackkitCloudTask::findByUuid($uuid); - - return [ - 'id' => $task->id, - 'status' => $task->status, - 'queue' => $task->queue, - 'events' => $task->getEvents(), - 'payload' => $task->getPayloadPretty(), - 'exception' => $task->getMetadata()['exception'] ?? null, - ]; - } -} diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index 88e4f8e..51d7cd9 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -13,9 +13,6 @@ use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; -use function Safe\file_get_contents; -use function Safe\json_decode; - class CloudTasksServiceProvider extends LaravelServiceProvider { public function boot(): void @@ -23,11 +20,8 @@ public function boot(): void $this->registerClient(); $this->registerConnector(); $this->registerConfig(); - $this->registerViews(); - $this->registerAssets(); - $this->registerMigrations(); $this->registerRoutes(); - $this->registerDashboard(); + $this->registerEvents(); } private function registerClient(): void @@ -61,38 +55,6 @@ private function registerConfig(): void $this->mergeConfigFrom(__DIR__.'/../config/cloud-tasks.php', 'cloud-tasks'); } - private function registerViews(): void - { - if (CloudTasks::dashboardDisabled()) { - // Larastan needs this view registered to check the service provider correctly. - // return; - } - - $this->loadViewsFrom(__DIR__.'/../views', 'cloud-tasks'); - } - - private function registerAssets(): void - { - if (CloudTasks::dashboardDisabled()) { - return; - } - - $this->publishes([ - __DIR__.'/../dashboard/dist' => public_path('vendor/cloud-tasks'), - ], ['cloud-tasks']); - } - - private function registerMigrations(): void - { - if (CloudTasks::dashboardDisabled()) { - return; - } - - $this->loadMigrationsFrom([ - __DIR__.'/../migrations', - ]); - } - private function registerRoutes(): void { /** @@ -101,46 +63,12 @@ private function registerRoutes(): void $router = $this->app['router']; $router->post('handle-task', [TaskHandler::class, 'handle'])->name('cloud-tasks.handle-task'); - - if (CloudTasks::dashboardDisabled()) { - return; - } - - $router->post('cloud-tasks-api/login', [CloudTasksApiController::class, 'login'])->name('cloud-tasks.api.login'); - $router->get('cloud-tasks/{view?}', function () { - return view('cloud-tasks::layout', [ - 'manifest' => json_decode(file_get_contents(public_path('vendor/cloud-tasks/manifest.json')), true), - 'isDownForMaintenance' => app()->isDownForMaintenance(), - 'cloudTasksScriptVariables' => [ - 'path' => 'cloud-tasks', - ], - ]); - })->where( - 'view', - '(.+)' - )->name( - 'cloud-tasks.index' - ); - - $router->middleware(Authenticate::class)->group(function () use ($router) { - $router->get('cloud-tasks-api/dashboard', [CloudTasksApiController::class, 'dashboard'])->name('cloud-tasks.api.dashboard'); - $router->get('cloud-tasks-api/tasks', [CloudTasksApiController::class, 'tasks'])->name('cloud-tasks.api.tasks'); - $router->get('cloud-tasks-api/task/{uuid}', [CloudTasksApiController::class, 'task'])->name('cloud-tasks.api.task'); - }); } - private function registerDashboard(): void + private function registerEvents(): void { $events = $this->app['events']; - $events->listen(TaskCreated::class, function (TaskCreated $event) { - if (CloudTasks::dashboardDisabled()) { - return; - } - - DashboardService::make()->add($event->queue, $event->task); - }); - $events->listen(JobFailed::class, function (JobFailed $event) { if (! $event->job instanceof CloudTasksJob) { return; @@ -158,10 +86,6 @@ private function registerDashboard(): void if (! $event->job instanceof CloudTasksJob) { return; } - - if (CloudTasks::dashboardEnabled()) { - DashboardService::make()->markAsRunning($event->job->uuid()); - } }); $events->listen(JobProcessed::class, function (JobProcessed $event) { @@ -170,10 +94,6 @@ private function registerDashboard(): void } data_set($event->job->job, 'internal.processed', true); - - if (CloudTasks::dashboardEnabled()) { - DashboardService::make()->markAsSuccessful($event->job->uuid()); - } }); $events->listen(JobExceptionOccurred::class, function (JobExceptionOccurred $event) { @@ -182,30 +102,18 @@ private function registerDashboard(): void } data_set($event->job->job, 'internal.errored', true); - - if (CloudTasks::dashboardEnabled()) { - DashboardService::make()->markAsError($event); - } }); $events->listen(JobFailed::class, function ($event) { if (! $event->job instanceof CloudTasksJob) { return; } - - if (CloudTasks::dashboardEnabled()) { - DashboardService::make()->markAsFailed($event); - } }); $events->listen(JobReleased::class, function (JobReleased $event) { if (! $event->job instanceof CloudTasksJob) { return; } - - if (CloudTasks::dashboardEnabled()) { - DashboardService::make()->markAsReleased($event); - } }); } } diff --git a/src/DashboardService.php b/src/DashboardService.php deleted file mode 100644 index eb17c1d..0000000 --- a/src/DashboardService.php +++ /dev/null @@ -1,177 +0,0 @@ -getHttpRequest() ?: $task->getAppEngineHttpRequest(); - - if (! $httpRequest) { - throw new Exception('Task does not have a HTTP request.'); - } - - return $httpRequest->getBody(); - } - - public function add(string $queue, Task $task): void - { - $uuid = $this->getTaskUuid($task); - - if (StackkitCloudTask::whereTaskUuid($uuid)->exists()) { - return; - } - - $metadata = new TaskMetadata(); - $metadata->payload = $this->getTaskBody($task); - - $data = [ - 'queue' => $queue, - ]; - - $scheduleTime = $task->getScheduleTime(); - - if ($scheduleTime) { - $status = 'scheduled'; - $data['scheduled_at'] = $scheduleTime->toDateTime()->format('Y-m-d H:i:s'); - } else { - $status = 'queued'; - } - - $metadata->addEvent($status, $data); - - DB::table('stackkit_cloud_tasks') - ->insert([ - 'task_uuid' => $uuid, - 'name' => $this->getTaskName($task), - 'queue' => $queue, - 'payload' => $this->getTaskBody($task), - 'status' => $status, - 'metadata' => $metadata->toJson(), - 'created_at' => now()->utc(), - 'updated_at' => now()->utc(), - ]); - } - - public function markAsRunning(string $uuid): void - { - $task = StackkitCloudTask::findByUuid($uuid); - - $task->status = 'running'; - $task->addMetadataEvent([ - 'status' => $task->status, - 'datetime' => now()->utc()->toDateTimeString(), - ]); - - $task->save(); - } - - public function markAsSuccessful(string $uuid): void - { - $task = StackkitCloudTask::findByUuid($uuid); - - if ($task->status === 'released') { - return; - } - - $task->status = 'successful'; - $task->addMetadataEvent([ - 'status' => $task->status, - 'datetime' => now()->utc()->toDateTimeString(), - ]); - - $task->save(); - } - - public function markAsError(JobExceptionOccurred $event): void - { - /** @var CloudTasksJob $job */ - $job = $event->job; - - try { - $task = StackkitCloudTask::findByUuid($job->uuid()); - } catch (ModelNotFoundException $e) { - return; - } - - if ($task->status === 'failed') { - return; - } - - $task->status = 'error'; - $task->addMetadataEvent([ - 'status' => $task->status, - 'datetime' => now()->utc()->toDateTimeString(), - ]); - $task->setMetadata('exception', (string) $event->exception); - - $task->save(); - } - - public function markAsFailed(JobFailed $event): void - { - /** @var CloudTasksJob $job */ - $job = $event->job; - - $task = StackkitCloudTask::findByUuid($job->uuid()); - - $task->status = 'failed'; - $task->addMetadataEvent([ - 'status' => $task->status, - 'datetime' => now()->utc()->toDateTimeString(), - ]); - - $task->save(); - } - - public function markAsReleased(JobReleased $event): void - { - /** @var CloudTasksJob $job */ - $job = $event->job; - - $task = StackkitCloudTask::findByUuid($job->uuid()); - - $task->status = 'released'; - $task->addMetadataEvent([ - 'status' => $task->status, - 'datetime' => now()->utc()->toDateTimeString(), - 'delay' => $event->delay, - ]); - - $task->save(); - } - - private function getTaskName(Task $task): string - { - /** @var array $decode */ - $decode = json_decode($this->getTaskBody($task), true); - - return $decode['displayName']; - } - - private function getTaskUuid(Task $task): string - { - /** @var array $task */ - $task = json_decode($this->getTaskBody($task), true); - - return $task['uuid']; - } -} diff --git a/src/Entities/StatRow.php b/src/Entities/StatRow.php deleted file mode 100644 index 406d982..0000000 --- a/src/Entities/StatRow.php +++ /dev/null @@ -1,25 +0,0 @@ - $value) { - $object->{$key} = $value; - } - - return $object; - } -} diff --git a/tests/CloudTasksDashboardTest.php b/tests/CloudTasksDashboardTest.php deleted file mode 100644 index 58c353b..0000000 --- a/tests/CloudTasksDashboardTest.php +++ /dev/null @@ -1,644 +0,0 @@ -create(); - - // Act - $response = $this->getJson('/cloud-tasks-api/dashboard'); - - // Assert - $response->assertStatus(200); - } - - /** - * @test - */ - public function it_counts_the_number_of_tasks() - { - // Arrange - Carbon::setTestNow(Carbon::parse('2022-01-01 15:15:00')); - $lastMinute = now()->startOfMinute()->subMinute(); - $thisMinute = now()->startOfMinute(); - $thisHour = now()->startOfHour(); - $thisDay = now()->startOfDay(); - - factory(StackkitCloudTask::class)->create(['status' => 'queued', 'created_at' => $thisMinute]); - factory(StackkitCloudTask::class)->create(['status' => 'queued', 'created_at' => $thisHour]); - factory(StackkitCloudTask::class)->create(['status' => 'queued', 'created_at' => $thisDay]); - factory(StackkitCloudTask::class)->create(['status' => 'queued', 'created_at' => $lastMinute]); - - factory(StackkitCloudTask::class)->create(['status' => 'failed', 'created_at' => $thisMinute]); - factory(StackkitCloudTask::class)->create(['status' => 'failed', 'created_at' => $thisHour]); - factory(StackkitCloudTask::class)->create(['status' => 'failed', 'created_at' => $thisDay]); - factory(StackkitCloudTask::class)->create(['status' => 'failed', 'created_at' => $lastMinute]); - - // Act - $response = $this->getJson('/cloud-tasks-api/dashboard'); - - // Assert - $this->assertEquals(2, $response->json('recent.this_minute')); - $this->assertEquals(6, $response->json('recent.this_hour')); - $this->assertEquals(8, $response->json('recent.this_day')); - - $this->assertEquals(1, $response->json('failed.this_minute')); - $this->assertEquals(3, $response->json('failed.this_hour')); - $this->assertEquals(4, $response->json('failed.this_day')); - } - - /** - * @test - */ - public function tasks_shows_newest_first() - { - // Arrange - factory(StackkitCloudTask::class)->create(['created_at' => now()->subMinute()]); - $task = factory(StackkitCloudTask::class)->create(['created_at' => now()]); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks'); - - // Assert - $this->assertEquals($task->task_uuid, $response->json('0.uuid')); - } - - /** - * @test - */ - public function it_shows_tasks_only_from_today() - { - // Arrange - factory(StackkitCloudTask::class)->create(['created_at' => today()]); - factory(StackkitCloudTask::class)->create(['created_at' => today()->subDay()]); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks'); - - // Assert - $this->assertCount(1, $response->json()); - } - - /** - * @test - */ - public function it_can_filter_only_failed_tasks() - { - // Arrange - factory(StackkitCloudTask::class)->create(['status' => 'pending']); - factory(StackkitCloudTask::class)->create(['status' => 'failed']); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks?filter=failed'); - - // Assert - $this->assertCount(1, $response->json()); - } - - /** - * @test - */ - public function it_can_filter_tasks_created_at_exact_time() - { - // Arrange - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(15, 4, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 5, 0)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 5, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 6, 0)]); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks?time=16:05'); - - // Assert - $this->assertCount(2, $response->json()); - } - - /** - * @test - */ - public function it_can_filter_tasks_created_at_exact_hour() - { - // Arrange - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(15, 59, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 5, 59)]); - factory(StackkitCloudTask::class)->create(['created_at' => now()->setTime(16, 32, 32)]); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks?hour=16'); - - // Assert - $this->assertCount(2, $response->json()); - } - - /** - * @test - */ - public function it_can_filter_tasks_by_queue() - { - // Arrange - factory(StackkitCloudTask::class)->create(['queue' => 'barbequeue']); - factory(StackkitCloudTask::class)->create(['queue' => 'barbequeue-priority']); - factory(StackkitCloudTask::class)->create(['queue' => 'barbequeue-priority']); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks?queue=barbequeue-priority'); - - // Assert - $this->assertCount(2, $response->json()); - } - - /** - * @test - */ - public function it_can_filter_tasks_by_status() - { - // Arrange - factory(StackkitCloudTask::class)->create(['status' => 'queued']); - factory(StackkitCloudTask::class)->create(['status' => 'pending']); - factory(StackkitCloudTask::class)->create(['status' => 'failed']); - factory(StackkitCloudTask::class)->create(['status' => 'failed']); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks?status=failed'); - - // Assert - $this->assertCount(2, $response->json()); - } - - /** - * @test - */ - public function it_shows_max_100_tasks() - { - // Arrange - factory(StackkitCloudTask::class)->times(101)->create(); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks'); - - // Assert - $this->assertCount(100, $response->json()); - } - - /** - * @test - */ - public function it_returns_the_correct_task_fields() - { - // Arrange - $task = factory(StackkitCloudTask::class)->create(); - - // Act - $response = $this->getJson('/cloud-tasks-api/tasks'); - - // Assert - $this->assertEquals($task->task_uuid, $response->json('0.uuid')); - $this->assertEquals($task->id, $response->json('0.id')); - $this->assertEquals('SimpleJob', $response->json('0.name')); - $this->assertEquals('queued', $response->json('0.status')); - $this->assertEquals(0, $response->json('0.attempts')); - $this->assertEquals('1 second ago', $response->json('0.created')); - $this->assertEquals('barbequeue', $response->json('0.queue')); - } - - /** - * @test - */ - public function it_returns_info_about_a_specific_task() - { - // Arrange - $task = factory(StackkitCloudTask::class)->create(); - - // Act - $response = $this->getJson('/cloud-tasks-api/task/'.$task->task_uuid); - - // Assert - $this->assertEquals($task->id, $response['id']); - $this->assertEquals('queued', $response['status']); - $this->assertEquals('barbequeue', $response['queue']); - $this->assertEquals([], $response['events']); - $this->assertEquals('[]', $response['payload']); - $this->assertEquals(null, $response['exception']); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_is_dispatched_it_will_be_added_to_the_dashboard(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - CloudTasksApi::fake(); - $tasksBefore = StackkitCloudTask::count(); - $job = $this->dispatch(new SimpleJob()); - $tasksAfter = StackkitCloudTask::count(); - - // Assert - $task = StackkitCloudTask::first(); - $this->assertSame(0, $tasksBefore); - $this->assertSame(1, $tasksAfter); - $this->assertDatabaseHas((new StackkitCloudTask())->getTable(), [ - 'queue' => 'barbequeue', - 'status' => 'queued', - 'name' => SimpleJob::class, - ]); - $this->assertSame($task->getMetadata()['payload'], $job->payload); - } - - /** - * @test - */ - public function when_dashboard_is_disabled_jobs_will_not_be_added_to_the_dashboard() - { - // Arrange - CloudTasksApi::fake(); - config()->set('cloud-tasks.dashboard.enabled', false); - - // Act - $this->dispatch(new SimpleJob()); - - // Assert - $this->assertDatabaseCount((new StackkitCloudTask())->getTable(), 0); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_is_scheduled_it_will_be_added_as_such(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - CloudTasksApi::fake(); - Carbon::setTestNow(now()); - $tasksBefore = StackkitCloudTask::count(); - - $job = $this->dispatch((new SimpleJob())->delay(now()->addSeconds(10))); - $tasksAfter = StackkitCloudTask::count(); - - // Assert - $task = StackkitCloudTask::first(); - $this->assertSame(0, $tasksBefore); - $this->assertSame(1, $tasksAfter); - $this->assertDatabaseHas((new StackkitCloudTask())->getTable(), [ - 'queue' => 'barbequeue', - 'status' => 'scheduled', - 'name' => SimpleJob::class, - ]); - $this->assertEquals(now()->addSeconds(10)->toDateTimeString(), $task->getEvents()[0]['scheduled_at']); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_is_running_it_will_be_updated_in_the_dashboard(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - Carbon::setTestNow(now()); - CloudTasksApi::fake(); - OpenIdVerificator::fake(); - - $this->dispatch(new SimpleJob())->run(); - - // Assert - $task = StackkitCloudTask::firstOrFail(); - $events = $task->getEvents(); - $this->assertCount(3, $events); - $this->assertEquals( - [ - 'status' => 'running', - 'datetime' => now()->toDateTimeString(), - 'diff' => '1 second ago', - ], - $events[1] - ); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_is_successful_it_will_be_updated_in_the_dashboard(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - Carbon::setTestNow(now()); - CloudTasksApi::fake(); - OpenIdVerificator::fake(); - - $this->dispatch(new SimpleJob())->run(); - - // Assert - $task = StackkitCloudTask::firstOrFail(); - $events = $task->getEvents(); - $this->assertCount(3, $events); - $this->assertEquals( - [ - 'status' => 'successful', - 'datetime' => now()->toDateTimeString(), - 'diff' => '1 second ago', - ], - $events[2] - ); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_errors_it_will_be_updated_in_the_dashboard(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - Carbon::setTestNow(now()); - CloudTasksApi::fake(); - OpenIdVerificator::fake(); - - $this->dispatch(new FailingJob())->run(); - - // Assert - $task = StackkitCloudTask::firstOrFail(); - $events = $task->getEvents(); - $this->assertCount(3, $events); - $this->assertEquals( - [ - 'status' => 'error', - 'datetime' => now()->toDateTimeString(), - 'diff' => '1 second ago', - ], - $events[2] - ); - $this->assertStringContainsString('Error: simulating a failing job', $task->getMetadata()['exception']); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_fails_it_will_be_updated_in_the_dashboard(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - Carbon::setTestNow(now()); - CloudTasksApi::fake(); - OpenIdVerificator::fake(); - - $job = $this->dispatch(new FailingJobWithMaxTries()); - $releasedJob = $job->runAndGetReleasedJob(); - $releasedJob = $releasedJob->runAndGetReleasedJob(); - $releasedJob->run(); - - // Assert - $task = StackkitCloudTask::firstOrFail(); - $events = $task->getEvents(); - $this->assertCount(7, $events); - $this->assertEquals( - [ - 'status' => 'failed', - 'datetime' => now()->toDateTimeString(), - 'diff' => '1 second ago', - ], - $events[6] - ); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function when_a_job_is_released_it_will_be_updated_in_the_dashboard(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - Carbon::setTestNow(now()); - CloudTasksApi::fake(); - OpenIdVerificator::fake(); - - $this->dispatch(new JobThatWillBeReleased())->run(); - - // Assert - $task = StackkitCloudTask::firstOrFail(); - $events = $task->getEvents(); - - $this->assertCount(3, $events); - $this->assertEquals( - [ - 'status' => 'released', - 'datetime' => now()->toDateTimeString(), - 'diff' => '1 second ago', - 'delay' => 0, - ], - $events[2] - ); - } - - /** - * @test - * - * @testWith [{"task_type": "http"}] - * [{"task_type": "appengine"}] - */ - public function job_release_delay_is_added_to_the_metadata(array $test) - { - // Arrange - $this->withTaskType($test['task_type']); - - Carbon::setTestNow(now()); - CloudTasksApi::fake(); - OpenIdVerificator::fake(); - - $this->dispatch(new JobThatWillBeReleased(15))->run(); - - // Assert - $task = StackkitCloudTask::firstOrFail(); - $events = $task->getEvents(); - - $this->assertCount(3, $events); - $this->assertEquals( - [ - 'status' => 'released', - 'datetime' => now()->toDateTimeString(), - 'diff' => '1 second ago', - 'delay' => 15, - ], - $events[2] - ); - } - - /** - * @test - */ - public function test_publish() - { - // Arrange - config()->set('cloud-tasks.dashboard.enabled', true); - - // Act & Assert - $expectedPublishBase = dirname(__DIR__); - - $this->artisan('vendor:publish --tag=cloud-tasks --force') - ->expectsOutputToContain('Publishing [cloud-tasks] assets.') - ->expectsOutputToContain('Copying file ['.$expectedPublishBase.'/config/cloud-tasks.php] to [config/cloud-tasks.php]') - ->expectsOutputToContain('Copying directory ['.$expectedPublishBase.'/dashboard/dist] to [public/vendor/cloud-tasks]'); - - } - - /** - * @test - */ - public function when_dashboard_is_enabled_it_adds_the_necessary_routes() - { - // Act - $routes = app(Router::class)->getRoutes(); - - // Assert - $this->assertInstanceOf(Route::class, $routes->getByName('cloud-tasks.handle-task')); - $this->assertInstanceOf(Route::class, $routes->getByName('cloud-tasks.index')); - $this->assertInstanceOf(Route::class, $routes->getByName('cloud-tasks.api.dashboard')); - $this->assertInstanceOf(Route::class, $routes->getByName('cloud-tasks.api.tasks')); - $this->assertInstanceOf(Route::class, $routes->getByName('cloud-tasks.api.task')); - } - - /** - * @test - */ - public function when_dashboard_is_enabled_it_adds_the_necessary_migrations() - { - $this->assertTrue(in_array(dirname(__DIR__).'/src/../migrations', app('migrator')->paths())); - } - - /** - * @test - */ - public function when_dashboard_is_disabled_it_adds_the_necessary_migrations() - { - $this->assertEmpty(app('migrator')->paths()); - } - - /** - * @test - */ - public function when_dashboard_is_disabled_it_does_not_add_the_dashboard_routes() - { - // Act - $routes = app(Router::class)->getRoutes(); - - // Assert - $this->assertInstanceOf(Route::class, $routes->getByName('cloud-tasks.handle-task')); - $this->assertNull($routes->getByName('cloud-tasks.index')); - $this->assertNull($routes->getByName('cloud-tasks.api.dashboard')); - $this->assertNull($routes->getByName('cloud-tasks.api.tasks')); - $this->assertNull($routes->getByName('cloud-tasks.api.task')); - } - - /** - * @test - */ - public function dashboard_is_password_protected() - { - // Arrange - $this->defaultHeaders['Authorization'] = ''; - - // Act - $response = $this->getJson('/cloud-tasks-api/dashboard'); - - // Assert - $this->assertEquals(403, $response->status()); - } - - /** - * @test - */ - public function can_enter_with_token() - { - // Arrange - $this->defaultHeaders['Authorization'] = 'Bearer '.encrypt(time() + 10); - - // Act - $response = $this->getJson('/cloud-tasks-api/dashboard'); - - // Assert - $this->assertEquals(200, $response->status()); - } - - /** - * @test - */ - public function token_can_expire() - { - // Arrange - $this->defaultHeaders['Authorization'] = 'Bearer '.encrypt(Carbon::create(2020, 5, 15, 15, 15, 15)->timestamp); - - // Act & Assert - Carbon::setTestNow(Carbon::create(2020, 5, 15, 15, 15, 14)); - $this->assertEquals(200, $this->getJson('/cloud-tasks-api/dashboard')->status()); - Carbon::setTestNow(Carbon::create(2020, 5, 15, 15, 15, 15)); - $this->assertEquals(403, $this->getJson('/cloud-tasks-api/dashboard')->status()); - } - - /** - * @test - */ - public function there_is_a_login_endpoint() - { - // Arrange - Carbon::setTestNow($now = now()); - config()->set('cloud-tasks.dashboard.password', 'test123'); - - // Act - $invalidPassword = $this->postJson('/cloud-tasks-api/login', ['password' => 'hey']); - $validPassword = $this->postJson('/cloud-tasks-api/login', ['password' => 'test123']); - - // Assert - $this->assertSame('', $invalidPassword->content()); - $this->assertStringStartsWith('ey', $validPassword->content()); - $validUntil = decrypt($validPassword->content()); - - // the token should be valid for 15 minutes. - $this->assertSame($now->timestamp + 900, $validUntil); - } -} diff --git a/views/layout.blade.php b/views/layout.blade.php deleted file mode 100644 index c7f0474..0000000 --- a/views/layout.blade.php +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - Cloud Tasks for Laravel - - - - - @foreach ($manifest['index.html']['css'] as $css) - - @endforeach - - -
- - - - - - From db3dc1735edb6c5d9b0970fb1c121891e869aad5 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Thu, 18 Jan 2024 22:04:05 +0100 Subject: [PATCH 09/46] Remove trailing comma --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f4d259e..1eec0a3 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,6 @@ "l10": [ "composer require laravel/framework:10.* orchestra/testbench:8.* --no-interaction --no-update", "composer update --prefer-stable --prefer-dist --no-interaction" - ], + ] } } From bd12aab3d38d2f38a27c55fc703a3440af3d28fa Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 11:47:01 +0100 Subject: [PATCH 10/46] Remove dashboard remaining files --- src/StackkitCloudTask.php | 122 -------------------------------------- src/TaskMetadata.php | 53 ----------------- 2 files changed, 175 deletions(-) delete mode 100644 src/StackkitCloudTask.php delete mode 100644 src/TaskMetadata.php diff --git a/src/StackkitCloudTask.php b/src/StackkitCloudTask.php deleted file mode 100644 index 2d83bae..0000000 --- a/src/StackkitCloudTask.php +++ /dev/null @@ -1,122 +0,0 @@ -firstOrFail(); - } - - /** - * @param Builder $builder - * @return Builder - */ - public function scopeNewestFirst(Builder $builder): Builder - { - return $builder->orderByDesc('created_at'); - } - - /** - * @param Builder $builder - * @return Builder - */ - public function scopeFailed(Builder $builder): Builder - { - return $builder->whereStatus('failed'); - } - - public function getMetadata(): array - { - $value = $this->metadata; - - if (is_null($value)) { - return []; - } - - $decoded = json_decode($value, true); - - return is_array($decoded) ? $decoded : []; - } - - public function getNumberOfAttempts(): int - { - return collect($this->getEvents()) - ->where('status', 'running') - ->count(); - } - - /** - * @param mixed $value - */ - public function setMetadata(string $key, $value): void - { - $metadata = $this->getMetadata(); - - Arr::set($metadata, $key, $value); - - $this->metadata = json_encode($metadata); - } - - public function addMetadataEvent(array $event): void - { - $metadata = $this->getMetadata(); - - $metadata['events'] ??= []; - - $metadata['events'][] = $event; - - $this->metadata = json_encode($metadata); - } - - public function getEvents(): array - { - Carbon::setTestNowAndTimezone(now()->utc()); - - /** @var array $events */ - $events = Arr::get($this->getMetadata(), 'events', []); - - return collect($events)->map(function ($event) { - /** @var array $event */ - $event['diff'] = Carbon::parse($event['datetime'])->diffForHumans(); - - return $event; - })->toArray(); - } - - public function getPayloadPretty(): string - { - $payload = $this->getMetadata()['payload'] ?? '[]'; - - return json_encode( - json_decode($payload), - JSON_PRETTY_PRINT - ); - } -} diff --git a/src/TaskMetadata.php b/src/TaskMetadata.php deleted file mode 100644 index 2451a39..0000000 --- a/src/TaskMetadata.php +++ /dev/null @@ -1,53 +0,0 @@ - $status, - 'datetime' => now()->utc()->toDateTimeString(), - ]; - - $this->events[] = array_merge($additional, $event); - } - - public function toArray(): array - { - return [ - 'events' => $this->events, - 'payload' => $this->payload, - ]; - } - - public function toJson(): string - { - return json_encode($this->toArray()); - } - - public static function createFromArray(array $data): TaskMetadata - { - $metadata = new TaskMetadata(); - - $metadata->events = $data['events']; - $metadata->payload = $data['payload']; - - return $metadata; - } -} From bcf92bc58ed41f69268c8f8b17e5774a719ced6f Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 11:53:25 +0100 Subject: [PATCH 11/46] Replace deprecated client --- src/CloudTasksApiConcrete.php | 2 +- src/CloudTasksConnector.php | 2 +- src/CloudTasksQueue.php | 2 +- src/CloudTasksServiceProvider.php | 2 +- src/TaskHandler.php | 2 +- tests/CloudTasksApiTest.php | 2 +- tests/TestCase.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CloudTasksApiConcrete.php b/src/CloudTasksApiConcrete.php index 4e09517..9ebb52b 100644 --- a/src/CloudTasksApiConcrete.php +++ b/src/CloudTasksApiConcrete.php @@ -4,7 +4,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\Task; class CloudTasksApiConcrete implements CloudTasksApiContract diff --git a/src/CloudTasksConnector.php b/src/CloudTasksConnector.php index c91ec24..3f511b5 100644 --- a/src/CloudTasksConnector.php +++ b/src/CloudTasksConnector.php @@ -4,7 +4,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Queue\Connectors\ConnectorInterface; class CloudTasksConnector implements ConnectorInterface diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index f7518dd..3b1edcf 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -6,7 +6,7 @@ use Google\Cloud\Tasks\V2\AppEngineHttpRequest; use Google\Cloud\Tasks\V2\AppEngineRouting; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\HttpMethod; use Google\Cloud\Tasks\V2\HttpRequest; use Google\Cloud\Tasks\V2\OidcToken; diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index 51d7cd9..3c04af8 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -4,7 +4,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Queue\Events\JobExceptionOccurred; use Illuminate\Queue\Events\JobFailed; use Illuminate\Queue\Events\JobProcessed; diff --git a/src/TaskHandler.php b/src/TaskHandler.php index c4cba6a..9fdc5ce 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -5,7 +5,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Google\ApiCore\ApiException; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Queue\WorkerOptions; use Illuminate\Support\Str; diff --git a/tests/CloudTasksApiTest.php b/tests/CloudTasksApiTest.php index e78c275..c36d988 100644 --- a/tests/CloudTasksApiTest.php +++ b/tests/CloudTasksApiTest.php @@ -5,7 +5,7 @@ namespace Tests; use Google\ApiCore\ApiException; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\HttpMethod; use Google\Cloud\Tasks\V2\HttpRequest; use Google\Cloud\Tasks\V2\Task; diff --git a/tests/TestCase.php b/tests/TestCase.php index a698b97..7a6d877 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -7,7 +7,7 @@ use Closure; use Firebase\JWT\JWT; use Google\ApiCore\ApiException; -use Google\Cloud\Tasks\V2\CloudTasksClient; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\Task; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Queue\Events\JobReleasedAfterException; From a99a0e9ee9e27ce036e763c7d3904c52620e2496 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 11:59:16 +0100 Subject: [PATCH 12/46] Update api requests with new client options --- src/CloudTasksApiConcrete.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/CloudTasksApiConcrete.php b/src/CloudTasksApiConcrete.php index 9ebb52b..176c06e 100644 --- a/src/CloudTasksApiConcrete.php +++ b/src/CloudTasksApiConcrete.php @@ -5,6 +5,9 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; +use Google\Cloud\Tasks\V2\CreateTaskRequest; +use Google\Cloud\Tasks\V2\DeleteTaskRequest; +use Google\Cloud\Tasks\V2\GetTaskRequest; use Google\Cloud\Tasks\V2\Task; class CloudTasksApiConcrete implements CloudTasksApiContract @@ -21,16 +24,23 @@ public function __construct(CloudTasksClient $client) public function createTask(string $queueName, Task $task): Task { - return $this->client->createTask($queueName, $task); + return $this->client->createTask(new CreateTaskRequest([ + 'parent' => $queueName, + 'task' => $task, + ])); } public function deleteTask(string $taskName): void { - $this->client->deleteTask($taskName); + $this->client->deleteTask(new DeleteTaskRequest([ + 'name' => $taskName, + ])); } public function getTask(string $taskName): Task { - return $this->client->getTask($taskName); + return $this->client->getTask(new GetTaskRequest([ + 'name' => $taskName, + ])); } } From 0728bb50609fadf102dc7df493f910981d53b7f7 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 14:35:33 +0100 Subject: [PATCH 13/46] Refactor --- composer.json | 1 + src/CloudTasksApi.php | 2 +- src/CloudTasksApiConcrete.php | 9 +--- src/CloudTasksConnector.php | 2 +- src/CloudTasksJob.php | 35 +++++++------- src/CloudTasksQueue.php | 79 ++++++++++++------------------- src/CloudTasksServiceProvider.php | 9 ++-- src/Events/JobReleased.php | 26 +--------- src/TaskHandler.php | 16 +++---- 9 files changed, 66 insertions(+), 113 deletions(-) diff --git a/composer.json b/composer.json index f98b48e..436095e 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,7 @@ } ], "require": { + "php": "^8.1", "ext-json": "*", "phpseclib/phpseclib": "^3.0", "google/auth": "^v1.29.1", diff --git a/src/CloudTasksApi.php b/src/CloudTasksApi.php index e0c04a2..31643d1 100644 --- a/src/CloudTasksApi.php +++ b/src/CloudTasksApi.php @@ -14,7 +14,7 @@ */ class CloudTasksApi extends Facade { - protected static function getFacadeAccessor() + protected static function getFacadeAccessor(): string { return 'cloud-tasks-api'; } diff --git a/src/CloudTasksApiConcrete.php b/src/CloudTasksApiConcrete.php index 176c06e..7afe805 100644 --- a/src/CloudTasksApiConcrete.php +++ b/src/CloudTasksApiConcrete.php @@ -12,14 +12,9 @@ class CloudTasksApiConcrete implements CloudTasksApiContract { - /** - * @var CloudTasksClient - */ - private $client; - - public function __construct(CloudTasksClient $client) + public function __construct(private readonly CloudTasksClient $client) { - $this->client = $client; + // } public function createTask(string $queueName, Task $task): Task diff --git a/src/CloudTasksConnector.php b/src/CloudTasksConnector.php index 3f511b5..aeaac7c 100644 --- a/src/CloudTasksConnector.php +++ b/src/CloudTasksConnector.php @@ -9,7 +9,7 @@ class CloudTasksConnector implements ConnectorInterface { - public function connect(array $config) + public function connect(array $config): CloudTasksQueue { // The handler is the URL which Cloud Tasks will call with the job payload. This // URL of the handler can be manually set through an environment variable, but diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index bb10496..0b16a96 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -13,27 +13,26 @@ class CloudTasksJob extends LaravelJob implements JobContract { - /** - * The Cloud Tasks raw job payload (request payload). - */ + protected $container; + + private CloudTasksQueue $cloudTasksQueue; + public array $job; - /** - * @var CloudTasksQueue - */ - public $cloudTasksQueue; + protected $connectionName; - public function __construct(array $job, CloudTasksQueue $cloudTasksQueue) + protected $queue; + + public function __construct(Container $container, CloudTasksQueue $cloudTasksQueue, $job, $connectionName, $queue) { - $this->job = $job; - $this->container = Container::getInstance(); + $this->container = $container; $this->cloudTasksQueue = $cloudTasksQueue; - - $command = TaskHandler::getCommandProperties($job['data']['command']); - $this->queue = $command['queue'] ?? config('queue.connections.'.config('queue.default').'.queue'); + $this->job = $job; + $this->connectionName = $connectionName; + $this->queue = $queue; } - public function job() + public function job(): array { return $this->job; } @@ -63,9 +62,9 @@ public function setAttempts(int $attempts): void $this->job['internal']['attempts'] = $attempts; } - public function setQueue(string $queue): void + public function getTaskName(): string { - $this->queue = $queue; + return $this->job['internal']['taskName']; } public function delete(): void @@ -95,9 +94,9 @@ public function hasError(): bool return data_get($this->job, 'internal.errored') === true; } - public function release($delay = 0) + public function release($delay = 0): void { - parent::release(); + parent::release($delay); $this->cloudTasksQueue->release($this, $delay); diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 3b1edcf..200a24a 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -20,30 +20,21 @@ use function Safe\json_decode; use function Safe\json_encode; +use function Safe\preg_replace; class CloudTasksQueue extends LaravelQueue implements QueueContract { - /** - * @var CloudTasksClient - */ - private $client; - - public array $config; - - public function __construct(array $config, CloudTasksClient $client, $dispatchAfterCommit = false) + public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false) { - $this->client = $client; - $this->config = $config; - $this->dispatchAfterCommit = $dispatchAfterCommit; + // } /** * Get the size of the queue. * * @param string|null $queue - * @return int */ - public function size($queue = null) + public function size($queue = null): int { // It is not possible to know the number of tasks in the queue. return 0; @@ -61,7 +52,7 @@ public function push($job, $data = '', $queue = null) { return $this->enqueueUsing( $job, - $this->createPayload($job, $this->getQueue($queue), $data), + $this->createPayload($job, $queue, $data), $queue, null, function ($payload, $queue) { @@ -97,7 +88,7 @@ public function later($delay, $job, $data = '', $queue = null) { return $this->enqueueUsing( $job, - $this->createPayload($job, $this->getQueue($queue), $data), + $this->createPayload($job, $queue, $data), $queue, $delay, function ($payload, $queue, $delay) { @@ -116,7 +107,7 @@ function ($payload, $queue, $delay) { */ protected function pushToCloudTasks($queue, $payload, $delay = 0) { - $queue = $this->getQueue($queue); + $queue = $queue ?: $this->config['queue']; $queueName = $this->client->queueName($this->config['project'], $this->config['location'], $queue); $availableAt = $this->availableAt($delay); @@ -127,9 +118,13 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) // value and need to manually set and update the number of times a task has been attempted. $payload = $this->withAttempts($payload); - $task = $this->createTask(); + $payload = $this->withQueueName($payload, $queue); + + $task = new Task(); $task->setName($this->taskName($queue, $payload)); + $payload = $this->withTaskName($payload, $task->getName()); + if (! empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); @@ -144,7 +139,7 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) } $task->setAppEngineHttpRequest($appEngineRequest); } else { - $httpRequest = $this->createHttpRequest(); + $httpRequest = new HttpRequest(); $httpRequest->setUrl($this->getHandler()); $httpRequest->setHttpMethod(HttpMethod::POST); @@ -189,7 +184,7 @@ private function taskName(string $queueName, array $payload): string ); } - private function sanitizeTaskName(string $taskName) + private function sanitizeTaskName(string $taskName): string { // Remove all characters that are not -, letters, numbers, or whitespace $sanitizedName = preg_replace('![^-\pL\pN\s]+!u', '-', $taskName); @@ -209,6 +204,20 @@ private function withAttempts(array $payload): array return $payload; } + private function withQueueName(array $payload, string $queueName): array + { + $payload['internal']['queue'] = $queueName; + + return $payload; + } + + private function withTaskName(array $payload, string $taskName): array + { + $payload['internal']['taskName'] = $taskName; + + return $payload; + } + /** * Pop the next job off of the queue. * @@ -217,35 +226,12 @@ private function withAttempts(array $payload): array */ public function pop($queue = null) { - // TODO: Implement pop() method. - } - - private function getQueue(?string $queue = null): string - { - return $queue ?: $this->config['queue']; - } - - private function createHttpRequest(): HttpRequest - { - return app(HttpRequest::class); + // } public function delete(CloudTasksJob $job): void { - $config = $this->config; - - $queue = $job->getQueue() ?: $this->config['queue']; // @todo: make this a helper method somewhere. - - $headerTaskName = request()->headers->get('X-Cloudtasks-Taskname') - ?? request()->headers->get('X-AppEngine-TaskName'); - $taskName = $this->client->taskName( - $config['project'], - $config['location'], - $queue, - (string) $headerTaskName - ); - - CloudTasksApi::deleteTask($taskName); + CloudTasksApi::deleteTask($job->getTaskName()); } public function release(CloudTasksJob $job, int $delay = 0): void @@ -259,11 +245,6 @@ public function release(CloudTasksJob $job, int $delay = 0): void $this->pushRaw($payload, $job->getQueue(), $options); } - private function createTask(): Task - { - return app(Task::class); - } - public function getHandler(): string { return Config::getHandler($this->config['handler']); diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index 3c04af8..8a5802d 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -11,7 +11,6 @@ use Illuminate\Queue\Events\JobProcessing; use Illuminate\Support\ServiceProvider as LaravelServiceProvider; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; -use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; class CloudTasksServiceProvider extends LaravelServiceProvider { @@ -74,11 +73,11 @@ private function registerEvents(): void return; } - $config = $event->job->cloudTasksQueue->config; - app('queue.failer')->log( - $config['connection'], $event->job->getQueue() ?: $config['queue'], - $event->job->getRawBody(), $event->exception + $event->job->getConnectionName(), + $event->job->getQueue(), + $event->job->getRawBody(), + $event->exception, ); }); diff --git a/src/Events/JobReleased.php b/src/Events/JobReleased.php index 530f1e8..e5fbb62 100644 --- a/src/Events/JobReleased.php +++ b/src/Events/JobReleased.php @@ -8,30 +8,8 @@ class JobReleased { - /** - * The connection name. - */ - public string $connectionName; - - /** - * The job instance. - */ - public Job $job; - - /** - * The job delay in seconds. - */ - public int $delay; - - /** - * Create a new event instance. - * - * @return void - */ - public function __construct(string $connectionName, Job $job, int $delay = 0) + public function __construct(public string $connectionName, public Job $job, public int $delay = 0) { - $this->job = $job; - $this->connectionName = $connectionName; - $this->delay = $delay; + // } } diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 9fdc5ce..f439360 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -6,6 +6,7 @@ use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; +use Illuminate\Container\Container; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Queue\WorkerOptions; use Illuminate\Support\Str; @@ -120,17 +121,16 @@ private function guard(): void private function handleTask(array $task): void { - $job = new CloudTasksJob($task, $this->queue); - - $fullTaskName = $this->client->taskName( - $this->config['project'], - $this->config['location'], - $job->getQueue() ?: $this->config['queue'], - request()->header('X-CloudTasks-TaskName') ?? request()->header('X-AppEngine-TaskName'), + $job = new CloudTasksJob( + Container::getInstance(), + $this->queue, + $task, + $this->config['connection'], + $task['internal']['queue'], ); try { - $apiTask = CloudTasksApi::getTask($fullTaskName); + $apiTask = CloudTasksApi::getTask($task['internal']['taskName']); } catch (ApiException $e) { if (in_array($e->getStatus(), ['NOT_FOUND', 'PRECONDITION_FAILED'])) { abort(404); From e6a795d2c5c828ab7bf9e57aff445795c31fc906 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 15:39:06 +0100 Subject: [PATCH 14/46] Refactor & cleanup --- src/CloudTasksJob.php | 5 +- src/CloudTasksQueue.php | 17 +++--- src/TaskHandler.php | 112 ++++++++------------------------------ tests/QueueTest.php | 5 +- tests/TaskHandlerTest.php | 83 ---------------------------- tests/TestCase.php | 28 ++++++---- 6 files changed, 55 insertions(+), 195 deletions(-) diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 0b16a96..1fe4b94 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -100,11 +100,8 @@ public function release($delay = 0): void $this->cloudTasksQueue->release($this, $delay); - $properties = TaskHandler::getCommandProperties($this->job['data']['command']); - $connection = $properties['connection'] ?? config('queue.default'); - if (! data_get($this->job, 'internal.errored')) { - app('events')->dispatch(new JobReleased($connection, $this, $delay)); + app('events')->dispatch(new JobReleased($this->getConnectionName(), $this, $delay)); } } } diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 200a24a..630e6cf 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -113,17 +113,13 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = json_decode($payload, true); - // Since 3.x tasks are released back onto the queue after an exception has - // been thrown. This means we lose the native [X-CloudTasks-TaskRetryCount] header - // value and need to manually set and update the number of times a task has been attempted. - $payload = $this->withAttempts($payload); - - $payload = $this->withQueueName($payload, $queue); - $task = new Task(); $task->setName($this->taskName($queue, $payload)); + $payload = $this->withAttempts($payload); + $payload = $this->withQueueName($payload, $queue); $payload = $this->withTaskName($payload, $task->getName()); + $payload = $this->withConnectionName($payload, $this->getConnectionName()); if (! empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); @@ -218,6 +214,13 @@ private function withTaskName(array $payload, string $taskName): array return $payload; } + private function withConnectionName(array $payload, string $connectionName): array + { + $payload['internal']['connection'] = $connectionName; + + return $payload; + } + /** * Pop the next job off of the queue. * diff --git a/src/TaskHandler.php b/src/TaskHandler.php index f439360..15981aa 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -7,11 +7,9 @@ use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Container\Container; -use Illuminate\Contracts\Encryption\Encrypter; +use Illuminate\Queue\Worker; use Illuminate\Queue\WorkerOptions; -use Illuminate\Support\Str; -use Illuminate\Validation\ValidationException; -use Safe\Exceptions\JsonException; +use Throwable; use function Safe\json_decode; @@ -39,72 +37,15 @@ public function __construct(CloudTasksClient $client) public function handle(?string $task = null): void { - $task = $this->captureTask($task); + $task = json_decode((string) $task ?: request()->getContent(), assoc: true); - $this->loadQueueConnectionConfiguration($task); - - $this->setQueue(); + $this->config = config('queue.connections.'.$task['internal']['connection']); $this->guard(); $this->handleTask($task); } - /** - * @param string|array|null $task - * - * @throws JsonException - */ - private function captureTask($task): array - { - $task = $task ?: (string) (request()->getContent()); - - try { - $array = json_decode($task, true); - } catch (JsonException $e) { - $array = []; - } - - $validator = validator([ - 'json' => $task, - 'task' => $array, - ], [ - 'json' => 'required|json', - 'task' => 'required|array', - 'task.data' => 'required|array', - ]); - - try { - $validator->validate(); - } catch (ValidationException $e) { - if (config('app.debug')) { - throw $e; - } else { - abort(404); - } - } - - return json_decode($task, true); - } - - private function loadQueueConnectionConfiguration(array $task): void - { - $command = self::getCommandProperties($task['data']['command']); - $connection = $command['connection'] ?? config('queue.default'); - $baseConfig = config('queue.connections.'.$connection); - $config = (new CloudTasksConnector())->connect($baseConfig)->config; - - // The connection name from the config may not be the actual connection name - $config['connection'] = $connection; - - $this->config = $config; - } - - private function setQueue(): void - { - $this->queue = new CloudTasksQueue($this->config, $this->client); - } - private function guard(): void { $appEngine = ! empty($this->config['app_engine']); @@ -121,18 +62,25 @@ private function guard(): void private function handleTask(array $task): void { + $queue = new CloudTasksQueue( + config: $this->config, + client: $this->client, + ); + + $queue->setConnectionName($task['internal']['connection']); + $job = new CloudTasksJob( - Container::getInstance(), - $this->queue, - $task, - $this->config['connection'], - $task['internal']['queue'], + container: Container::getInstance(), + cloudTasksQueue: $queue, + job: $task, + connectionName: $task['internal']['connection'], + queue: $task['internal']['queue'], ); try { - $apiTask = CloudTasksApi::getTask($task['internal']['taskName']); - } catch (ApiException $e) { - if (in_array($e->getStatus(), ['NOT_FOUND', 'PRECONDITION_FAILED'])) { + CloudTasksApi::getTask($task['internal']['taskName']); + } catch (Throwable $e) { + if ($e instanceof ApiException && in_array($e->getStatus(), ['NOT_FOUND', 'PRECONDITION_FAILED'])) { abort(404); } @@ -141,23 +89,11 @@ private function handleTask(array $task): void $job->setAttempts($job->attempts() + 1); - app('queue.worker')->process($this->config['connection'], $job, $this->getWorkerOptions()); - } - - public static function getCommandProperties(string $command): array - { - if (Str::startsWith($command, 'O:')) { - return (array) unserialize($command, ['allowed_classes' => false]); - } - - if (app()->bound(Encrypter::class)) { - return (array) unserialize( - app(Encrypter::class)->decrypt($command), - ['allowed_classes' => ['Illuminate\Support\Carbon']] - ); - } - - return []; + tap(app('queue.worker'), fn (Worker $worker) => $worker->process( + connectionName: $job->getConnectionName(), + job: $job, + options: $this->getWorkerOptions() + )); } public function getWorkerOptions(): WorkerOptions diff --git a/tests/QueueTest.php b/tests/QueueTest.php index e459991..afab4cc 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -19,7 +19,6 @@ use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; use Stackkit\LaravelGoogleCloudTasksQueue\OpenIdVerificator; -use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; use Tests\Support\JobThatWillBeReleased; @@ -154,7 +153,7 @@ public function it_posts_the_task_the_correct_queue() // Assert CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool { $decoded = json_decode($task->getHttpRequest()->getBody(), true); - $command = TaskHandler::getCommandProperties($decoded['data']['command']); + $command = $this->getCommandProperties($decoded['data']['command']); return $decoded['displayName'] === SimpleJob::class && ($command['queue'] ?? null) === null @@ -163,7 +162,7 @@ public function it_posts_the_task_the_correct_queue() CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool { $decoded = json_decode($task->getHttpRequest()->getBody(), true); - $command = TaskHandler::getCommandProperties($decoded['data']['command']); + $command = $this->getCommandProperties($decoded['data']['command']); return $decoded['displayName'] === FailingJob::class && $command['queue'] === 'my-special-queue' diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index e795268..1e7b6b8 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -16,7 +16,6 @@ use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksException; use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; use Stackkit\LaravelGoogleCloudTasksQueue\OpenIdVerificator; -use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; use Tests\Support\EncryptedJob; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithMaxTries; @@ -34,88 +33,6 @@ protected function setUp(): void CloudTasksApi::fake(); } - /** - * @test - * - * @testWith [true] - * [false] - */ - public function it_returns_responses_for_empty_payloads($debug) - { - // Arrange - config()->set('app.debug', $debug); - - // Act - $response = $this->postJson(action([TaskHandler::class, 'handle'])); - - // Assert - if ($debug) { - $response->assertJsonValidationErrors('task'); - } else { - $response->assertNotFound(); - } - } - - /** - * @test - * - * @testWith [true] - * [false] - */ - public function it_returns_responses_for_invalid_json($debug) - { - // Arrange - config()->set('app.debug', $debug); - - // Act - $response = $this->call( - 'POST', - action([TaskHandler::class, 'handle']), - [], - [], - [], - [ - 'HTTP_ACCEPT' => 'application/json', - ], - 'test', - ); - - // Assert - if ($debug) { - $response->assertJsonValidationErrors('task'); - } else { - $response->assertNotFound(); - } - } - - /** - * @test - * - * @testWith ["{\"invalid\": \"data\"}"] - * ["{\"data\": \"\"}"] - * ["{\"data\": \"test\"}"] - */ - public function it_returns_responses_for_invalid_payloads(string $payload) - { - // Arrange - - // Act - $response = $this->call( - 'POST', - action([TaskHandler::class, 'handle']), - [], - [], - [], - [ - 'HTTP_ACCEPT' => 'application/json', - ], - $payload, - ); - - // Assert - $response->assertJsonValidationErrors('task.data'); - } - /** * @test */ diff --git a/tests/TestCase.php b/tests/TestCase.php index 7a6d877..e8740f7 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,10 +9,12 @@ use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\Task; +use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Queue\Events\JobReleasedAfterException; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Str; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; @@ -134,16 +136,6 @@ public function dispatch($job) $payload = $request->getBody(); $payloadAsArray = json_decode($payload, true); $task = $event->task; - - [,,,,,,,$taskName] = explode('/', $task->getName()); - - if ($task->hasHttpRequest()) { - request()->headers->set('X-Cloudtasks-Taskname', $taskName); - } - - if ($task->hasAppEngineHttpRequest()) { - request()->headers->set('X-AppEngine-TaskName', $taskName); - } }); dispatch($job); @@ -271,4 +263,20 @@ public function withTaskType(string $taskType): void break; } } + + public static function getCommandProperties(string $command): array + { + if (Str::startsWith($command, 'O:')) { + return (array) unserialize($command, ['allowed_classes' => false]); + } + + if (app()->bound(Encrypter::class)) { + return (array) unserialize( + app(Encrypter::class)->decrypt($command), + ['allowed_classes' => ['Illuminate\Support\Carbon']] + ); + } + + return []; + } } From 90359c059946cb8408a0ed735c1f42bf9cd1fba2 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 15:48:11 +0100 Subject: [PATCH 15/46] Wip to remove Config class --- src/CloudTasksQueue.php | 7 ++++++- tests/ConfigHandlerTest.php | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 630e6cf..175bf3d 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -250,7 +250,12 @@ public function release(CloudTasksJob $job, int $delay = 0): void public function getHandler(): string { - return Config::getHandler($this->config['handler']); + $handler = rtrim($this->config['handler'], '/'); + + return match (true) { + ! str_ends_with($handler, '/handle-task') => $handler.'/handle-task', + default => $handler, + }; } public function getAudience(): ?string diff --git a/tests/ConfigHandlerTest.php b/tests/ConfigHandlerTest.php index 7264aa3..a3a062f 100644 --- a/tests/ConfigHandlerTest.php +++ b/tests/ConfigHandlerTest.php @@ -4,16 +4,26 @@ namespace Tests; -use Stackkit\LaravelGoogleCloudTasksQueue\Config; +use Google\Cloud\Tasks\V2\Task; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; +use Tests\Support\SimpleJob; -class ConfigHandlerTest extends \PHPUnit\Framework\TestCase +class ConfigHandlerTest extends TestCase { /** * @dataProvider handlerDataProvider */ public function test_it_allows_a_handler_url_to_contain_path(string $handler, string $expectedHandler): void { - self::assertSame($expectedHandler, Config::getHandler($handler)); + CloudTasksApi::fake(); + + $this->setConfigValue('handler', $handler); + + $this->dispatch(new SimpleJob()); + + CloudTasksApi::assertTaskCreated(function (Task $task) use ($expectedHandler) { + return $task->getHttpRequest()->getUrl() === $expectedHandler; + }); } public static function handlerDataProvider(): array From abe5dbc1943dca52800af6ff5d8a459c297517b8 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 16:57:39 +0100 Subject: [PATCH 16/46] Simplify authorization with simple token instead of hacky signed audience --- README.md | 20 ++++- composer.json | 1 - config/cloud-tasks.php | 6 ++ src/CloudTasksQueue.php | 16 ++-- src/CloudTasksServiceProvider.php | 5 +- src/Config.php | 77 ----------------- src/Errors.php | 28 ------- src/OpenIdVerificator.php | 20 ----- src/OpenIdVerificatorConcrete.php | 26 ------ src/OpenIdVerificatorFake.php | 26 ------ src/TaskHandler.php | 12 ++- tests/QueueTest.php | 11 --- tests/Support/self-signed-private-key.txt | 15 ---- .../self-signed-public-key-as-jwk.json | 12 --- tests/Support/self-signed-public-key.txt | 6 -- tests/TaskHandlerTest.php | 82 ------------------- tests/TestCase.php | 26 ------ 17 files changed, 43 insertions(+), 346 deletions(-) delete mode 100644 src/Config.php delete mode 100644 src/Errors.php delete mode 100644 src/OpenIdVerificator.php delete mode 100644 src/OpenIdVerificatorConcrete.php delete mode 100644 src/OpenIdVerificatorFake.php delete mode 100644 tests/Support/self-signed-private-key.txt delete mode 100644 tests/Support/self-signed-public-key-as-jwk.json delete mode 100644 tests/Support/self-signed-public-key.txt diff --git a/README.md b/README.md index b69f11e..bb9df44 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,12 @@ Please check the [Laravel support policy](https://laravel.com/docs/master/releas composer require stackkit/laravel-google-cloud-tasks-queue ``` + Publish the service provider: + + ```console + php artisan vendor:publish --provider=cloud-tasks + ``` + Add a new queue connection to `config/queue.php` ```php @@ -51,7 +57,6 @@ Please check the [Laravel support policy](https://laravel.com/docs/master/releas // Required when not using AppEngine 'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''), 'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''), - 'signed_audience' => env('STACKKIT_CLOUD_TASKS_SIGNED_AUDIENCE', true), // Optional: The deadline in seconds for requests sent to the worker. If the worker // does not respond by this deadline then the request is cancelled and the attempt @@ -61,7 +66,17 @@ Please check the [Laravel support policy](https://laravel.com/docs/master/releas ], ``` -Update the `QUEUE_CONNECTION` environment variable +If you are using separate services for dispatching and handling tasks, you may want to change the following settings: + +```php +// config/cloud-tasks.php + +// If the application only dispatches jobs +'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), + +// If the application only handles jobs and is secured by already (e.g. requires Authentication) +'disable_security_key_verification' => env('STACKKIT_CLOUD_TASKS_DISABLE_SECURITY_KEY_VERIFICATION', false), +``` ```dotenv QUEUE_CONNECTION=cloudtasks @@ -82,7 +97,6 @@ Please check the table below on what the values mean and what their value should | **Non- App Engine apps** | `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. |`my-service-account@appspot.gserviceaccount.com` | `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://.com` -| `STACKKIT_CLOUD_TASKS_SIGNED_AUDIENCE` (optional) | True or false depending if you want extra security by signing the audience of your tasks. May misbehave in certain Cloud Run setups. Defaults to true. | `true`
diff --git a/composer.json b/composer.json index 436095e..1b5ea29 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,6 @@ "php": "^8.1", "ext-json": "*", "phpseclib/phpseclib": "^3.0", - "google/auth": "^v1.29.1", "google/cloud-tasks": "^1.10", "thecodingmachine/safe": "^1.0|^2.0" }, diff --git a/config/cloud-tasks.php b/config/cloud-tasks.php index 1885df2..ef172c5 100644 --- a/config/cloud-tasks.php +++ b/config/cloud-tasks.php @@ -3,6 +3,12 @@ declare(strict_types=1); return [ + // If the application only dispatches jobs + 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), + + // If the application only handles jobs and is secured by already (e.g. requires Authentication) + 'disable_security_key_verification' => env('STACKKIT_CLOUD_TASKS_DISABLE_SECURITY_KEY_VERIFICATION', false), + 'dashboard' => [ 'enabled' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED', false), 'password' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD', 'MyPassword1!'), diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 175bf3d..b6e89c8 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -120,6 +120,7 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = $this->withQueueName($payload, $queue); $payload = $this->withTaskName($payload, $task->getName()); $payload = $this->withConnectionName($payload, $this->getConnectionName()); + $payload = $this->withSecurityKey($payload); if (! empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); @@ -143,9 +144,6 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $token = new OidcToken; $token->setServiceAccountEmail($this->config['service_account_email']); - if ($audience = $this->getAudience()) { - $token->setAudience($audience); - } $httpRequest->setOidcToken($token); $task->setHttpRequest($httpRequest); } @@ -221,6 +219,13 @@ private function withConnectionName(array $payload, string $connectionName): arr return $payload; } + private function withSecurityKey(array $payload): array + { + $payload['internal']['securityKey'] = encrypt($this->config['security_key'] ?? $payload['uuid']); + + return $payload; + } + /** * Pop the next job off of the queue. * @@ -257,9 +262,4 @@ public function getHandler(): string default => $handler, }; } - - public function getAudience(): ?string - { - return Config::getAudience($this->config); - } } diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index 8a5802d..69fa1e7 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -29,7 +29,6 @@ private function registerClient(): void return new CloudTasksClient(); }); - $this->app->bind('open-id-verificator', OpenIdVerificatorConcrete::class); $this->app->bind('cloud-tasks-api', CloudTasksApiConcrete::class); } @@ -56,6 +55,10 @@ private function registerConfig(): void private function registerRoutes(): void { + if (config('cloud-tasks.disable_task_handler')) { + return; + } + /** * @var \Illuminate\Routing\Router $router */ diff --git a/src/Config.php b/src/Config.php deleted file mode 100644 index a96386f..0000000 --- a/src/Config.php +++ /dev/null @@ -1,77 +0,0 @@ -verify( - $token, - [ - 'audience' => Config::getAudience($config), - 'throwException' => true, - ] - ); - } -} diff --git a/src/OpenIdVerificatorFake.php b/src/OpenIdVerificatorFake.php deleted file mode 100644 index 5666e76..0000000 --- a/src/OpenIdVerificatorFake.php +++ /dev/null @@ -1,26 +0,0 @@ -verify( - $token, - [ - 'audience' => Config::getAudience($config), - 'throwException' => true, - 'certsLocation' => __DIR__.'/../tests/Support/self-signed-public-key-as-jwk.json', - ] - ); - } -} diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 15981aa..184ecb3 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -41,12 +41,12 @@ public function handle(?string $task = null): void $this->config = config('queue.connections.'.$task['internal']['connection']); - $this->guard(); + $this->guard($task); $this->handleTask($task); } - private function guard(): void + private function guard(array $task): void { $appEngine = ! empty($this->config['app_engine']); @@ -55,8 +55,12 @@ private function guard(): void // "If your request handler finds any of the headers listed above, it can trust // that the request is a Cloud Tasks request." abort_if(empty(request()->header('X-AppEngine-TaskName')), 404); - } else { - OpenIdVerificator::verify(request()->bearerToken(), $this->config); + + return; + } + + if (config('cloud-tasks.disable_security_key_verification') !== true) { + abort_if(decrypt($task['internal']['securityKey']) !== $task['uuid'], 404); } } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index afab4cc..5e49b5a 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -18,7 +18,6 @@ use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; -use Stackkit\LaravelGoogleCloudTasksQueue\OpenIdVerificator; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; use Tests\Support\JobThatWillBeReleased; @@ -222,7 +221,6 @@ public function jobs_can_be_released() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Event::fake([ JobReleasedAfterException::class, JobReleased::class, @@ -267,7 +265,6 @@ public function jobs_can_be_released_with_a_delay() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Event::fake([ JobReleasedAfterException::class, JobReleased::class, @@ -295,7 +292,6 @@ public function test_default_backoff() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Event::fake(JobReleasedAfterException::class); // Act @@ -314,7 +310,6 @@ public function test_backoff_from_queue_config() Carbon::setTestNow(now()->addDay()); $this->setConfigValue('backoff', 123); CloudTasksApi::fake(); - OpenIdVerificator::fake(); Event::fake(JobReleasedAfterException::class); // Act @@ -333,7 +328,6 @@ public function test_backoff_from_job() // Arrange Carbon::setTestNow(now()->addDay()); CloudTasksApi::fake(); - OpenIdVerificator::fake(); Event::fake(JobReleasedAfterException::class); // Act @@ -354,7 +348,6 @@ public function test_exponential_backoff_from_job_method() // Arrange Carbon::setTestNow(now()->addDay()); CloudTasksApi::fake(); - OpenIdVerificator::fake(); // Act $releasedJob = $this->dispatch(new FailingJobWithExponentialBackoff()) @@ -382,7 +375,6 @@ public function test_failing_method_on_job() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Log::swap(new LogFake()); // Act @@ -400,7 +392,6 @@ public function test_queue_before_and_after_hooks() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Log::swap(new LogFake()); // Act @@ -422,7 +413,6 @@ public function test_queue_looping_hook_not_supported_with_this_package() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Log::swap(new LogFake()); // Act @@ -440,7 +430,6 @@ public function test_ignoring_jobs_with_deleted_models() { // Arrange CloudTasksApi::fake(); - OpenIdVerificator::fake(); Log::swap(new LogFake()); $user1 = User::create([ diff --git a/tests/Support/self-signed-private-key.txt b/tests/Support/self-signed-private-key.txt deleted file mode 100644 index e287c02..0000000 --- a/tests/Support/self-signed-private-key.txt +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn -vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9 -5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB -AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz -bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J -Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1 -cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5 -5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck -ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe -k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb -qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k -eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm -B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM= ------END RSA PRIVATE KEY----- diff --git a/tests/Support/self-signed-public-key-as-jwk.json b/tests/Support/self-signed-public-key-as-jwk.json deleted file mode 100644 index 0937c5d..0000000 --- a/tests/Support/self-signed-public-key-as-jwk.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "keys": [ - { - "kty": "RSA", - "n": "vJBmtaUo20mGVXm7U0QS8Qc-R-Itqf5ZSwqxHkIbWuZGkLv0Z77hEeFvKAx9_t4riGFuFUAM8qhacLs45AyPte7ebdLcms8mfCV8PioF08ZXTDxC_efqlYYF78LYoVwtXOaBm0ZRA7wxekmud63BVbGCeHoXXv81MaOlL0u1KwU", - "e": "AQAB", - "alg": "RS256", - "kid": "abc123", - "use": "sig" - } - ] -} diff --git a/tests/Support/self-signed-public-key.txt b/tests/Support/self-signed-public-key.txt deleted file mode 100644 index 5996602..0000000 --- a/tests/Support/self-signed-public-key.txt +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H -4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t -0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4 -ehde/zUxo6UvS7UrBQIDAQAB ------END PUBLIC KEY----- diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 1e7b6b8..490b015 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -4,7 +4,6 @@ namespace Tests; -use Firebase\JWT\ExpiredException; use Google\Cloud\Tasks\V2\Task; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; @@ -13,16 +12,13 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; -use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksException; use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; -use Stackkit\LaravelGoogleCloudTasksQueue\OpenIdVerificator; use Tests\Support\EncryptedJob; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithMaxTries; use Tests\Support\FailingJobWithMaxTriesAndRetryUntil; use Tests\Support\FailingJobWithRetryUntil; use Tests\Support\SimpleJob; -use UnexpectedValueException; class TaskHandlerTest extends TestCase { @@ -33,80 +29,12 @@ protected function setUp(): void CloudTasksApi::fake(); } - /** - * @test - */ - public function the_task_handler_needs_an_open_id_token() - { - // Assert - $this->expectException(CloudTasksException::class); - $this->expectExceptionMessage('Missing [Authorization] header'); - - // Act - $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); - } - - /** - * @test - */ - public function the_task_handler_throws_an_exception_if_the_id_token_is_invalid() - { - // Arrange - request()->headers->set('Authorization', 'Bearer my-invalid-token'); - - // Assert - $this->expectException(UnexpectedValueException::class); - $this->expectExceptionMessage('Wrong number of segments'); - - // Act - $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); - } - - /** - * @test - */ - public function it_validates_the_token_expiration() - { - // Arrange - OpenIdVerificator::fake(); - $this->addIdTokenToHeader(function (array $base) { - return ['exp' => time() - 5] + $base; - }); - - // Assert - $this->expectException(ExpiredException::class); - $this->expectExceptionMessage('Expired token'); - - // Act - $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); - } - - /** - * @test - */ - public function it_validates_the_token_aud() - { - // Arrange - OpenIdVerificator::fake(); - $this->addIdTokenToHeader(function (array $base) { - return ['aud' => 'invalid-aud'] + $base; - }); - - // Assert - $this->expectException(UnexpectedValueException::class); - $this->expectExceptionMessage('Audience does not match'); - - // Act - $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); - } - /** * @test */ public function it_can_run_a_task() { // Arrange - OpenIdVerificator::fake(); Log::swap(new LogFake()); Event::fake([JobProcessing::class, JobProcessed::class]); @@ -123,7 +51,6 @@ public function it_can_run_a_task() public function it_can_run_a_task_using_the_task_connection() { // Arrange - OpenIdVerificator::fake(); Log::swap(new LogFake()); Event::fake([JobProcessing::class, JobProcessed::class]); $this->app['config']->set('queue.default', 'non-existing-connection'); @@ -143,7 +70,6 @@ public function it_can_run_a_task_using_the_task_connection() public function after_max_attempts_it_will_log_to_failed_table() { // Arrange - OpenIdVerificator::fake(); $job = $this->dispatch(new FailingJobWithMaxTries()); // Act & Assert @@ -165,7 +91,6 @@ public function after_max_attempts_it_will_log_to_failed_table() public function after_max_attempts_it_will_delete_the_task() { // Arrange - OpenIdVerificator::fake(); $job = $this->dispatch(new FailingJob()); @@ -198,7 +123,6 @@ public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the // Arrange $this->travelTo($args['now']); - OpenIdVerificator::fake(); $job = $this->dispatch(new FailingJobWithRetryUntil()); // Act @@ -223,7 +147,6 @@ public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the public function test_unlimited_max_attempts() { // Arrange - OpenIdVerificator::fake(); // Act $job = $this->dispatch(new FailingJob()); @@ -241,7 +164,6 @@ public function test_unlimited_max_attempts() public function test_max_attempts_in_combination_with_retry_until() { // Arrange - OpenIdVerificator::fake(); $this->travelTo('2020-01-01 00:00:00'); @@ -272,7 +194,6 @@ public function test_max_attempts_in_combination_with_retry_until() public function it_can_handle_encrypted_jobs() { // Arrange - OpenIdVerificator::fake(); Log::swap(new LogFake()); // Act @@ -294,7 +215,6 @@ public function it_can_handle_encrypted_jobs() public function failing_jobs_are_released() { // Arrange - OpenIdVerificator::fake(); Event::fake(JobReleasedAfterException::class); // Act @@ -320,7 +240,6 @@ public function failing_jobs_are_released() public function attempts_are_tracked_internally() { // Arrange - OpenIdVerificator::fake(); Event::fake(JobReleasedAfterException::class); // Act & Assert @@ -347,7 +266,6 @@ public function attempts_are_tracked_internally() public function retried_jobs_get_a_new_name() { // Arrange - OpenIdVerificator::fake(); Event::fake(JobReleasedAfterException::class); CloudTasksApi::fake(); diff --git a/tests/TestCase.php b/tests/TestCase.php index e8740f7..336b681 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,8 +4,6 @@ namespace Tests; -use Closure; -use Firebase\JWT\JWT; use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\Task; @@ -35,8 +33,6 @@ protected function setUp(): void $this->withFactories(__DIR__.'/../factories'); - $this->defaultHeaders['Authorization'] = 'Bearer '.encrypt(time() + 10); - Event::listen( JobReleasedAfterException::class, function ($event) { @@ -105,7 +101,6 @@ protected function getEnvironmentSetUp($app) 'location' => 'europe-west6', 'handler' => env('CLOUD_TASKS_HANDLER', 'https://docker.for.mac.localhost:8080'), 'service_account_email' => 'info@stackkit.io', - 'signed_audience' => true, ]); $app['config']->set('queue.failed.driver', 'database-uuids'); $app['config']->set('queue.failed.database', 'testbench'); @@ -218,25 +213,6 @@ public function assertTaskExists(string $taskId): void } } - protected function addIdTokenToHeader(?Closure $closure = null): void - { - $base = [ - 'iss' => 'https://accounts.google.com', - 'aud' => 'https://docker.for.mac.localhost:8080', - 'exp' => time() + 10, - ]; - - if ($closure) { - $base = $closure($base); - } - - $privateKey = file_get_contents(__DIR__.'/../tests/Support/self-signed-private-key.txt'); - - $token = JWT::encode($base, $privateKey, 'RS256', 'abc123'); - - request()->headers->set('Authorization', 'Bearer '.$token); - } - protected function assertDatabaseCount($table, int $count, $connection = null) { $this->assertEquals($count, DB::connection($connection)->table($table)->count()); @@ -248,7 +224,6 @@ public function withTaskType(string $taskType): void case 'appengine': $this->setConfigValue('handler', null); $this->setConfigValue('service_account_email', null); - $this->setConfigValue('signed_audience', null); $this->setConfigValue('app_engine', true); $this->setConfigValue('app_engine_service', 'api'); @@ -259,7 +234,6 @@ public function withTaskType(string $taskType): void $this->setConfigValue('handler', 'https://docker.for.mac.localhost:8080'); $this->setConfigValue('service_account_email', 'info@stackkit.io'); - $this->setConfigValue('signed_audience', true); break; } } From 19ac434360258f135ff4f7ac3a34982d3a63c644 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 20:03:52 +0100 Subject: [PATCH 17/46] Refactor & cleanup --- src/CloudTasksConnector.php | 18 +++++------------- src/CloudTasksJob.php | 5 +++++ src/CloudTasksQueue.php | 17 +++++++++++------ 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/CloudTasksConnector.php b/src/CloudTasksConnector.php index aeaac7c..60aa5f8 100644 --- a/src/CloudTasksConnector.php +++ b/src/CloudTasksConnector.php @@ -11,18 +11,10 @@ class CloudTasksConnector implements ConnectorInterface { public function connect(array $config): CloudTasksQueue { - // The handler is the URL which Cloud Tasks will call with the job payload. This - // URL of the handler can be manually set through an environment variable, but - // if it is not then we will choose a sensible default (the current app url) - if (empty($config['handler'])) { - // At this point (during service provider boot) the trusted proxy middleware - // has not been set up, and so we are not ready to get the scheme and host - // So we wrap it and get it later, after the middleware has been set up. - $config['handler'] = function () { - return request()->getSchemeAndHttpHost(); - }; - } - - return new CloudTasksQueue($config, app(CloudTasksClient::class), $config['after_commit'] ?? null); + return new CloudTasksQueue( + config: $config, + client: app(CloudTasksClient::class), + dispatchAfterCommit: $config['after_commit'] ?? null + ); } } diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 1fe4b94..67a19a8 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -23,6 +23,11 @@ class CloudTasksJob extends LaravelJob implements JobContract protected $queue; + /** + * @param array $job + * @param string $connectionName + * @param string $queue + */ public function __construct(Container $container, CloudTasksQueue $cloudTasksQueue, $job, $connectionName, $queue) { $this->container = $container; diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index b6e89c8..4e88250 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -108,13 +108,12 @@ function ($payload, $queue, $delay) { protected function pushToCloudTasks($queue, $payload, $delay = 0) { $queue = $queue ?: $this->config['queue']; - $queueName = $this->client->queueName($this->config['project'], $this->config['location'], $queue); - $availableAt = $this->availableAt($delay); - $payload = json_decode($payload, true); + $payload = (array) json_decode($payload, true); - $task = new Task(); - $task->setName($this->taskName($queue, $payload)); + $task = new Task([ + 'name' => $this->taskName($queue, $payload), + ]); $payload = $this->withAttempts($payload); $payload = $this->withQueueName($payload, $queue); @@ -155,10 +154,12 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $task->setDispatchDeadline(new Duration(['seconds' => $this->config['dispatch_deadline']])); } + $availableAt = $this->availableAt($delay); if ($availableAt > time()) { $task->setScheduleTime(new Timestamp(['seconds' => $availableAt])); } + $queueName = $this->client->queueName($this->config['project'], $this->config['location'], $queue); CloudTasksApi::createTask($queueName, $task); event((new TaskCreated)->queue($queue)->task($task)); @@ -255,11 +256,15 @@ public function release(CloudTasksJob $job, int $delay = 0): void public function getHandler(): string { + if (empty($this->config['handler'])) { + $this->config['handler'] = request()->getSchemeAndHttpHost(); + } + $handler = rtrim($this->config['handler'], '/'); return match (true) { ! str_ends_with($handler, '/handle-task') => $handler.'/handle-task', - default => $handler, + default => $this->config['handler'], }; } } From 77c75456e72dd8754df464a56ff7ae0c99d438d1 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 18 Feb 2024 23:12:09 +0100 Subject: [PATCH 18/46] wip readme --- UPGRADING.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 93d0a71..ff8fed8 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,3 +1,11 @@ +# From 3.x to 4.x + +## New task internal metadata (Impact: high) + +The task internal metadata has been enriched with `queue`, `taskName`, `connection` and `securityKey`. +Existing tasks in the queue cannot be processed because they are missing these fields. +Please ensure that all tasks in the queue are processed before upgrading to 4.x. + # From 2.x to 3.x PHP 7.2 and 7.3, and Laravel 5.x are no longer supported. From 9ecafb6000e96944426cee3a1a945b896d02f121 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 19 Feb 2024 22:29:44 +0100 Subject: [PATCH 19/46] wip --- src/CloudTasksApi.php | 1 + src/CloudTasksApiConcrete.php | 27 ++++++++++++ src/CloudTasksApiContract.php | 2 + src/CloudTasksApiFake.php | 11 +++++ src/CloudTasksJob.php | 37 +++++++--------- src/CloudTasksQueue.php | 9 ++-- src/IncomingTask.php | 52 ++++++++++++++++++++++ src/TaskHandler.php | 82 +++++++++-------------------------- 8 files changed, 134 insertions(+), 87 deletions(-) create mode 100644 src/IncomingTask.php diff --git a/src/CloudTasksApi.php b/src/CloudTasksApi.php index 31643d1..51639fa 100644 --- a/src/CloudTasksApi.php +++ b/src/CloudTasksApi.php @@ -11,6 +11,7 @@ * @method static Task createTask(string $queueName, Task $task) * @method static void deleteTask(string $taskName) * @method static Task getTask(string $taskName) + * @method static bool exists(string $taskName) */ class CloudTasksApi extends Facade { diff --git a/src/CloudTasksApiConcrete.php b/src/CloudTasksApiConcrete.php index 7afe805..b0b8b92 100644 --- a/src/CloudTasksApiConcrete.php +++ b/src/CloudTasksApiConcrete.php @@ -4,6 +4,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; +use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Google\Cloud\Tasks\V2\CreateTaskRequest; use Google\Cloud\Tasks\V2\DeleteTaskRequest; @@ -17,6 +18,9 @@ public function __construct(private readonly CloudTasksClient $client) // } + /** + * @throws ApiException + */ public function createTask(string $queueName, Task $task): Task { return $this->client->createTask(new CreateTaskRequest([ @@ -25,6 +29,9 @@ public function createTask(string $queueName, Task $task): Task ])); } + /** + * @throws ApiException + */ public function deleteTask(string $taskName): void { $this->client->deleteTask(new DeleteTaskRequest([ @@ -32,10 +39,30 @@ public function deleteTask(string $taskName): void ])); } + /** + * @throws ApiException + */ public function getTask(string $taskName): Task { return $this->client->getTask(new GetTaskRequest([ 'name' => $taskName, ])); } + + public function exists(string $taskName): bool + { + try { + $this->getTask($taskName); + + return true; + } catch (ApiException $e) { + if ($e->getStatus() === 'NOT_FOUND') { + return false; + } + + report($e); + } + + return false; + } } diff --git a/src/CloudTasksApiContract.php b/src/CloudTasksApiContract.php index 8e8aca3..5f0af35 100644 --- a/src/CloudTasksApiContract.php +++ b/src/CloudTasksApiContract.php @@ -13,4 +13,6 @@ public function createTask(string $queueName, Task $task): Task; public function deleteTask(string $taskName): void; public function getTask(string $taskName): Task; + + public function exists(string $taskName): bool; } diff --git a/src/CloudTasksApiFake.php b/src/CloudTasksApiFake.php index 1614efe..074eb68 100644 --- a/src/CloudTasksApiFake.php +++ b/src/CloudTasksApiFake.php @@ -32,6 +32,17 @@ public function getTask(string $taskName): Task ->setName($taskName); } + public function exists(string $taskName): bool + { + foreach ($this->createdTasks as $createdTask) { + if ($createdTask['task']->getName() === $taskName) { + return ! in_array($taskName, $this->deletedTasks); + } + } + + return false; + } + public function assertTaskDeleted(string $taskName): void { Assert::assertTrue( diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 67a19a8..ecf40cf 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -4,9 +4,11 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; +use Exception; use Illuminate\Container\Container; use Illuminate\Contracts\Queue\Job as JobContract; use Illuminate\Queue\Jobs\Job as LaravelJob; +use Safe\Exceptions\JsonException; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use function Safe\json_encode; @@ -15,7 +17,7 @@ class CloudTasksJob extends LaravelJob implements JobContract { protected $container; - private CloudTasksQueue $cloudTasksQueue; + private CloudTasksQueue $driver; public array $job; @@ -23,35 +25,28 @@ class CloudTasksJob extends LaravelJob implements JobContract protected $queue; - /** - * @param array $job - * @param string $connectionName - * @param string $queue - */ - public function __construct(Container $container, CloudTasksQueue $cloudTasksQueue, $job, $connectionName, $queue) + public function __construct( + Container $container, + CloudTasksQueue $driver, + array $job, + string $connectionName, + string $queue) { $this->container = $container; - $this->cloudTasksQueue = $cloudTasksQueue; + $this->driver = $driver; $this->job = $job; $this->connectionName = $connectionName; $this->queue = $queue; } - public function job(): array - { - return $this->job; - } - public function getJobId(): string { - return $this->job['uuid']; - } - - public function uuid(): string - { - return $this->job['uuid']; + return $this->uuid() ?? throw new Exception(); } + /** + * @throws JsonException + */ public function getRawBody(): string { return json_encode($this->job); @@ -91,7 +86,7 @@ public function delete(): void parent::delete(); - $this->cloudTasksQueue->delete($this); + $this->driver->delete($this); } public function hasError(): bool @@ -103,7 +98,7 @@ public function release($delay = 0): void { parent::release($delay); - $this->cloudTasksQueue->release($this, $delay); + $this->driver->release($this, $delay); if (! data_get($this->job, 'internal.errored')) { app('events')->dispatch(new JobReleased($this->getConnectionName(), $this, $delay)); diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 4e88250..b61177c 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -262,9 +262,10 @@ public function getHandler(): string $handler = rtrim($this->config['handler'], '/'); - return match (true) { - ! str_ends_with($handler, '/handle-task') => $handler.'/handle-task', - default => $this->config['handler'], - }; + if (str_ends_with($handler, '/handle-task')) { + return $handler; + } + + return $handler.'/handle-task'; } } diff --git a/src/IncomingTask.php b/src/IncomingTask.php new file mode 100644 index 0000000..fae4b2a --- /dev/null +++ b/src/IncomingTask.php @@ -0,0 +1,52 @@ +task === []; + } + + public function connection(): string + { + return $this->task['internal']['connection']; + } + + public function queue(): string + { + return $this->task['internal']['queue']; + } + + public function taskName(): string + { + return $this->task['internal']['taskName']; + } + + public function toArray(): array + { + return $this->task; + } +} diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 184ecb3..9e910ea 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -4,93 +4,51 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; -use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Container\Container; use Illuminate\Queue\Worker; use Illuminate\Queue\WorkerOptions; -use Throwable; - -use function Safe\json_decode; class TaskHandler { - /** - * @var array - */ - private $config; - - /** - * @var CloudTasksClient - */ - private $client; - - /** - * @var CloudTasksQueue - */ - private $queue; - - public function __construct(CloudTasksClient $client) + private array $config; + + public function __construct(private readonly CloudTasksClient $client) { - $this->client = $client; + // } public function handle(?string $task = null): void { - $task = json_decode((string) $task ?: request()->getContent(), assoc: true); + $task = IncomingTask::fromJson($task ?: request()->getContent()); - $this->config = config('queue.connections.'.$task['internal']['connection']); - - $this->guard($task); + if ($task->isEmpty()) { + abort(422, 'Invalid task payload'); + } - $this->handleTask($task); - } + if (! CloudTasksApi::exists($task->taskName())) { + abort(404); + } - private function guard(array $task): void - { - $appEngine = ! empty($this->config['app_engine']); + $config = config('queue.connections.'.$task->connection()); - if ($appEngine) { - // https://cloud.google.com/tasks/docs/creating-appengine-handlers#reading_task_request_headers - // "If your request handler finds any of the headers listed above, it can trust - // that the request is a Cloud Tasks request." - abort_if(empty(request()->header('X-AppEngine-TaskName')), 404); + $this->config = is_array($config) ? $config : []; - return; - } - - if (config('cloud-tasks.disable_security_key_verification') !== true) { - abort_if(decrypt($task['internal']['securityKey']) !== $task['uuid'], 404); - } + $this->run($task); } - private function handleTask(array $task): void + private function run(IncomingTask $task): void { - $queue = new CloudTasksQueue( - config: $this->config, - client: $this->client, - ); - - $queue->setConnectionName($task['internal']['connection']); + $queue = tap(new CloudTasksQueue($this->config, $this->client))->setConnectionName($task->connection()); $job = new CloudTasksJob( container: Container::getInstance(), - cloudTasksQueue: $queue, - job: $task, - connectionName: $task['internal']['connection'], - queue: $task['internal']['queue'], + driver: $queue, + job: $task->toArray(), + connectionName: $task->connection(), + queue: $task->queue(), ); - try { - CloudTasksApi::getTask($task['internal']['taskName']); - } catch (Throwable $e) { - if ($e instanceof ApiException && in_array($e->getStatus(), ['NOT_FOUND', 'PRECONDITION_FAILED'])) { - abort(404); - } - - throw $e; - } - $job->setAttempts($job->attempts() + 1); tap(app('queue.worker'), fn (Worker $worker) => $worker->process( From 00b3343156746fa36700bafce6a3f3a29fe4e39d Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Tue, 20 Feb 2024 20:34:21 +0100 Subject: [PATCH 20/46] Refactor some tests --- src/CloudTasksQueue.php | 2 +- tests/QueueTest.php | 10 +-- .../Support/FailingJobWithUnlimitedTries.php | 10 +++ tests/TaskHandlerTest.php | 61 ++++++++----------- tests/TestCase.php | 23 +++++-- 5 files changed, 58 insertions(+), 48 deletions(-) create mode 100644 tests/Support/FailingJobWithUnlimitedTries.php diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index b61177c..37ca41f 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -175,7 +175,7 @@ private function taskName(string $queueName, array $payload): string $this->config['project'], $this->config['location'], $queueName, - $displayName.'-'.$payload['uuid'].'-'.Carbon::now()->getTimeStampMs(), + $displayName.'-'. bin2hex(random_bytes(8)), ); } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 5e49b5a..1238390 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -463,16 +463,16 @@ public function it_adds_a_task_name_based_on_the_display_name() { // Arrange CloudTasksApi::fake(); - Carbon::setTestNow(Carbon::create(2023, 6, 1, 20, 2, 37)); // Act $this->dispatch((new SimpleJob())); // Assert - CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool { - $uuid = \Safe\json_decode($task->getHttpRequest()->getBody(), true)['uuid']; - - return $task->getName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/Tests-Support-SimpleJob-'.$uuid.'-1685649757000'; + CloudTasksApi::assertTaskCreated(function (Task $task): bool { + return str_starts_with( + $task->getName(), + 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/Tests-Support-SimpleJob' + ); }); } } diff --git a/tests/Support/FailingJobWithUnlimitedTries.php b/tests/Support/FailingJobWithUnlimitedTries.php new file mode 100644 index 0000000..7f92520 --- /dev/null +++ b/tests/Support/FailingJobWithUnlimitedTries.php @@ -0,0 +1,10 @@ +dispatch(new FailingJob()); - foreach (range(1, 50) as $attempt) { - $job->run(); - CloudTasksApi::assertDeletedTaskCount($attempt); - CloudTasksApi::assertTaskDeleted($job->task->getName()); - $this->assertDatabaseCount('failed_jobs', 0); + $job = $this->dispatch(new FailingJobWithUnlimitedTries()); + + foreach (range(0, 50) as $attempt) { + usleep(1000); + $job = $job->runAndGetReleasedJob(); } + + // -1 because the last job is not run. + CloudTasksApi::assertDeletedTaskCount(51); } /** @@ -164,7 +165,6 @@ public function test_unlimited_max_attempts() public function test_max_attempts_in_combination_with_retry_until() { // Arrange - $this->travelTo('2020-01-01 00:00:00'); $job = $this->dispatch(new FailingJobWithMaxTriesAndRetryUntil()); @@ -174,13 +174,14 @@ public function test_max_attempts_in_combination_with_retry_until() // Act & Assert // The max attempts is 3, but the retryUntil is set to 5 minutes from now. - // So when we attempt the job 10 times, it should still not fail. - foreach (range(1, 10) as $attempt) { - $job = $job->runAndGetReleasedJob(); - CloudTasksApi::assertDeletedTaskCount($attempt); - CloudTasksApi::assertTaskDeleted($job->task->getName()); - $this->assertDatabaseCount('failed_jobs', 0); - } + // So when we attempt the job 4 times, it should still not fail. + $job = $job + ->runAndGetReleasedJob() + ->runAndGetReleasedJob() + ->runAndGetReleasedJob() + ->runAndGetReleasedJob(); + + $this->assertDatabaseCount('failed_jobs', 0); // Now we travel to 5 minutes from now, and the job should fail. $this->travelTo('2020-01-01 00:05:00'); @@ -244,8 +245,8 @@ public function attempts_are_tracked_internally() // Act & Assert $job = $this->dispatch(new FailingJob()); - $job->run(); - $releasedJob = null; + + $released = $job->runAndGetReleasedJob(); Event::assertDispatched(JobReleasedAfterException::class, function ($event) use (&$releasedJob) { $releasedJob = $event->job->getRawBody(); @@ -253,7 +254,7 @@ public function attempts_are_tracked_internally() return $event->job->attempts() === 1; }); - $this->runFromPayload($releasedJob); + $released->run(); Event::assertDispatched(JobReleasedAfterException::class, function ($event) { return $event->job->attempts() === 2; @@ -270,23 +271,9 @@ public function retried_jobs_get_a_new_name() CloudTasksApi::fake(); // Act & Assert - Carbon::setTestNow(Carbon::createFromTimestamp(1685035628)); - $job = $this->dispatch(new FailingJob()); - Carbon::setTestNow(Carbon::createFromTimestamp(1685035629)); - - $job->run(); - - // Assert - CloudTasksApi::assertCreatedTaskCount(2); - CloudTasksApi::assertTaskCreated(function (Task $task): bool { - [$timestamp] = array_reverse(explode('-', $task->getName())); - - return $timestamp === '1685035628000'; - }); - CloudTasksApi::assertTaskCreated(function (Task $task): bool { - [$timestamp] = array_reverse(explode('-', $task->getName())); - - return $timestamp === '1685035629000'; - }); + $this->assertCount(0, $this->createdTasks); + $this->dispatch(new FailingJob())->runAndGetReleasedJob(); + $this->assertCount(2, $this->createdTasks); + $this->assertNotEquals($this->createdTasks[0]->getName(), $this->createdTasks[1]->getName()); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 336b681..b8fddd8 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -27,12 +27,18 @@ class TestCase extends \Orchestra\Testbench\TestCase public string $releasedJobPayload; + public array $createdTasks = []; + protected function setUp(): void { parent::setUp(); $this->withFactories(__DIR__.'/../factories'); + Event::listen(TaskCreated::class, function (TaskCreated $event) { + $this->createdTasks[] = $event->task; + }); + Event::listen( JobReleasedAfterException::class, function ($event) { @@ -123,13 +129,11 @@ protected function setConfigValue($key, $value) public function dispatch($job) { $payload = null; - $payloadAsArray = []; $task = null; - Event::listen(TaskCreated::class, function (TaskCreated $event) use (&$payload, &$payloadAsArray, &$task) { + Event::listen(TaskCreated::class, function (TaskCreated $event) use (&$payload, &$task) { $request = $event->task->getHttpRequest() ?? $event->task->getAppEngineHttpRequest(); $payload = $request->getBody(); - $payloadAsArray = json_decode($payload, true); $task = $event->task; }); @@ -168,9 +172,18 @@ public function runAndGetReleasedJob(): self app(TaskHandler::class)->handle($this->payload); }); + $releasedTask = end($this->testCase->createdTasks); + + if (! $releasedTask) { + $this->testCase->fail('No task was released.'); + } + + $payload = $releasedTask->getAppEngineHttpRequest()?->getBody() + ?: $releasedTask->getHttpRequest()->getBody(); + return new self( - $this->testCase->releasedJobPayload, - $this->task, + $payload, + $releasedTask, $this->testCase ); } From dfb24c6d081a349c273eacc4e08998f96341da6e Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Tue, 20 Feb 2024 22:16:29 +0100 Subject: [PATCH 21/46] Get rid of LogFake and clean up test jobs --- src/LogFake.php | 78 ------------------- tests/QueueTest.php | 28 +++---- tests/Support/BaseJob.php | 16 ++++ tests/Support/EncryptedJob.php | 11 +-- tests/Support/FailingJob.php | 31 ++------ .../FailingJobWithExponentialBackoff.php | 15 +--- tests/Support/JobOutput.php | 13 ++++ tests/Support/JobThatWillBeReleased.php | 28 +------ tests/Support/SimpleJob.php | 2 +- tests/Support/UserJob.php | 2 +- tests/TaskHandlerTest.php | 23 ++---- 11 files changed, 64 insertions(+), 183 deletions(-) delete mode 100644 src/LogFake.php create mode 100644 tests/Support/BaseJob.php create mode 100644 tests/Support/JobOutput.php diff --git a/src/LogFake.php b/src/LogFake.php deleted file mode 100644 index c9a3476..0000000 --- a/src/LogFake.php +++ /dev/null @@ -1,78 +0,0 @@ -loggedMessages[] = $message; - } - - public function alert(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function critical(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function error(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function warning(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function notice(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function info(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function debug(string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - /** - * @param string $level - */ - public function log($level, string $message, array $context = []): void - { - $this->loggedMessages[] = $message; - } - - public function channel(): self - { - return $this; - } - - public function assertLogged(string $message): void - { - PHPUnit::assertTrue(in_array($message, $this->loggedMessages), 'The message ['.$message.'] was not logged.'); - } - - public function assertNotLogged(string $message): void - { - PHPUnit::assertTrue( - ! in_array($message, $this->loggedMessages), - 'The message ['.$message.'] was logged.' - ); - } -} diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 1238390..9226db2 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -13,13 +13,12 @@ use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; -use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Queue; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; -use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; +use Tests\Support\JobOutput; use Tests\Support\JobThatWillBeReleased; use Tests\Support\SimpleJob; use Tests\Support\User; @@ -375,7 +374,7 @@ public function test_failing_method_on_job() { // Arrange CloudTasksApi::fake(); - Log::swap(new LogFake()); + Event::fake(JobOutput::class); // Act $this->dispatch(new FailingJob()) @@ -384,7 +383,7 @@ public function test_failing_method_on_job() ->runAndGetReleasedJob(); // Assert - Log::assertLogged('FailingJob:failed'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'FailingJob:failed'); } /** @test */ @@ -392,20 +391,20 @@ public function test_queue_before_and_after_hooks() { // Arrange CloudTasksApi::fake(); - Log::swap(new LogFake()); + Event::fake(JobOutput::class); // Act Queue::before(function (JobProcessing $event) { - logger('Queue::before:'.$event->job->payload()['data']['commandName']); + event(new JobOutput('Queue::before:'.$event->job->payload()['data']['commandName'])); }); Queue::after(function (JobProcessed $event) { - logger('Queue::after:'.$event->job->payload()['data']['commandName']); + event(new JobOutput('Queue::after:'.$event->job->payload()['data']['commandName'])); }); $this->dispatch(new SimpleJob())->run(); // Assert - Log::assertLogged('Queue::before:Tests\Support\SimpleJob'); - Log::assertLogged('Queue::after:Tests\Support\SimpleJob'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'Queue::before:Tests\Support\SimpleJob'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'Queue::after:Tests\Support\SimpleJob'); } /** @test */ @@ -413,16 +412,17 @@ public function test_queue_looping_hook_not_supported_with_this_package() { // Arrange CloudTasksApi::fake(); - Log::swap(new LogFake()); + Event::fake(JobOutput::class); // Act Queue::looping(function () { - logger('Queue::looping'); + event(new JobOutput('Queue::looping')); }); $this->dispatch(new SimpleJob())->run(); // Assert - Log::assertNotLogged('Queue::looping'); + Event::assertDispatchedTimes(JobOutput::class, times: 1); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'SimpleJob:success'); } /** @test */ @@ -430,7 +430,7 @@ public function test_ignoring_jobs_with_deleted_models() { // Arrange CloudTasksApi::fake(); - Log::swap(new LogFake()); + Event::fake(JobOutput::class); $user1 = User::create([ 'name' => 'John', @@ -452,7 +452,7 @@ public function test_ignoring_jobs_with_deleted_models() $job->runWithoutExceptionHandler(); // Act - Log::assertLogged('UserJob:John'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'UserJob:John'); CloudTasksApi::assertTaskNotDeleted($job->task->getName()); } diff --git a/tests/Support/BaseJob.php b/tests/Support/BaseJob.php new file mode 100644 index 0000000..4f9cc94 --- /dev/null +++ b/tests/Support/BaseJob.php @@ -0,0 +1,16 @@ +releaseDelay = $releaseDelay; + // } - /** - * Execute the job. - * - * @return void - */ public function handle() { - logger('JobThatWillBeReleased:beforeRelease'); $this->release($this->releaseDelay); - logger('JobThatWillBeReleased:afterRelease'); } } diff --git a/tests/Support/SimpleJob.php b/tests/Support/SimpleJob.php index c2ba7cb..e554d24 100644 --- a/tests/Support/SimpleJob.php +++ b/tests/Support/SimpleJob.php @@ -33,6 +33,6 @@ public function __construct() */ public function handle() { - logger('SimpleJob:success'); + event(new JobOutput('SimpleJob:success')); } } diff --git a/tests/Support/UserJob.php b/tests/Support/UserJob.php index 5bc5582..2589146 100644 --- a/tests/Support/UserJob.php +++ b/tests/Support/UserJob.php @@ -30,6 +30,6 @@ public function __construct(User $user) */ public function handle() { - logger('UserJob:'.$this->user->name); + event(new JobOutput('UserJob:'.$this->user->name)); } } diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 0cff1c4..7db2234 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -4,21 +4,16 @@ namespace Tests; -use Google\Cloud\Tasks\V2\Task; -use Illuminate\Queue\Events\JobProcessed; -use Illuminate\Queue\Events\JobProcessing; use Illuminate\Queue\Events\JobReleasedAfterException; -use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Event; -use Illuminate\Support\Facades\Log; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; -use Stackkit\LaravelGoogleCloudTasksQueue\LogFake; use Tests\Support\EncryptedJob; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithMaxTries; use Tests\Support\FailingJobWithMaxTriesAndRetryUntil; use Tests\Support\FailingJobWithRetryUntil; use Tests\Support\FailingJobWithUnlimitedTries; +use Tests\Support\JobOutput; use Tests\Support\SimpleJob; class TaskHandlerTest extends TestCase @@ -36,14 +31,13 @@ protected function setUp(): void public function it_can_run_a_task() { // Arrange - Log::swap(new LogFake()); - Event::fake([JobProcessing::class, JobProcessed::class]); + Event::fake(JobOutput::class); // Act $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); // Assert - Log::assertLogged('SimpleJob:success'); + Event::assertDispatched(fn(JobOutput $event) => $event->output === 'SimpleJob:success'); } /** @@ -52,8 +46,8 @@ public function it_can_run_a_task() public function it_can_run_a_task_using_the_task_connection() { // Arrange - Log::swap(new LogFake()); - Event::fake([JobProcessing::class, JobProcessed::class]); + + Event::fake(JobOutput::class); $this->app['config']->set('queue.default', 'non-existing-connection'); // Act @@ -62,7 +56,7 @@ public function it_can_run_a_task_using_the_task_connection() $this->dispatch($job)->runWithoutExceptionHandler(); // Assert - Log::assertLogged('SimpleJob:success'); + Event::assertDispatched(fn(JobOutput $event) => $event->output === 'SimpleJob:success'); } /** @@ -92,7 +86,6 @@ public function after_max_attempts_it_will_log_to_failed_table() public function after_max_attempts_it_will_delete_the_task() { // Arrange - $job = $this->dispatch(new FailingJob()); // Act & Assert @@ -195,7 +188,7 @@ public function test_max_attempts_in_combination_with_retry_until() public function it_can_handle_encrypted_jobs() { // Arrange - Log::swap(new LogFake()); + Event::fake(JobOutput::class); // Act $job = $this->dispatch(new EncryptedJob()); @@ -207,7 +200,7 @@ public function it_can_handle_encrypted_jobs() decrypt($job->payloadAsArray('data.command')), ); - Log::assertLogged('EncryptedJob:success'); + Event::assertDispatched(fn(JobOutput $event) => $event->output === 'EncryptedJob:success'); } /** From 82dfb287526221c6065ad57be57fca6d07d9c313 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Tue, 20 Feb 2024 22:19:53 +0100 Subject: [PATCH 22/46] Cleanup --- src/CloudTasksException.php | 12 ------------ src/CloudTasksQueue.php | 2 +- src/Events/TaskCreated.php | 17 ++--------------- 3 files changed, 3 insertions(+), 28 deletions(-) delete mode 100644 src/CloudTasksException.php diff --git a/src/CloudTasksException.php b/src/CloudTasksException.php deleted file mode 100644 index 1e42f08..0000000 --- a/src/CloudTasksException.php +++ /dev/null @@ -1,12 +0,0 @@ -client->queueName($this->config['project'], $this->config['location'], $queue); CloudTasksApi::createTask($queueName, $task); - event((new TaskCreated)->queue($queue)->task($task)); + event(new TaskCreated($queue, $task)); return $payload['uuid']; } diff --git a/src/Events/TaskCreated.php b/src/Events/TaskCreated.php index 9ab76aa..a95608e 100644 --- a/src/Events/TaskCreated.php +++ b/src/Events/TaskCreated.php @@ -8,21 +8,8 @@ class TaskCreated { - public string $queue; - - public Task $task; - - public function task(Task $task): self + public function __construct(public string $queue, public Task $task) { - $this->task = $task; - - return $this; - } - - public function queue(string $queue): self - { - $this->queue = $queue; - - return $this; + // } } From ef54f7ef1078c37221cd0e7be56ec1c276e4583d Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Tue, 20 Feb 2024 22:32:33 +0100 Subject: [PATCH 23/46] wip --- src/CloudTasksQueue.php | 109 +++++++++++++++++----------------------- tests/TestCase.php | 4 +- 2 files changed, 48 insertions(+), 65 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index ec28bf1..63acd1b 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -111,41 +111,16 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = (array) json_decode($payload, true); - $task = new Task([ - 'name' => $this->taskName($queue, $payload), - ]); + $task = tap(new Task())->setName($this->taskName($queue, $payload)); - $payload = $this->withAttempts($payload); - $payload = $this->withQueueName($payload, $queue); - $payload = $this->withTaskName($payload, $task->getName()); - $payload = $this->withConnectionName($payload, $this->getConnectionName()); - $payload = $this->withSecurityKey($payload); - - if (! empty($this->config['app_engine'])) { - $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); - - $appEngineRequest = new AppEngineHttpRequest(); - $appEngineRequest->setRelativeUri($path); - $appEngineRequest->setHttpMethod(HttpMethod::POST); - $appEngineRequest->setBody(json_encode($payload)); - if (! empty($service = $this->config['app_engine_service'])) { - $routing = new AppEngineRouting(); - $routing->setService($service); - $appEngineRequest->setAppEngineRouting($routing); - } - $task->setAppEngineHttpRequest($appEngineRequest); - } else { - $httpRequest = new HttpRequest(); - $httpRequest->setUrl($this->getHandler()); - $httpRequest->setHttpMethod(HttpMethod::POST); - - $httpRequest->setBody(json_encode($payload)); + $payload = $this->enrichPayloadWithInternalData( + payload: $payload, + taskName: $task->getName(), + connectionName: $this->getConnectionName(), + queueName: $queue, + ); - $token = new OidcToken; - $token->setServiceAccountEmail($this->config['service_account_email']); - $httpRequest->setOidcToken($token); - $task->setHttpRequest($httpRequest); - } + $this->addPayloadToTask($payload, $task); // The deadline for requests sent to the app. If the app does not respond by // this deadline then the request is cancelled and the attempt is marked as @@ -190,52 +165,60 @@ private function sanitizeTaskName(string $taskName): string return trim($sanitizedName, '-'); } - private function withAttempts(array $payload): array + private function enrichPayloadWithInternalData( + array $payload, + string $queueName, + string $taskName, + string $connectionName, + ): array { - if (! isset($payload['internal']['attempts'])) { - $payload['internal']['attempts'] = 0; - } + $payload['internal'] = [ + 'attempts' => $payload['internal']['attempts'] ?? 0, + 'queue' => $queueName, + 'taskName' => $taskName, + 'connection' => $connectionName, + ]; return $payload; } - private function withQueueName(array $payload, string $queueName): array + public function addPayloadToTask(array $payload, Task $task): Task { - $payload['internal']['queue'] = $queueName; - - return $payload; - } + if (!empty($this->config['app_engine'])) { + $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); - private function withTaskName(array $payload, string $taskName): array - { - $payload['internal']['taskName'] = $taskName; + $appEngineRequest = new AppEngineHttpRequest(); + $appEngineRequest->setRelativeUri($path); + $appEngineRequest->setHttpMethod(HttpMethod::POST); + $appEngineRequest->setBody(json_encode($payload)); - return $payload; - } + if (!empty($service = $this->config['app_engine_service'])) { + $routing = new AppEngineRouting(); + $routing->setService($service); + $appEngineRequest->setAppEngineRouting($routing); + } - private function withConnectionName(array $payload, string $connectionName): array - { - $payload['internal']['connection'] = $connectionName; + $task->setAppEngineHttpRequest($appEngineRequest); + } else { + $httpRequest = new HttpRequest(); + $httpRequest->setUrl($this->getHandler()); - return $payload; - } + $httpRequest->setBody(json_encode($payload)); + $httpRequest->setHttpMethod(HttpMethod::POST); - private function withSecurityKey(array $payload): array - { - $payload['internal']['securityKey'] = encrypt($this->config['security_key'] ?? $payload['uuid']); + $token = new OidcToken; + $token->setServiceAccountEmail($this->config['service_account_email']); + $httpRequest->setOidcToken($token); + $task->setHttpRequest($httpRequest); + } - return $payload; + return $task; } - /** - * Pop the next job off of the queue. - * - * @param string|null $queue - * @return \Illuminate\Contracts\Queue\Job|null - */ public function pop($queue = null) { - // + // It is not possible to pop a job from the queue. + return null; } public function delete(CloudTasksJob $job): void diff --git a/tests/TestCase.php b/tests/TestCase.php index b8fddd8..98052dc 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -70,8 +70,8 @@ protected function getPackageProviders($app) */ protected function defineDatabaseMigrations() { - $this->loadMigrationsFrom(__DIR__.'/../migrations'); - $this->loadMigrationsFrom(__DIR__.'/../vendor/orchestra/testbench-core/laravel/migrations'); +// $this->loadMigrationsFrom(__DIR__.'/../migrations'); +// $this->loadMigrationsFrom(__DIR__.'/../vendor/orchestra/testbench-core/laravel/migrations'); } /** From cfcf0ebf971fe66e75d1c936b056a851cfed3277 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 21 Feb 2024 21:44:11 +0100 Subject: [PATCH 24/46] wip --- README.md | 3 --- config/cloud-tasks.php | 3 --- src/CloudTasksQueue.php | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index bb9df44..fbe8164 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,6 @@ If you are using separate services for dispatching and handling tasks, you may w // If the application only dispatches jobs 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), - -// If the application only handles jobs and is secured by already (e.g. requires Authentication) -'disable_security_key_verification' => env('STACKKIT_CLOUD_TASKS_DISABLE_SECURITY_KEY_VERIFICATION', false), ``` ```dotenv diff --git a/config/cloud-tasks.php b/config/cloud-tasks.php index ef172c5..58bff0c 100644 --- a/config/cloud-tasks.php +++ b/config/cloud-tasks.php @@ -6,9 +6,6 @@ // If the application only dispatches jobs 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), - // If the application only handles jobs and is secured by already (e.g. requires Authentication) - 'disable_security_key_verification' => env('STACKKIT_CLOUD_TASKS_DISABLE_SECURITY_KEY_VERIFICATION', false), - 'dashboard' => [ 'enabled' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED', false), 'password' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD', 'MyPassword1!'), diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 63acd1b..7b9a8ab 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -115,9 +115,9 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = $this->enrichPayloadWithInternalData( payload: $payload, + queueName: $queue, taskName: $task->getName(), connectionName: $this->getConnectionName(), - queueName: $queue, ); $this->addPayloadToTask($payload, $task); From ff0c7b1fdd6ea01be215dcfc2072120ca2f922ad Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 21 Feb 2024 21:48:53 +0100 Subject: [PATCH 25/46] Make task handler route customizable --- config/cloud-tasks.php | 3 +++ src/CloudTasksQueue.php | 4 ++-- src/CloudTasksServiceProvider.php | 2 +- tests/ConfigHandlerTest.php | 29 +++++++++++++++++++++++++++++ tests/TestCase.php | 4 ++-- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/config/cloud-tasks.php b/config/cloud-tasks.php index 58bff0c..be93015 100644 --- a/config/cloud-tasks.php +++ b/config/cloud-tasks.php @@ -3,6 +3,9 @@ declare(strict_types=1); return [ + // The URI of the endpoint that will handle the task + 'uri' => env('STACKKIT_CLOUD_TASKS_URI', 'handle-task'), + // If the application only dispatches jobs 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 7b9a8ab..17eca63 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -245,10 +245,10 @@ public function getHandler(): string $handler = rtrim($this->config['handler'], '/'); - if (str_ends_with($handler, '/handle-task')) { + if (str_ends_with($handler, '/'. config('cloud-tasks.uri'))) { return $handler; } - return $handler.'/handle-task'; + return $handler.'/'. config('cloud-tasks.uri'); } } diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index 69fa1e7..e53edae 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -64,7 +64,7 @@ private function registerRoutes(): void */ $router = $this->app['router']; - $router->post('handle-task', [TaskHandler::class, 'handle'])->name('cloud-tasks.handle-task'); + $router->post(config('cloud-tasks.uri'), [TaskHandler::class, 'handle'])->name('cloud-tasks.handle-task'); } private function registerEvents(): void diff --git a/tests/ConfigHandlerTest.php b/tests/ConfigHandlerTest.php index a3a062f..4711d2a 100644 --- a/tests/ConfigHandlerTest.php +++ b/tests/ConfigHandlerTest.php @@ -26,6 +26,35 @@ public function test_it_allows_a_handler_url_to_contain_path(string $handler, st }); } + /** @test */ + public function the_handle_route_task_uri_can_be_configured(): void + { + CloudTasksApi::fake(); + + $this->app['config']->set('cloud-tasks.uri', 'my-custom-route'); + + $this->dispatch(new SimpleJob()); + + CloudTasksApi::assertTaskCreated(function (Task $task) { + return $task->getHttpRequest()->getUrl() === 'https://docker.for.mac.localhost:8080/my-custom-route'; + }); + } + + /** @test */ + public function the_handle_route_task_uri_in_combination_with_path_can_be_configured(): void + { + CloudTasksApi::fake(); + + $this->setConfigValue('handler', 'https://example.com/api'); + $this->app['config']->set('cloud-tasks.uri', 'my-custom-route'); + + $this->dispatch(new SimpleJob()); + + CloudTasksApi::assertTaskCreated(function (Task $task) { + return $task->getHttpRequest()->getUrl() === 'https://example.com/api/my-custom-route'; + }); + } + public static function handlerDataProvider(): array { return [ diff --git a/tests/TestCase.php b/tests/TestCase.php index 98052dc..b8fddd8 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -70,8 +70,8 @@ protected function getPackageProviders($app) */ protected function defineDatabaseMigrations() { -// $this->loadMigrationsFrom(__DIR__.'/../migrations'); -// $this->loadMigrationsFrom(__DIR__.'/../vendor/orchestra/testbench-core/laravel/migrations'); + $this->loadMigrationsFrom(__DIR__.'/../migrations'); + $this->loadMigrationsFrom(__DIR__.'/../vendor/orchestra/testbench-core/laravel/migrations'); } /** From c30151ad509eb2a218680846743d4a8e2573bb92 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 21 Feb 2024 22:22:05 +0100 Subject: [PATCH 26/46] Make it possible to pass headers to task --- README.md | 213 +++++++++++++++++++++++----------------- src/CloudTasksQueue.php | 14 ++- tests/QueueTest.php | 45 +++++++++ 3 files changed, 180 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index fbe8164..44586fa 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

Build Status @@ -12,59 +12,60 @@ This package allows Google Cloud Tasks to be used as the queue driver.

- +

- - Requirements - + +Requirements + -
- 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. +
+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. -Please check the [Laravel support policy](https://laravel.com/docs/master/releases#support-policy) table for supported Laravel and PHP versions. +Please check the [Laravel support policy](https://laravel.com/docs/master/releases#support-policy) table for supported +Laravel and PHP versions.
- Installation -
- - Require the package using Composer - - ```console - composer require stackkit/laravel-google-cloud-tasks-queue - ``` - - Publish the service provider: - - ```console - php artisan vendor:publish --provider=cloud-tasks - ``` - - Add a new queue connection to `config/queue.php` - - ```php - 'cloudtasks' => [ - 'driver' => 'cloudtasks', - 'project' => env('STACKKIT_CLOUD_TASKS_PROJECT', ''), - 'location' => env('STACKKIT_CLOUD_TASKS_LOCATION', ''), - 'queue' => env('STACKKIT_CLOUD_TASKS_QUEUE', 'default'), - - // Required when using AppEngine - 'app_engine' => env('STACKKIT_APP_ENGINE_TASK', false), - 'app_engine_service' => env('STACKKIT_APP_ENGINE_SERVICE', ''), - - // Required when not using AppEngine - 'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''), - 'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''), - - // Optional: The deadline in seconds for requests sent to the worker. If the worker - // 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, - ], - ``` +Installation +
+ +Require the package using Composer + +```console +composer require stackkit/laravel-google-cloud-tasks-queue +``` + +Publish the service provider: + +```console +php artisan vendor:publish --provider=cloud-tasks +``` + +Add a new queue connection to `config/queue.php` + +```php +'cloudtasks' => [ + 'driver' => 'cloudtasks', + 'project' => env('STACKKIT_CLOUD_TASKS_PROJECT', ''), + 'location' => env('STACKKIT_CLOUD_TASKS_LOCATION', ''), + 'queue' => env('STACKKIT_CLOUD_TASKS_QUEUE', 'default'), + + // Required when using AppEngine + 'app_engine' => env('STACKKIT_APP_ENGINE_TASK', false), + 'app_engine_service' => env('STACKKIT_APP_ENGINE_SERVICE', ''), + + // Required when not using AppEngine + 'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''), + 'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''), + + // Optional: The deadline in seconds for requests sent to the worker. If the worker + // 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, +], +``` If you are using separate services for dispatching and handling tasks, you may want to change the following settings: @@ -75,50 +76,78 @@ If you are using separate services for dispatching and handling tasks, you may w 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), ``` - ```dotenv - QUEUE_CONNECTION=cloudtasks - ``` +```dotenv +QUEUE_CONNECTION=cloudtasks +``` Now that the package is installed, the final step is to set the correct environment variables. Please check the table below on what the values mean and what their value should be. -| Environment variable | Description |Example ----------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|--- -| `STACKKIT_CLOUD_TASKS_PROJECT` | The project your queue belongs to. |`my-project` -| `STACKKIT_CLOUD_TASKS_LOCATION` | The region where the project is hosted. |`europe-west6` -| `STACKKIT_CLOUD_TASKS_QUEUE` | The default queue a job will be added to. |`emails` -| **App Engine** -| `STACKKIT_APP_ENGINE_TASK` (optional) | Set to true to use App Engine task (else a Http task will be used). Defaults to false. |`true` -| `STACKKIT_APP_ENGINE_SERVICE` (optional) | The App Engine service to handle the task (only if using App Engine task). |`api` -| **Non- App Engine apps** -| `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. |`my-service-account@appspot.gserviceaccount.com` -| `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://.com` +| Environment variable | Description | Example +---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------- +| `STACKKIT_CLOUD_TASKS_PROJECT` | The project your queue belongs to. | `my-project` +| `STACKKIT_CLOUD_TASKS_LOCATION` | The region where the project is hosted. | `europe-west6` +| `STACKKIT_CLOUD_TASKS_QUEUE` | The default queue a job will be added to. | `emails` +| **App Engine** +| `STACKKIT_APP_ENGINE_TASK` (optional) | Set to true to use App Engine task (else a Http task will be used). Defaults to false. | `true` +| `STACKKIT_APP_ENGINE_SERVICE` (optional) | The App Engine service to handle the task (only if using App Engine task). | `api` +| **Non- App Engine apps** +| `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. | `my-service-account@appspot.gserviceaccount.com` +| `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://.com` +
+ +### How to + +#### Passing headers to a task + +You can pass headers to a task by using the `withHeaders` method on the queue connection. + +```php +use Illuminate\Queue\Queue; + +Queue::connection()->setTaskHeaders([ + 'X-My-Header' => 'My-Value', +]); +``` + +If necessary, the current job being dispatched is also available: + +```php +use Illuminate\Queue\Queue; + +Queue::connection()->setTaskHeaders(fn (array $job) => [ + 'X-My-Header' => $job['displayName'] +]); +``` +
- How it works & Differences +How it works & Differences -
- Using Cloud Tasks as a Laravel queue driver is fundamentally different than other Laravel queue drivers, like Redis. +
+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. +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 -- Backoff, retries, max tries, retryUntil are all handled by Laravel. All these options are ignored in the Cloud Tasks configuration. +- Backoff, retries, max tries, retryUntil are all handled by Laravel. All these options are ignored in the Cloud Tasks + configuration.
- Dashboard (beta) -
- The package comes with a beautiful dashboard that can be used to monitor all queued jobs. +Dashboard (beta) +
+The package comes with a beautiful dashboard that can be used to monitor all queued jobs. - + - --- +--- _Experimental_ @@ -126,48 +155,52 @@ The dashboard works by storing all outgoing tasks in a database table. When Clou package handles the task, we will automatically update the tasks' status, attempts and possible errors. -There is probably a (small) performance penalty because each task dispatch and handling does extra database read and writes. +There is probably a (small) performance penalty because each task dispatch and handling does extra database read and +writes. Also, the dashboard has not been tested with high throughput queues. - --- +--- To make use of it, enable it through the `.env` file: - ```dotenv - STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED=true - STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD=MySecretLoginPasswordPleaseChangeThis - ``` +```dotenv +STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED=true +STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD=MySecretLoginPasswordPleaseChangeThis +``` Then publish its assets and migrations: - ```console - php artisan vendor:publish --tag=cloud-tasks - php artisan migrate - ``` +```console +php artisan vendor:publish --tag=cloud-tasks +php artisan migrate +``` The dashboard is accessible at the URI: /cloud-tasks
- Authentication -
+Authentication +
Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable with a path to the credentials file. More info: https://cloud.google.com/docs/authentication/production -If you're not using your master service account (which has all abilities), you must add the following roles to make it works: +If you're not using your master service account (which has all abilities), you must add the following roles to make it +works: + 1. App Engine Viewer 2. Cloud Tasks Enqueuer 3. Cloud Tasks Viewer 4. Cloud Tasks Task Deleter 5. Service Account User +
- Security -
- 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. +Security +
+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. This package verifies that the token is digitally signed by Google. Only Google Tasks will be able to call your handler. @@ -176,7 +209,7 @@ More information about OpenID Connect: https://developers.google.com/identity/protocols/oauth2/openid-connect
- Upgrading -
- Read [UPGRADING.MD](UPGRADING.md) on how to update versions. +Upgrading +
+Read [UPGRADING.MD](UPGRADING.md) on how to update versions.
diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 17eca63..72edbd8 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -4,6 +4,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; +use Closure; use Google\Cloud\Tasks\V2\AppEngineHttpRequest; use Google\Cloud\Tasks\V2\AppEngineRouting; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; @@ -15,7 +16,6 @@ use Google\Protobuf\Timestamp; use Illuminate\Contracts\Queue\Queue as QueueContract; use Illuminate\Queue\Queue as LaravelQueue; -use Illuminate\Support\Carbon; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; use function Safe\json_decode; @@ -24,6 +24,8 @@ class CloudTasksQueue extends LaravelQueue implements QueueContract { + private Closure | array $headers = []; + public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false) { // @@ -184,6 +186,8 @@ private function enrichPayloadWithInternalData( public function addPayloadToTask(array $payload, Task $task): Task { + $headers = value($this->headers, $payload) ?: []; + if (!empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); @@ -191,6 +195,7 @@ public function addPayloadToTask(array $payload, Task $task): Task $appEngineRequest->setRelativeUri($path); $appEngineRequest->setHttpMethod(HttpMethod::POST); $appEngineRequest->setBody(json_encode($payload)); + $appEngineRequest->setHeaders($headers); if (!empty($service = $this->config['app_engine_service'])) { $routing = new AppEngineRouting(); @@ -202,9 +207,9 @@ public function addPayloadToTask(array $payload, Task $task): Task } else { $httpRequest = new HttpRequest(); $httpRequest->setUrl($this->getHandler()); - $httpRequest->setBody(json_encode($payload)); $httpRequest->setHttpMethod(HttpMethod::POST); + $httpRequest->setHeaders($headers); $token = new OidcToken; $token->setServiceAccountEmail($this->config['service_account_email']); @@ -251,4 +256,9 @@ public function getHandler(): string return $handler.'/'. config('cloud-tasks.uri'); } + + public function setTaskHeaders(Closure | array $headers): void + { + $this->headers = $headers; + } } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 9226db2..f46b3aa 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -15,6 +15,7 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Queue; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; @@ -475,4 +476,48 @@ public function it_adds_a_task_name_based_on_the_display_name() ); }); } + + /** + * @test + */ + public function headers_can_be_added_to_the_task() + { + // Arrange + CloudTasksApi::fake(); + + // Act + Queue::connection()->setTaskHeaders([ + 'X-MyHeader' => 'MyValue', + ]); + + $this->dispatch((new SimpleJob())); + + // Assert + CloudTasksApi::assertTaskCreated(function (Task $task): bool { + return $task->getHttpRequest()->getHeaders()['X-MyHeader'] === 'MyValue'; + }); + } + + /** + * @test + */ + public function headers_can_be_added_to_the_task_with_job_context() + { + // Arrange + CloudTasksApi::fake(); + + // Act + Queue::connection()->setTaskHeaders(function (array $payload) { + return [ + 'X-MyHeader' => $payload['displayName'], + ]; + }); + + $this->dispatch((new SimpleJob())); + + // Assert + CloudTasksApi::assertTaskCreated(function (Task $task): bool { + return $task->getHttpRequest()->getHeaders()['X-MyHeader'] === SimpleJob::class; + }); + } } From 6a23ee8bbefa7a98a7a6cc397703296de9866678 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 21 Feb 2024 22:33:05 +0100 Subject: [PATCH 27/46] Test package with Laravel 11 --- .github/workflows/run-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index bf0c7a2..4309d06 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -67,6 +67,8 @@ jobs: - { queue: 'github-actions-laravel10-php83', laravel: '10.*', php: '8.3', 'testbench': '8.*'} - { queue: 'github-actions-laravel10-php82', laravel: '10.*', php: '8.2', 'testbench': '8.*'} - { queue: 'github-actions-laravel10-php81', laravel: '10.*', php: '8.1', 'testbench': '8.*'} + - { queue: 'github-actions-laravel11-php82', laravel: '11.*', php: '8.2', 'testbench': '9.*' } + - { queue: 'github-actions-laravel12-php83', laravel: '11.*', php: '8.3', 'testbench': '9.*' } name: PHP ${{ matrix.payload.php }} - Laravel ${{ matrix.payload.laravel }} - DB ${{ matrix.db }} From 0ba0b99716c66532e079271d6a3ca2cdc3a0b1ea Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 21 Feb 2024 22:43:07 +0100 Subject: [PATCH 28/46] Fix "Metadata found in doc-comment" --- tests/CloudTasksApiTest.php | 13 ++----- tests/ConfigHandlerTest.php | 5 ++- tests/QueueAppEngineTest.php | 13 ++----- tests/QueueTest.php | 73 ++++++++++++------------------------ tests/TaskHandlerTest.php | 53 ++++++++------------------ 5 files changed, 50 insertions(+), 107 deletions(-) diff --git a/tests/CloudTasksApiTest.php b/tests/CloudTasksApiTest.php index c36d988..2dd6e2a 100644 --- a/tests/CloudTasksApiTest.php +++ b/tests/CloudTasksApiTest.php @@ -10,6 +10,7 @@ use Google\Cloud\Tasks\V2\HttpRequest; use Google\Cloud\Tasks\V2\Task; use Google\Protobuf\Timestamp; +use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; class CloudTasksApiTest extends TestCase @@ -41,9 +42,7 @@ protected function setUp(): void } - /** - * @test - */ + #[Test] public function test_create_task() { // Arrange @@ -72,9 +71,7 @@ public function test_create_task() ); } - /** - * @test - */ + #[Test] public function test_delete_task_on_non_existing_task() { // Assert @@ -93,9 +90,7 @@ public function test_delete_task_on_non_existing_task() } - /** - * @test - */ + #[Test] public function test_delete_task() { // Arrange diff --git a/tests/ConfigHandlerTest.php b/tests/ConfigHandlerTest.php index 4711d2a..437473c 100644 --- a/tests/ConfigHandlerTest.php +++ b/tests/ConfigHandlerTest.php @@ -5,6 +5,7 @@ namespace Tests; use Google\Cloud\Tasks\V2\Task; +use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Tests\Support\SimpleJob; @@ -26,7 +27,7 @@ public function test_it_allows_a_handler_url_to_contain_path(string $handler, st }); } - /** @test */ + #[Test] public function the_handle_route_task_uri_can_be_configured(): void { CloudTasksApi::fake(); @@ -40,7 +41,7 @@ public function the_handle_route_task_uri_can_be_configured(): void }); } - /** @test */ + #[Test] public function the_handle_route_task_uri_in_combination_with_path_can_be_configured(): void { CloudTasksApi::fake(); diff --git a/tests/QueueAppEngineTest.php b/tests/QueueAppEngineTest.php index 994444f..1f2e8e4 100644 --- a/tests/QueueAppEngineTest.php +++ b/tests/QueueAppEngineTest.php @@ -5,6 +5,7 @@ namespace Tests; use Google\Cloud\Tasks\V2\Task; +use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Tests\Support\SimpleJob; @@ -17,9 +18,7 @@ protected function setUp(): void $this->withTaskType('appengine'); } - /** - * @test - */ + #[Test] public function an_app_engine_http_request_with_the_handler_url_is_made() { // Arrange @@ -34,9 +33,7 @@ public function an_app_engine_http_request_with_the_handler_url_is_made() }); } - /** - * @test - */ + #[Test] public function it_routes_to_the_service() { // Arrange @@ -51,9 +48,7 @@ public function it_routes_to_the_service() }); } - /** - * @test - */ + #[Test] public function it_contains_the_payload() { // Arrange diff --git a/tests/QueueTest.php b/tests/QueueTest.php index f46b3aa..d43739f 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -14,6 +14,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Queue; +use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; @@ -27,9 +28,7 @@ class QueueTest extends TestCase { - /** - * @test - */ + #[Test] public function a_http_request_with_the_handler_url_is_made() { // Arrange @@ -44,9 +43,7 @@ public function a_http_request_with_the_handler_url_is_made() }); } - /** - * @test - */ + #[Test] public function it_posts_to_the_handler() { // Arrange @@ -61,9 +58,7 @@ public function it_posts_to_the_handler() }); } - /** - * @test - */ + #[Test] public function it_posts_to_the_correct_handler_url() { // Arrange @@ -79,9 +74,7 @@ public function it_posts_to_the_correct_handler_url() }); } - /** - * @test - */ + #[Test] public function it_posts_the_serialized_job_payload_to_the_handler() { // Arrange @@ -100,9 +93,7 @@ public function it_posts_the_serialized_job_payload_to_the_handler() }); } - /** - * @test - */ + #[Test] public function it_will_set_the_scheduled_time_when_dispatching_later() { // Arrange @@ -118,9 +109,7 @@ public function it_will_set_the_scheduled_time_when_dispatching_later() }); } - /** - * @test - */ + #[Test] public function test_dispatch_deadline_config() { // Arrange @@ -137,9 +126,7 @@ public function test_dispatch_deadline_config() }); } - /** - * @test - */ + #[Test] public function it_posts_the_task_the_correct_queue() { // Arrange @@ -169,9 +156,7 @@ public function it_posts_the_task_the_correct_queue() }); } - /** - * @test - */ + #[Test] public function it_can_dispatch_after_commit_inline() { // Arrange @@ -191,9 +176,7 @@ public function it_can_dispatch_after_commit_inline() }); } - /** - * @test - */ + #[Test] public function it_can_dispatch_after_commit_through_config() { // Arrange @@ -214,9 +197,7 @@ public function it_can_dispatch_after_commit_through_config() }); } - /** - * @test - */ + #[Test] public function jobs_can_be_released() { // Arrange @@ -258,9 +239,7 @@ public function jobs_can_be_released() }); } - /** - * @test - */ + #[Test] public function jobs_can_be_released_with_a_delay() { // Arrange @@ -287,7 +266,7 @@ public function jobs_can_be_released_with_a_delay() }); } - /** @test */ + #[Test] public function test_default_backoff() { // Arrange @@ -303,7 +282,7 @@ public function test_default_backoff() }); } - /** @test */ + #[Test] public function test_backoff_from_queue_config() { // Arrange @@ -322,7 +301,7 @@ public function test_backoff_from_queue_config() }); } - /** @test */ + #[Test] public function test_backoff_from_job() { // Arrange @@ -342,7 +321,7 @@ public function test_backoff_from_job() }); } - /** @test */ + #[Test] public function test_exponential_backoff_from_job_method() { // Arrange @@ -370,7 +349,7 @@ public function test_exponential_backoff_from_job_method() }); } - /** @test */ + #[Test] public function test_failing_method_on_job() { // Arrange @@ -387,7 +366,7 @@ public function test_failing_method_on_job() Event::assertDispatched(fn (JobOutput $event) => $event->output === 'FailingJob:failed'); } - /** @test */ + #[Test] public function test_queue_before_and_after_hooks() { // Arrange @@ -408,7 +387,7 @@ public function test_queue_before_and_after_hooks() Event::assertDispatched(fn (JobOutput $event) => $event->output === 'Queue::after:Tests\Support\SimpleJob'); } - /** @test */ + #[Test] public function test_queue_looping_hook_not_supported_with_this_package() { // Arrange @@ -426,7 +405,7 @@ public function test_queue_looping_hook_not_supported_with_this_package() Event::assertDispatched(fn (JobOutput $event) => $event->output === 'SimpleJob:success'); } - /** @test */ + #[Test] public function test_ignoring_jobs_with_deleted_models() { // Arrange @@ -457,9 +436,7 @@ public function test_ignoring_jobs_with_deleted_models() CloudTasksApi::assertTaskNotDeleted($job->task->getName()); } - /** - * @test - */ + #[Test] public function it_adds_a_task_name_based_on_the_display_name() { // Arrange @@ -477,9 +454,7 @@ public function it_adds_a_task_name_based_on_the_display_name() }); } - /** - * @test - */ + #[Test] public function headers_can_be_added_to_the_task() { // Arrange @@ -498,9 +473,7 @@ public function headers_can_be_added_to_the_task() }); } - /** - * @test - */ + #[Test] public function headers_can_be_added_to_the_task_with_job_context() { // Arrange diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 7db2234..f4840c8 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -6,6 +6,8 @@ use Illuminate\Queue\Events\JobReleasedAfterException; use Illuminate\Support\Facades\Event; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestWith; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Tests\Support\EncryptedJob; use Tests\Support\FailingJob; @@ -25,9 +27,7 @@ protected function setUp(): void CloudTasksApi::fake(); } - /** - * @test - */ + #[Test] public function it_can_run_a_task() { // Arrange @@ -40,9 +40,7 @@ public function it_can_run_a_task() Event::assertDispatched(fn(JobOutput $event) => $event->output === 'SimpleJob:success'); } - /** - * @test - */ + #[Test] public function it_can_run_a_task_using_the_task_connection() { // Arrange @@ -59,9 +57,7 @@ public function it_can_run_a_task_using_the_task_connection() Event::assertDispatched(fn(JobOutput $event) => $event->output === 'SimpleJob:success'); } - /** - * @test - */ + #[Test] public function after_max_attempts_it_will_log_to_failed_table() { // Arrange @@ -80,9 +76,7 @@ public function after_max_attempts_it_will_log_to_failed_table() $this->assertDatabaseCount('failed_jobs', 1); } - /** - * @test - */ + #[Test] public function after_max_attempts_it_will_delete_the_task() { // Arrange @@ -105,13 +99,10 @@ public function after_max_attempts_it_will_delete_the_task() $this->assertDatabaseCount('failed_jobs', 1); } - /** - * @test - * - * @testWith [{"now": "2020-01-01 00:00:00", "try_at": "2020-01-01 00:00:00", "should_fail": false}] - * [{"now": "2020-01-01 00:00:00", "try_at": "2020-01-01 00:04:59", "should_fail": false}] - * [{"now": "2020-01-01 00:00:00", "try_at": "2020-01-01 00:05:00", "should_fail": true}] - */ + #[Test] + #[TestWith([['now' => '2020-01-01 00:00:00', 'try_at' => '2020-01-01 00:00:00', 'should_fail' => false]])] + #[TestWith([['now' => '2020-01-01 00:00:00', 'try_at' => '2020-01-01 00:04:59', 'should_fail' => false]])] + #[TestWith([['now' => '2020-01-01 00:00:00', 'try_at' => '2020-01-01 00:05:00', 'should_fail' => true]])] public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the_task(array $args) { // Arrange @@ -135,9 +126,7 @@ public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the $this->assertDatabaseCount('failed_jobs', $args['should_fail'] ? 1 : 0); } - /** - * @test - */ + #[Test] public function test_unlimited_max_attempts() { // Act @@ -152,9 +141,7 @@ public function test_unlimited_max_attempts() CloudTasksApi::assertDeletedTaskCount(51); } - /** - * @test - */ + #[Test] public function test_max_attempts_in_combination_with_retry_until() { // Arrange @@ -182,9 +169,7 @@ public function test_max_attempts_in_combination_with_retry_until() $this->assertDatabaseCount('failed_jobs', 1); } - /** - * @test - */ + #[Test] public function it_can_handle_encrypted_jobs() { // Arrange @@ -203,9 +188,7 @@ public function it_can_handle_encrypted_jobs() Event::assertDispatched(fn(JobOutput $event) => $event->output === 'EncryptedJob:success'); } - /** - * @test - */ + #[Test] public function failing_jobs_are_released() { // Arrange @@ -228,9 +211,7 @@ public function failing_jobs_are_released() }); } - /** - * @test - */ + #[Test] public function attempts_are_tracked_internally() { // Arrange @@ -254,9 +235,7 @@ public function attempts_are_tracked_internally() }); } - /** - * @test - */ + #[Test] public function retried_jobs_get_a_new_name() { // Arrange From 8bb520a2a6a628fea3933c37e795a6d2c9bac968 Mon Sep 17 00:00:00 2001 From: Auke Terpstra Date: Tue, 27 Feb 2024 22:08:14 +0100 Subject: [PATCH 29/46] [4.x-dev] Can use the task handler url from the job, if available. Otherwise it falls back to the configured handler url. --- src/CloudTasksQueue.php | 30 +++++++++++++++++---------- src/HasTaskHandlerUrl.php | 10 +++++++++ tests/QueueTest.php | 20 ++++++++++++++++-- tests/Support/CustomHandlerUrlJob.php | 27 ++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 src/HasTaskHandlerUrl.php create mode 100644 tests/Support/CustomHandlerUrlJob.php diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 72edbd8..82d8f31 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -57,8 +57,8 @@ public function push($job, $data = '', $queue = null) $this->createPayload($job, $queue, $data), $queue, null, - function ($payload, $queue) { - return $this->pushRaw($payload, $queue); + function ($payload, $queue) use ($job) { + return $this->pushRaw($payload, $queue, ['job' => $job]); } ); } @@ -73,8 +73,9 @@ function ($payload, $queue) { public function pushRaw($payload, $queue = null, array $options = []) { $delay = ! empty($options['delay']) ? $options['delay'] : 0; + $job = $options['job'] ?? null; - return $this->pushToCloudTasks($queue, $payload, $delay); + return $this->pushToCloudTasks($queue, $payload, $delay, $job); } /** @@ -93,8 +94,8 @@ public function later($delay, $job, $data = '', $queue = null) $this->createPayload($job, $queue, $data), $queue, $delay, - function ($payload, $queue, $delay) { - return $this->pushToCloudTasks($queue, $payload, $delay); + function ($payload, $queue, $delay) use ($job) { + return $this->pushToCloudTasks($queue, $payload, $delay, $job); } ); } @@ -105,9 +106,10 @@ function ($payload, $queue, $delay) { * @param string|null $queue * @param string $payload * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|object $job * @return string */ - protected function pushToCloudTasks($queue, $payload, $delay = 0) + protected function pushToCloudTasks($queue, $payload, $delay, mixed $job) { $queue = $queue ?: $this->config['queue']; @@ -122,7 +124,7 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) connectionName: $this->getConnectionName(), ); - $this->addPayloadToTask($payload, $task); + $this->addPayloadToTask($payload, $task, $job); // The deadline for requests sent to the app. If the app does not respond by // this deadline then the request is cancelled and the attempt is marked as @@ -184,7 +186,8 @@ private function enrichPayloadWithInternalData( return $payload; } - public function addPayloadToTask(array $payload, Task $task): Task + /** @param string|object $job */ + public function addPayloadToTask(array $payload, Task $task, mixed $job): Task { $headers = value($this->headers, $payload) ?: []; @@ -206,7 +209,7 @@ public function addPayloadToTask(array $payload, Task $task): Task $task->setAppEngineHttpRequest($appEngineRequest); } else { $httpRequest = new HttpRequest(); - $httpRequest->setUrl($this->getHandler()); + $httpRequest->setUrl($this->getHandler($job)); $httpRequest->setBody(json_encode($payload)); $httpRequest->setHttpMethod(HttpMethod::POST); $httpRequest->setHeaders($headers); @@ -237,13 +240,18 @@ public function release(CloudTasksJob $job, int $delay = 0): void $payload = $job->getRawBody(); - $options = ['delay' => $delay]; + $options = ['delay' => $delay, 'job' => $job]; $this->pushRaw($payload, $job->getQueue(), $options); } - public function getHandler(): string + /** @param string|object $job */ + public function getHandler(mixed $job): string { + if ($job instanceof HasTaskHandlerUrl) { + return $job->taskHandlerUrl(); + } + if (empty($this->config['handler'])) { $this->config['handler'] = request()->getSchemeAndHttpHost(); } diff --git a/src/HasTaskHandlerUrl.php b/src/HasTaskHandlerUrl.php new file mode 100644 index 0000000..418d3c4 --- /dev/null +++ b/src/HasTaskHandlerUrl.php @@ -0,0 +1,10 @@ +setConfigValue('handler', 'https://docker.for.mac.localhost:8081'); @@ -74,6 +74,22 @@ public function it_posts_to_the_correct_handler_url() }); } + #[Test] + public function it_posts_to_the_job_handler_url() + { + // Arrange + $this->setConfigValue('handler', 'https://docker.for.mac.localhost:8081'); + CloudTasksApi::fake(); + + // Act + $this->dispatch(new CustomHandlerUrlJob()); + + // Assert + CloudTasksApi::assertTaskCreated(function (Task $task): bool { + return $task->getHttpRequest()->getUrl() === 'https://example.com/api/my-custom-route'; + }); + } + #[Test] public function it_posts_the_serialized_job_payload_to_the_handler() { diff --git a/tests/Support/CustomHandlerUrlJob.php b/tests/Support/CustomHandlerUrlJob.php new file mode 100644 index 0000000..a55734f --- /dev/null +++ b/tests/Support/CustomHandlerUrlJob.php @@ -0,0 +1,27 @@ + Date: Tue, 27 Feb 2024 22:17:18 +0100 Subject: [PATCH 30/46] [4.x-dev] A job can also have task headers, which are merged with any other headers. --- src/CloudTasksQueue.php | 6 ++++++ src/HasTaskHeaders.php | 11 +++++++++++ tests/QueueTest.php | 20 ++++++++++++++++++++ tests/Support/CustomHeadersJob.php | 30 ++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 src/HasTaskHeaders.php create mode 100644 tests/Support/CustomHeadersJob.php diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 82d8f31..71a6c8a 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -190,6 +190,12 @@ private function enrichPayloadWithInternalData( public function addPayloadToTask(array $payload, Task $task, mixed $job): Task { $headers = value($this->headers, $payload) ?: []; + if ($job instanceof HasTaskHeaders) { + $headers = [ + ...$headers, + ...$job->taskHeaders(), + ]; + } if (!empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); diff --git a/src/HasTaskHeaders.php b/src/HasTaskHeaders.php new file mode 100644 index 0000000..38c9b70 --- /dev/null +++ b/src/HasTaskHeaders.php @@ -0,0 +1,11 @@ + */ + public function taskHeaders(): array; +} \ No newline at end of file diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 66b9713..03e792a 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -18,6 +18,7 @@ use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Tests\Support\CustomHandlerUrlJob; +use Tests\Support\CustomHeadersJob; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; use Tests\Support\JobOutput; @@ -509,4 +510,23 @@ public function headers_can_be_added_to_the_task_with_job_context() return $task->getHttpRequest()->getHeaders()['X-MyHeader'] === SimpleJob::class; }); } + + #[Test] + public function job_headers_can_be_added_to_the_task() + { + // Arrange + CloudTasksApi::fake(); + + // Act + Queue::connection()->setTaskHeaders([ + 'X-MyHeader' => 'MyValue', + ]); + $this->dispatch((new CustomHeadersJob())); + + // Assert + CloudTasksApi::assertTaskCreated(function (Task $task): bool { + $headers = $task->getHttpRequest()->getHeaders(); + return $headers['X-MyHeader'] === 'MyValue' && $headers['X-MyJobHeader'] === 'MyJobValue'; + }); + } } diff --git a/tests/Support/CustomHeadersJob.php b/tests/Support/CustomHeadersJob.php new file mode 100644 index 0000000..05baca5 --- /dev/null +++ b/tests/Support/CustomHeadersJob.php @@ -0,0 +1,30 @@ + 'MyJobValue', + ]; + } +} \ No newline at end of file From b5c9241afe8077d7333eadf77e91f0f13f55543f Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 4 Mar 2024 22:48:50 +0100 Subject: [PATCH 31/46] Add support for job timeouts --- src/CloudTasksServiceProvider.php | 11 ++++++ src/TaskHandler.php | 3 +- src/Worker.php | 52 ++++++++++++++++++++++++++ tests/Support/SimpleJobWithTimeout.php | 30 +++++++++++++++ tests/TaskHandlerTest.php | 22 +++++++++++ 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/Worker.php create mode 100644 tests/Support/SimpleJobWithTimeout.php diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index e53edae..9db6530 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -5,6 +5,8 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; +use Illuminate\Contracts\Debug\ExceptionHandler; +use Illuminate\Foundation\Application; use Illuminate\Queue\Events\JobExceptionOccurred; use Illuminate\Queue\Events\JobFailed; use Illuminate\Queue\Events\JobProcessed; @@ -29,6 +31,15 @@ private function registerClient(): void return new CloudTasksClient(); }); + $this->app->singleton('cloud-tasks.worker', function (Application $app) { + return new Worker( + $app['queue'], + $app['events'], + $app[ExceptionHandler::class], + fn() => $app->isDownForMaintenance(), + ); + }); + $this->app->bind('cloud-tasks-api', CloudTasksApiConcrete::class); } diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 9e910ea..28669a1 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -6,7 +6,6 @@ use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Container\Container; -use Illuminate\Queue\Worker; use Illuminate\Queue\WorkerOptions; class TaskHandler @@ -51,7 +50,7 @@ private function run(IncomingTask $task): void $job->setAttempts($job->attempts() + 1); - tap(app('queue.worker'), fn (Worker $worker) => $worker->process( + tap(app('cloud-tasks.worker'), fn (Worker $worker) => $worker->process( connectionName: $job->getConnectionName(), job: $job, options: $this->getWorkerOptions() diff --git a/src/Worker.php b/src/Worker.php new file mode 100644 index 0000000..f00d85f --- /dev/null +++ b/src/Worker.php @@ -0,0 +1,52 @@ +supportsAsyncSignals()) { + $this->listenForSignals(); + + $this->registerTimeoutHandler($job, $options); + } + + return parent::process($connectionName, $job, $options); + } + + public function kill($status = 0, $options = null): void + { + parent::stop($status, $options); + + // When running tests, we cannot run exit because it will kill the PHPunit process. + // So, to still test that the application has exited, we will simply rely on the + // WorkerStopped event that is fired when the worker is stopped. + if (app()->runningUnitTests()) { + return; + } + + exit($status); + } +} diff --git a/tests/Support/SimpleJobWithTimeout.php b/tests/Support/SimpleJobWithTimeout.php new file mode 100644 index 0000000..72296aa --- /dev/null +++ b/tests/Support/SimpleJobWithTimeout.php @@ -0,0 +1,30 @@ +assertCount(2, $this->createdTasks); $this->assertNotEquals($this->createdTasks[0]->getName(), $this->createdTasks[1]->getName()); } + + #[Test] + public function test_job_timeout() + { + // Arrange + Event::fake(JobOutput::class); + + // Act + $this->dispatch(new SimpleJobWithTimeout())->run(); + + // Assert + $events = Event::dispatched(JobOutput::class)->map(fn($event) => $event[0]->output)->toArray(); + $this->assertEquals([ + 'SimpleJobWithTimeout:1', + 'SimpleJobWithTimeout:2', + 'SimpleJobWithTimeout:3', + 'SimpleJobWithTimeout:worker-stopping', + 'SimpleJobWithTimeout:4', + 'SimpleJobWithTimeout:5', + ], $events); + } } From b377efa57f810a43e1f21ac7444f2c9af29d15b4 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Mon, 4 Mar 2024 22:49:31 +0100 Subject: [PATCH 32/46] Pint --- src/CloudTasksQueue.php | 17 ++++++++--------- src/CloudTasksServiceProvider.php | 2 +- src/IncomingTask.php | 1 + tests/QueueTest.php | 1 - tests/TaskHandlerTest.php | 8 ++++---- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 72edbd8..969ae27 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -24,7 +24,7 @@ class CloudTasksQueue extends LaravelQueue implements QueueContract { - private Closure | array $headers = []; + private Closure|array $headers = []; public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false) { @@ -152,7 +152,7 @@ private function taskName(string $queueName, array $payload): string $this->config['project'], $this->config['location'], $queueName, - $displayName.'-'. bin2hex(random_bytes(8)), + $displayName.'-'.bin2hex(random_bytes(8)), ); } @@ -172,8 +172,7 @@ private function enrichPayloadWithInternalData( string $queueName, string $taskName, string $connectionName, - ): array - { + ): array { $payload['internal'] = [ 'attempts' => $payload['internal']['attempts'] ?? 0, 'queue' => $queueName, @@ -188,7 +187,7 @@ public function addPayloadToTask(array $payload, Task $task): Task { $headers = value($this->headers, $payload) ?: []; - if (!empty($this->config['app_engine'])) { + if (! empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); $appEngineRequest = new AppEngineHttpRequest(); @@ -197,7 +196,7 @@ public function addPayloadToTask(array $payload, Task $task): Task $appEngineRequest->setBody(json_encode($payload)); $appEngineRequest->setHeaders($headers); - if (!empty($service = $this->config['app_engine_service'])) { + if (! empty($service = $this->config['app_engine_service'])) { $routing = new AppEngineRouting(); $routing->setService($service); $appEngineRequest->setAppEngineRouting($routing); @@ -250,14 +249,14 @@ public function getHandler(): string $handler = rtrim($this->config['handler'], '/'); - if (str_ends_with($handler, '/'. config('cloud-tasks.uri'))) { + if (str_ends_with($handler, '/'.config('cloud-tasks.uri'))) { return $handler; } - return $handler.'/'. config('cloud-tasks.uri'); + return $handler.'/'.config('cloud-tasks.uri'); } - public function setTaskHeaders(Closure | array $headers): void + public function setTaskHeaders(Closure|array $headers): void { $this->headers = $headers; } diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index 9db6530..f6fdfad 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -36,7 +36,7 @@ private function registerClient(): void $app['queue'], $app['events'], $app[ExceptionHandler::class], - fn() => $app->isDownForMaintenance(), + fn () => $app->isDownForMaintenance(), ); }); diff --git a/src/IncomingTask.php b/src/IncomingTask.php index fae4b2a..b2da5bf 100644 --- a/src/IncomingTask.php +++ b/src/IncomingTask.php @@ -5,6 +5,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Safe\Exceptions\JsonException; + use function Safe\json_decode; class IncomingTask diff --git a/tests/QueueTest.php b/tests/QueueTest.php index d43739f..05b2286 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -16,7 +16,6 @@ use Illuminate\Support\Facades\Queue; use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; -use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 36093ed..cc34540 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -38,7 +38,7 @@ public function it_can_run_a_task() $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); // Assert - Event::assertDispatched(fn(JobOutput $event) => $event->output === 'SimpleJob:success'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'SimpleJob:success'); } #[Test] @@ -55,7 +55,7 @@ public function it_can_run_a_task_using_the_task_connection() $this->dispatch($job)->runWithoutExceptionHandler(); // Assert - Event::assertDispatched(fn(JobOutput $event) => $event->output === 'SimpleJob:success'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'SimpleJob:success'); } #[Test] @@ -186,7 +186,7 @@ public function it_can_handle_encrypted_jobs() decrypt($job->payloadAsArray('data.command')), ); - Event::assertDispatched(fn(JobOutput $event) => $event->output === 'EncryptedJob:success'); + Event::assertDispatched(fn (JobOutput $event) => $event->output === 'EncryptedJob:success'); } #[Test] @@ -260,7 +260,7 @@ public function test_job_timeout() $this->dispatch(new SimpleJobWithTimeout())->run(); // Assert - $events = Event::dispatched(JobOutput::class)->map(fn($event) => $event[0]->output)->toArray(); + $events = Event::dispatched(JobOutput::class)->map(fn ($event) => $event[0]->output)->toArray(); $this->assertEquals([ 'SimpleJobWithTimeout:1', 'SimpleJobWithTimeout:2', From 841471cce5e92320cb4efd7c2ec0317614a247dd Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Wed, 6 Mar 2024 22:34:06 +0100 Subject: [PATCH 33/46] Potentially improve task insert performance by using hashed random id as task name --- src/CloudTasksQueue.php | 20 +++----------------- tests/QueueTest.php | 7 ++----- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 969ae27..0392bcd 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -20,7 +20,6 @@ use function Safe\json_decode; use function Safe\json_encode; -use function Safe\preg_replace; class CloudTasksQueue extends LaravelQueue implements QueueContract { @@ -113,7 +112,7 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = (array) json_decode($payload, true); - $task = tap(new Task())->setName($this->taskName($queue, $payload)); + $task = tap(new Task())->setName($this->taskName($queue)); $payload = $this->enrichPayloadWithInternalData( payload: $payload, @@ -144,29 +143,16 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) return $payload['uuid']; } - private function taskName(string $queueName, array $payload): string + private function taskName(string $queueName): string { - $displayName = $this->sanitizeTaskName($payload['displayName']); - return CloudTasksClient::taskName( $this->config['project'], $this->config['location'], $queueName, - $displayName.'-'.bin2hex(random_bytes(8)), + bin2hex(random_bytes(16)), ); } - private function sanitizeTaskName(string $taskName): string - { - // Remove all characters that are not -, letters, numbers, or whitespace - $sanitizedName = preg_replace('![^-\pL\pN\s]+!u', '-', $taskName); - - // Replace all separator characters and whitespace by a - - $sanitizedName = preg_replace('![-\s]+!u', '-', $sanitizedName); - - return trim($sanitizedName, '-'); - } - private function enrichPayloadWithInternalData( array $payload, string $queueName, diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 05b2286..9e11b42 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -436,7 +436,7 @@ public function test_ignoring_jobs_with_deleted_models() } #[Test] - public function it_adds_a_task_name_based_on_the_display_name() + public function it_adds_a_pre_defined_task_name() { // Arrange CloudTasksApi::fake(); @@ -446,10 +446,7 @@ public function it_adds_a_task_name_based_on_the_display_name() // Assert CloudTasksApi::assertTaskCreated(function (Task $task): bool { - return str_starts_with( - $task->getName(), - 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/Tests-Support-SimpleJob' - ); + return str($task->getName())->test('/projects\/.+\/locations\/.+\/queues\/.+\/tasks\/[a-z0-9]{16}/'); }); } From 7a0f7dff5c66110c3269aff5b65f64ab5479fbaa Mon Sep 17 00:00:00 2001 From: Auke Terpstra Date: Wed, 13 Mar 2024 20:44:00 +0100 Subject: [PATCH 34/46] [4.x-dev] Can set the HandlerUrl using a Closure callback. If given, the handler url is used from that closure. --- src/CloudTasksQueue.php | 16 +++++++------- src/HasTaskHandlerUrl.php | 10 --------- src/HasTaskHeaders.php | 11 ---------- tests/QueueTest.php | 31 ++++++--------------------- tests/Support/CustomHandlerUrlJob.php | 27 ----------------------- tests/Support/CustomHeadersJob.php | 30 -------------------------- 6 files changed, 15 insertions(+), 110 deletions(-) delete mode 100644 src/HasTaskHandlerUrl.php delete mode 100644 src/HasTaskHeaders.php delete mode 100644 tests/Support/CustomHandlerUrlJob.php delete mode 100644 tests/Support/CustomHeadersJob.php diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 71a6c8a..e45d78d 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -25,11 +25,17 @@ class CloudTasksQueue extends LaravelQueue implements QueueContract { private Closure | array $headers = []; + private static ?Closure $handlerUrlCallback = null; public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false) { // } + + public static function configureHandlerUrlUsing(Closure $callback): void + { + static::$handlerUrlCallback = $callback; + } /** * Get the size of the queue. @@ -190,12 +196,6 @@ private function enrichPayloadWithInternalData( public function addPayloadToTask(array $payload, Task $task, mixed $job): Task { $headers = value($this->headers, $payload) ?: []; - if ($job instanceof HasTaskHeaders) { - $headers = [ - ...$headers, - ...$job->taskHeaders(), - ]; - } if (!empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); @@ -254,8 +254,8 @@ public function release(CloudTasksJob $job, int $delay = 0): void /** @param string|object $job */ public function getHandler(mixed $job): string { - if ($job instanceof HasTaskHandlerUrl) { - return $job->taskHandlerUrl(); + if (static::$handlerUrlCallback) { + return (static::$handlerUrlCallback)($job); } if (empty($this->config['handler'])) { diff --git a/src/HasTaskHandlerUrl.php b/src/HasTaskHandlerUrl.php deleted file mode 100644 index 418d3c4..0000000 --- a/src/HasTaskHandlerUrl.php +++ /dev/null @@ -1,10 +0,0 @@ - */ - public function taskHeaders(): array; -} \ No newline at end of file diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 03e792a..82c35c0 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -16,9 +16,8 @@ use Illuminate\Support\Facades\Queue; use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; -use Tests\Support\CustomHandlerUrlJob; -use Tests\Support\CustomHeadersJob; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; use Tests\Support\JobOutput; @@ -76,18 +75,21 @@ public function it_posts_to_the_configured_handler_url() } #[Test] - public function it_posts_to_the_job_handler_url() + public function it_posts_to_the_callback_handler_url() { // Arrange $this->setConfigValue('handler', 'https://docker.for.mac.localhost:8081'); CloudTasksApi::fake(); + CloudTasksQueue::configureHandlerUrlUsing(static fn(SimpleJob $job) => 'https://example.com/api/my-custom-route?job=' . $job->id); // Act - $this->dispatch(new CustomHandlerUrlJob()); + $job = new SimpleJob(); + $job->id = 1; + $this->dispatch($job); // Assert CloudTasksApi::assertTaskCreated(function (Task $task): bool { - return $task->getHttpRequest()->getUrl() === 'https://example.com/api/my-custom-route'; + return $task->getHttpRequest()->getUrl() === 'https://example.com/api/my-custom-route?job=1'; }); } @@ -510,23 +512,4 @@ public function headers_can_be_added_to_the_task_with_job_context() return $task->getHttpRequest()->getHeaders()['X-MyHeader'] === SimpleJob::class; }); } - - #[Test] - public function job_headers_can_be_added_to_the_task() - { - // Arrange - CloudTasksApi::fake(); - - // Act - Queue::connection()->setTaskHeaders([ - 'X-MyHeader' => 'MyValue', - ]); - $this->dispatch((new CustomHeadersJob())); - - // Assert - CloudTasksApi::assertTaskCreated(function (Task $task): bool { - $headers = $task->getHttpRequest()->getHeaders(); - return $headers['X-MyHeader'] === 'MyValue' && $headers['X-MyJobHeader'] === 'MyJobValue'; - }); - } } diff --git a/tests/Support/CustomHandlerUrlJob.php b/tests/Support/CustomHandlerUrlJob.php deleted file mode 100644 index a55734f..0000000 --- a/tests/Support/CustomHandlerUrlJob.php +++ /dev/null @@ -1,27 +0,0 @@ - 'MyJobValue', - ]; - } -} \ No newline at end of file From fa0d67545acf7d837f6324399e8ff14b15055ec6 Mon Sep 17 00:00:00 2001 From: Auke Terpstra Date: Wed, 13 Mar 2024 20:49:52 +0100 Subject: [PATCH 35/46] [4.x-dev] Import class --- tests/QueueTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/QueueTest.php b/tests/QueueTest.php index b236aa8..82c35c0 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -16,6 +16,7 @@ use Illuminate\Support\Facades\Queue; use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; From 17a9d5942c0bf96b4d3deca1b021f3e0bf1c40a9 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 24 Mar 2024 12:56:30 +0100 Subject: [PATCH 36/46] Improve task deduplication and name in Cloud Tasks --- src/CloudTasksQueue.php | 10 +++++++--- tests/QueueTest.php | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 0392bcd..03b0531 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -16,6 +16,7 @@ use Google\Protobuf\Timestamp; use Illuminate\Contracts\Queue\Queue as QueueContract; use Illuminate\Queue\Queue as LaravelQueue; +use Illuminate\Support\Str; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; use function Safe\json_decode; @@ -112,7 +113,7 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) $payload = (array) json_decode($payload, true); - $task = tap(new Task())->setName($this->taskName($queue)); + $task = tap(new Task())->setName($this->taskName($queue, $payload['displayName'])); $payload = $this->enrichPayloadWithInternalData( payload: $payload, @@ -143,13 +144,16 @@ protected function pushToCloudTasks($queue, $payload, $delay = 0) return $payload['uuid']; } - private function taskName(string $queueName): string + private function taskName(string $queueName, string $displayName): string { return CloudTasksClient::taskName( $this->config['project'], $this->config['location'], $queueName, - bin2hex(random_bytes(16)), + str($displayName) + ->afterLast('\\') + ->prepend((string) Str::ulid(), '-') + ->toString(), ); } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 9e11b42..1cfe37d 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -14,6 +14,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Queue; +use Illuminate\Support\Str; use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; @@ -440,13 +441,14 @@ public function it_adds_a_pre_defined_task_name() { // Arrange CloudTasksApi::fake(); + Str::createUlidsUsingSequence(['01HSR4V9QE2F4T0K8RBAYQ88KE']); // Act $this->dispatch((new SimpleJob())); // Assert CloudTasksApi::assertTaskCreated(function (Task $task): bool { - return str($task->getName())->test('/projects\/.+\/locations\/.+\/queues\/.+\/tasks\/[a-z0-9]{16}/'); + return $task->getName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/01HSR4V9QE2F4T0K8RBAYQ88KE-SimpleJob'; }); } From 3ffdee80642b078ec16192df5c17bf82f1bc8d7f Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 24 Mar 2024 15:32:37 +0100 Subject: [PATCH 37/46] Let Cloud Tasks handle task deletion --- src/CloudTasksJob.php | 21 +++------------------ src/CloudTasksQueue.php | 12 +++++------- src/IncomingTask.php | 2 +- src/TaskHandler.php | 9 +++++++-- tests/Support/FailingJob.php | 1 + tests/TaskHandlerTest.php | 24 ++++++++++-------------- 6 files changed, 27 insertions(+), 42 deletions(-) diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index ecf40cf..882286c 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -69,24 +69,9 @@ public function getTaskName(): string public function delete(): void { - // Laravel automatically calls delete() after a job is processed successfully. However, this is - // not what we want to happen in Cloud Tasks because Cloud Tasks will also delete the task upon - // a 200 OK status, which means a task is deleted twice, possibly resulting in errors. So if the - // task was processed successfully (no errors or failures) then we will not delete the task - // manually and will let Cloud Tasks do it. - $successful = - // If the task has failed, we should be able to delete it permanently - $this->hasFailed() === false - // If the task has errored, it should be released, which in process deletes the errored task - && $this->hasError() === false; - - if ($successful) { - return; - } - - parent::delete(); - - $this->driver->delete($this); + // Laravel automatically calls delete() after a job is processed successfully. + // However, this is not what we want to happen in Cloud Tasks because Cloud Tasks + // will also delete the task upon a 200 OK status, which means a task is deleted twice. } public function hasError(): bool diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 03b0531..1e714c1 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -222,13 +222,11 @@ public function delete(CloudTasksJob $job): void public function release(CloudTasksJob $job, int $delay = 0): void { - $job->delete(); - - $payload = $job->getRawBody(); - - $options = ['delay' => $delay]; - - $this->pushRaw($payload, $job->getQueue(), $options); + $this->pushRaw( + payload: $job->getRawBody(), + queue: $job->getQueue(), + options: ['delay' => $delay] + ); } public function getHandler(): string diff --git a/src/IncomingTask.php b/src/IncomingTask.php index b2da5bf..77b8ff1 100644 --- a/src/IncomingTask.php +++ b/src/IncomingTask.php @@ -26,7 +26,7 @@ public static function fromJson(string $payload): self } } - public function isEmpty(): bool + public function isInvalid(): bool { return $this->task === []; } diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 28669a1..c7c7de8 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -21,7 +21,7 @@ public function handle(?string $task = null): void { $task = IncomingTask::fromJson($task ?: request()->getContent()); - if ($task->isEmpty()) { + if ($task->isInvalid()) { abort(422, 'Invalid task payload'); } @@ -33,7 +33,12 @@ public function handle(?string $task = null): void $this->config = is_array($config) ? $config : []; - $this->run($task); + // We want to catch any errors so we have more fine-grained control over + // how tasks are retried. Cloud Tasks will retry the task if a 5xx status + // is returned. Because we manually manage retries by releaseing jobs, + // we never want to return a 5xx status as that will result in duplicate + // job attempts. + rescue(fn () => $this->run($task), report: false); } private function run(IncomingTask $task): void diff --git a/tests/Support/FailingJob.php b/tests/Support/FailingJob.php index f2b0339..b1b3157 100644 --- a/tests/Support/FailingJob.php +++ b/tests/Support/FailingJob.php @@ -12,6 +12,7 @@ class FailingJob extends BaseJob public function handle() { + event(new JobOutput('FailingJob:running')); throw new Error('simulating a failing job'); } diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index cc34540..8faa037 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -78,25 +78,23 @@ public function after_max_attempts_it_will_log_to_failed_table() } #[Test] - public function after_max_attempts_it_will_delete_the_task() + public function after_max_attempts_it_will_no_longer_execute_the_task() { // Arrange + Event::fake([JobOutput::class]); $job = $this->dispatch(new FailingJob()); // Act & Assert $releasedJob = $job->runAndGetReleasedJob(); - CloudTasksApi::assertDeletedTaskCount(1); - CloudTasksApi::assertTaskDeleted($job->task->getName()); + Event::assertDispatched(JobOutput::class, 1); $this->assertDatabaseCount('failed_jobs', 0); $releasedJob = $releasedJob->runAndGetReleasedJob(); - CloudTasksApi::assertDeletedTaskCount(2); - CloudTasksApi::assertTaskDeleted($job->task->getName()); + Event::assertDispatched(JobOutput::class, 2); $this->assertDatabaseCount('failed_jobs', 0); $releasedJob->run(); - CloudTasksApi::assertDeletedTaskCount(3); - CloudTasksApi::assertTaskDeleted($job->task->getName()); + Event::assertDispatched(JobOutput::class, 4); $this->assertDatabaseCount('failed_jobs', 1); } @@ -104,7 +102,7 @@ public function after_max_attempts_it_will_delete_the_task() #[TestWith([['now' => '2020-01-01 00:00:00', 'try_at' => '2020-01-01 00:00:00', 'should_fail' => false]])] #[TestWith([['now' => '2020-01-01 00:00:00', 'try_at' => '2020-01-01 00:04:59', 'should_fail' => false]])] #[TestWith([['now' => '2020-01-01 00:00:00', 'try_at' => '2020-01-01 00:05:00', 'should_fail' => true]])] - public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the_task(array $args) + public function after_max_retry_until_it_will_log_to_failed_table(array $args) { // Arrange $this->travelTo($args['now']); @@ -115,8 +113,6 @@ public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the $releasedJob = $job->runAndGetReleasedJob(); // Assert - CloudTasksApi::assertDeletedTaskCount(1); - CloudTasksApi::assertTaskDeleted($job->task->getName()); $this->assertDatabaseCount('failed_jobs', 0); // Act @@ -130,6 +126,9 @@ public function after_max_retry_until_it_will_log_to_failed_table_and_delete_the #[Test] public function test_unlimited_max_attempts() { + // Assert + Event::fake(JobOutput::class); + // Act $job = $this->dispatch(new FailingJobWithUnlimitedTries()); @@ -138,8 +137,7 @@ public function test_unlimited_max_attempts() $job = $job->runAndGetReleasedJob(); } - // -1 because the last job is not run. - CloudTasksApi::assertDeletedTaskCount(51); + Event::assertDispatched(JobOutput::class, 51); } #[Test] @@ -204,9 +202,7 @@ public function failing_jobs_are_released() $job->run(); - CloudTasksApi::assertDeletedTaskCount(1); CloudTasksApi::assertCreatedTaskCount(2); - CloudTasksApi::assertTaskDeleted($job->task->getName()); Event::assertDispatched(JobReleasedAfterException::class, function ($event) { return $event->job->attempts() === 1; }); From 4cf5598db6ed35def3ceaaf37fd062bcf174af07 Mon Sep 17 00:00:00 2001 From: Auke Terpstra Date: Wed, 27 Mar 2024 20:25:50 +0100 Subject: [PATCH 38/46] [4.x-dev] Added missing test attribute --- tests/Support/SimpleJob.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Support/SimpleJob.php b/tests/Support/SimpleJob.php index e554d24..d443116 100644 --- a/tests/Support/SimpleJob.php +++ b/tests/Support/SimpleJob.php @@ -15,6 +15,7 @@ class SimpleJob implements ShouldQueue use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $tries = 3; + public $id = 0; /** * Create a new job instance. From 829f7205de45a095aa150d94e56ff7ab8997e2f1 Mon Sep 17 00:00:00 2001 From: Auke Terpstra Date: Wed, 27 Mar 2024 20:27:06 +0100 Subject: [PATCH 39/46] [4.x-dev] Added "setTaskHeadersUsing()" method to allow a closure to be passed for the task headers. This is the same as the "configureHandlerUrlUsing()" method. Also added some forget methods so these callbacks can be easily cleared if necessary. --- README.md | 32 +++++++++++++++++++++++++------- src/CloudTasksQueue.php | 31 +++++++++++++++++++++++++++---- tests/QueueTest.php | 20 ++++++++++++++------ 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 44586fa..749b314 100644 --- a/README.md +++ b/README.md @@ -102,26 +102,44 @@ Please check the table below on what the values mean and what their value should #### Passing headers to a task -You can pass headers to a task by using the `withHeaders` method on the queue connection. +You can pass headers to a task by using the `setTaskHeadersUsing` method on the `CloudTasksQueue` class. ```php -use Illuminate\Queue\Queue; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; -Queue::connection()->setTaskHeaders([ +CloudTasksQueue::setTaskHeadersUsing(static fn() => [ 'X-My-Header' => 'My-Value', ]); ``` -If necessary, the current job being dispatched is also available: +If necessary, the current payload being dispatched is also available: ```php -use Illuminate\Queue\Queue; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; -Queue::connection()->setTaskHeaders(fn (array $job) => [ - 'X-My-Header' => $job['displayName'] +CloudTasksQueue::setTaskHeadersUsing(static fn(array $payload) => [ + 'X-My-Header' => $payload['displayName'], ]); ``` +#### Configure task handler url + +You can set the handler url for a task by using the `configureHandlerUrlUsing` method on the `CloudTasksQueue` class. + +```php +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; + +CloudTasksQueue::configureHandlerUrlUsing(static fn() => 'https://example.com/my-url'); +``` + +If necessary, the current job being dispatched is also available: + +```php +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; + +CloudTasksQueue::configureHandlerUrlUsing(static fn(MyJob $job) => 'https://example.com/my-url/' . $job->something()); +``` +
How it works & Differences diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index e491d00..a4980e5 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -24,8 +24,8 @@ class CloudTasksQueue extends LaravelQueue implements QueueContract { - private Closure|array $headers = []; private static ?Closure $handlerUrlCallback = null; + private static ?Closure $taskHeadersCallback = null; public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false) { @@ -37,6 +37,21 @@ public static function configureHandlerUrlUsing(Closure $callback): void static::$handlerUrlCallback = $callback; } + public static function forgetHandlerUrlCallback(): void + { + self::$handlerUrlCallback = null; + } + + public static function setTaskHeadersUsing(Closure $callback): void + { + static::$taskHeadersCallback = $callback; + } + + public static function forgetTaskHeadersCallback(): void + { + self::$taskHeadersCallback = null; + } + /** * Get the size of the queue. * @@ -194,7 +209,7 @@ private function enrichPayloadWithInternalData( /** @param string|object $job */ public function addPayloadToTask(array $payload, Task $task, mixed $job): Task { - $headers = value($this->headers, $payload) ?: []; + $headers = $this->headers($payload); if (! empty($this->config['app_engine'])) { $path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH); @@ -270,8 +285,16 @@ public function getHandler(mixed $job): string return $handler.'/'.config('cloud-tasks.uri'); } - public function setTaskHeaders(Closure|array $headers): void + /** + * @param array $payload + * @return array + */ + private function headers(mixed $payload): array { - $this->headers = $headers; + if (!static::$taskHeadersCallback) { + return []; + } + + return (static::$taskHeadersCallback)($payload); } } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 82c35c0..a296032 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -14,6 +14,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Queue; +use Override; use PHPUnit\Framework\Attributes\Test; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; @@ -28,6 +29,15 @@ class QueueTest extends TestCase { + #[Override] + protected function tearDown(): void + { + parent::tearDown(); + + CloudTasksQueue::forgetHandlerUrlCallback(); + CloudTasksQueue::forgetTaskHeadersCallback(); + } + #[Test] public function a_http_request_with_the_handler_url_is_made() { @@ -480,7 +490,7 @@ public function headers_can_be_added_to_the_task() CloudTasksApi::fake(); // Act - Queue::connection()->setTaskHeaders([ + CloudTasksQueue::setTaskHeadersUsing(static fn() => [ 'X-MyHeader' => 'MyValue', ]); @@ -499,11 +509,9 @@ public function headers_can_be_added_to_the_task_with_job_context() CloudTasksApi::fake(); // Act - Queue::connection()->setTaskHeaders(function (array $payload) { - return [ - 'X-MyHeader' => $payload['displayName'], - ]; - }); + CloudTasksQueue::setTaskHeadersUsing(static fn(array $payload) => [ + 'X-MyHeader' => $payload['displayName'], + ]); $this->dispatch((new SimpleJob())); From a6189b49f9137e88b29bb4f2e0bbcf9ac617d8aa Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sat, 30 Mar 2024 19:08:58 +0100 Subject: [PATCH 40/46] Refactor and cleanups --- README.md | 4 - assets/dashboard.png | Bin 896048 -> 0 bytes config/cloud-tasks.php | 5 - ..._02_14_211616_create_cloud_tasks_table.php | 43 ----- src/CloudTasksJob.php | 12 +- src/CloudTasksQueue.php | 27 +-- src/CloudTasksServiceProvider.php | 14 -- src/Events/TaskIncoming.php | 15 ++ src/IncomingTask.php | 33 +++- src/TaskHandler.php | 3 + tests/IncomingTaskTest.php | 136 +++++++++++++ tests/QueueTest.php | 42 +--- tests/Support/DispatchedJob.php | 63 ++++++ tests/TaskHandlerTest.php | 9 +- tests/TestCase.php | 179 ++---------------- 15 files changed, 279 insertions(+), 306 deletions(-) delete mode 100644 assets/dashboard.png delete mode 100644 migrations/2024_02_14_211616_create_cloud_tasks_table.php create mode 100644 src/Events/TaskIncoming.php create mode 100644 tests/IncomingTaskTest.php create mode 100644 tests/Support/DispatchedJob.php diff --git a/README.md b/README.md index 749b314..633408b 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,6 @@ Add a new queue connection to `config/queue.php` 'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''), 'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''), - // Optional: The deadline in seconds for requests sent to the worker. If the worker - // 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, ], ``` diff --git a/assets/dashboard.png b/assets/dashboard.png deleted file mode 100644 index 0051f177e1ac7d5f24d7c43195658f5510ed3d7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 896048 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%0AdEH?qsca2fk|2!7|XftjE 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

Ocb!~5>LujGz_-p3NGe>l=`F8Y- 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

yxT)7 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 ?+JDIkm?`Cn(84V+mFkc~Z&3|5UB_EcCxH0$) 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%0AuTNR;z7Ao6Ekj$@1mM+XWr&MrG0y3 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¼j^MzEC7BpW-qqO5RdBPS_ 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 diff --git a/config/cloud-tasks.php b/config/cloud-tasks.php index be93015..b9f2dc7 100644 --- a/config/cloud-tasks.php +++ b/config/cloud-tasks.php @@ -8,9 +8,4 @@ // If the application only dispatches jobs 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), - - 'dashboard' => [ - 'enabled' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED', false), - 'password' => env('STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD', 'MyPassword1!'), - ], ]; diff --git a/migrations/2024_02_14_211616_create_cloud_tasks_table.php b/migrations/2024_02_14_211616_create_cloud_tasks_table.php deleted file mode 100644 index 8b44394..0000000 --- a/migrations/2024_02_14_211616_create_cloud_tasks_table.php +++ /dev/null @@ -1,43 +0,0 @@ -increments('id'); - $table->string('queue'); - $table->string('task_name'); - $table->string('name'); - $table->string('status'); - $table->timestamps(); - - $table->index('task_name'); - $table->index('queue'); - $table->index('status'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('cloud_tasks'); - } -} diff --git a/src/CloudTasksJob.php b/src/CloudTasksJob.php index 882286c..399a7c4 100644 --- a/src/CloudTasksJob.php +++ b/src/CloudTasksJob.php @@ -62,11 +62,6 @@ public function setAttempts(int $attempts): void $this->job['internal']['attempts'] = $attempts; } - public function getTaskName(): string - { - return $this->job['internal']['taskName']; - } - public function delete(): void { // Laravel automatically calls delete() after a job is processed successfully. @@ -74,11 +69,6 @@ public function delete(): void // will also delete the task upon a 200 OK status, which means a task is deleted twice. } - public function hasError(): bool - { - return data_get($this->job, 'internal.errored') === true; - } - public function release($delay = 0): void { parent::release($delay); @@ -86,7 +76,7 @@ public function release($delay = 0): void $this->driver->release($this, $delay); if (! data_get($this->job, 'internal.errored')) { - app('events')->dispatch(new JobReleased($this->getConnectionName(), $this, $delay)); + event(new JobReleased($this->getConnectionName(), $this, $delay)); } } } diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 8173f20..1186815 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -12,7 +12,6 @@ use Google\Cloud\Tasks\V2\HttpRequest; use Google\Cloud\Tasks\V2\OidcToken; use Google\Cloud\Tasks\V2\Task; -use Google\Protobuf\Duration; use Google\Protobuf\Timestamp; use Illuminate\Contracts\Queue\Queue as QueueContract; use Illuminate\Queue\Queue as LaravelQueue; @@ -138,22 +137,10 @@ protected function pushToCloudTasks($queue, $payload, $delay, mixed $job) $task = tap(new Task())->setName($this->taskName($queue, $payload['displayName'])); - $payload = $this->enrichPayloadWithInternalData( - payload: $payload, - queueName: $queue, - taskName: $task->getName(), - connectionName: $this->getConnectionName(), - ); + $payload = $this->enrichPayloadWithAttempts($payload); $this->addPayloadToTask($payload, $task, $job); - // The deadline for requests sent to the app. If the app does not respond by - // this deadline then the request is cancelled and the attempt is marked as - // a failure. Cloud Tasks will retry the task according to the RetryConfig. - if (! empty($this->config['dispatch_deadline'])) { - $task->setDispatchDeadline(new Duration(['seconds' => $this->config['dispatch_deadline']])); - } - $availableAt = $this->availableAt($delay); if ($availableAt > time()) { $task->setScheduleTime(new Timestamp(['seconds' => $availableAt])); @@ -175,22 +162,18 @@ private function taskName(string $queueName, string $displayName): string $queueName, str($displayName) ->afterLast('\\') + ->replaceMatches('![^-\pL\pN\s]+!u', '-') + ->replaceMatches('![-\s]+!u', '-') ->prepend((string) Str::ulid(), '-') ->toString(), ); } - private function enrichPayloadWithInternalData( + private function enrichPayloadWithAttempts( array $payload, - string $queueName, - string $taskName, - string $connectionName, ): array { $payload['internal'] = [ 'attempts' => $payload['internal']['attempts'] ?? 0, - 'queue' => $queueName, - 'taskName' => $taskName, - 'connection' => $connectionName, ]; return $payload; @@ -241,7 +224,7 @@ public function pop($queue = null) public function delete(CloudTasksJob $job): void { - CloudTasksApi::deleteTask($job->getTaskName()); + // Job deletion will be handled by Cloud Tasks. } public function release(CloudTasksJob $job, int $delay = 0): void diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index f6fdfad..ca54054 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -95,20 +95,6 @@ private function registerEvents(): void ); }); - $events->listen(JobProcessing::class, function (JobProcessing $event) { - if (! $event->job instanceof CloudTasksJob) { - return; - } - }); - - $events->listen(JobProcessed::class, function (JobProcessed $event) { - if (! $event->job instanceof CloudTasksJob) { - return; - } - - data_set($event->job->job, 'internal.processed', true); - }); - $events->listen(JobExceptionOccurred::class, function (JobExceptionOccurred $event) { if (! $event->job instanceof CloudTasksJob) { return; diff --git a/src/Events/TaskIncoming.php b/src/Events/TaskIncoming.php new file mode 100644 index 0000000..f25fc32 --- /dev/null +++ b/src/Events/TaskIncoming.php @@ -0,0 +1,15 @@ +task['internal']['connection']; + if ($connection = data_get($this->command(), 'connection')) { + return $connection; + } + + return config('queue.default'); } public function queue(): string { - return $this->task['internal']['queue']; + if ($queue = data_get($this->command(), 'queue')) { + return $queue; + } + + return config('queue.connections.'.$this->connection().'.queue'); } public function taskName(): string { - return $this->task['internal']['taskName']; + return request()->header('X-CloudTasks-TaskName') + ?? request()->header('X-AppEngine-TaskName') + ?? throw new Error('Unable to extract taskname from header'); + } + + public function command(): array + { + $command = $this->task['data']['command']; + + if (str_starts_with($command, 'O:')) { + return (array) unserialize($command, ['allowed_classes' => false]); + } + + if (app()->bound(Encrypter::class)) { + return (array) unserialize(app(Encrypter::class)->decrypt($command)); + } + + return []; } public function toArray(): array diff --git a/src/TaskHandler.php b/src/TaskHandler.php index c7c7de8..68391e6 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -7,6 +7,7 @@ use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Container\Container; use Illuminate\Queue\WorkerOptions; +use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskIncoming; class TaskHandler { @@ -21,6 +22,8 @@ public function handle(?string $task = null): void { $task = IncomingTask::fromJson($task ?: request()->getContent()); + event(new TaskIncoming($task)); + if ($task->isInvalid()) { abort(422, 'Invalid task payload'); } diff --git a/tests/IncomingTaskTest.php b/tests/IncomingTaskTest.php new file mode 100644 index 0000000..c5002e9 --- /dev/null +++ b/tests/IncomingTaskTest.php @@ -0,0 +1,136 @@ +withTaskType($taskType); + Str::createUlidsUsingSequence(['01HSR4V9QE2F4T0K8RBAYQ88KE']); + + // Act + $this->dispatch(new $job)->run(); + + // Assert + Event::assertDispatched(function (TaskIncoming $event) use ($job) { + return $event->task->taskName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/01HSR4V9QE2F4T0K8RBAYQ88KE-'.class_basename($job) + && $event->task->connection() === 'my-cloudtasks-connection' + && $event->task->queue() === 'barbequeue'; + }); + } + + #[Test] + #[TestWith([SimpleJob::class, 'cloudtasks'])] + #[TestWith([SimpleJob::class, 'appengine'])] + #[TestWith([EncryptedJob::class, 'cloudtasks'])] + #[TestWith([EncryptedJob::class, 'appengine'])] + public function it_reads_the_custom_queue(string $job, string $taskType) + { + // Arrange + $this->withTaskType($taskType); + + // Act + $this->dispatch((new $job)->onQueue('other-queue'))->run(); + + // Assert + Event::assertDispatched(function (TaskIncoming $event) { + return $event->task->queue() === 'other-queue'; + }); + } + + #[Test] + #[TestWith([SimpleJob::class, 'cloudtasks'])] + #[TestWith([SimpleJob::class, 'appengine'])] + #[TestWith([EncryptedJob::class, 'cloudtasks'])] + #[TestWith([EncryptedJob::class, 'appengine'])] + public function it_reads_the_custom_connection(string $job, string $taskType) + { + // Arrange + $this->withTaskType($taskType); + + // Act + $this->dispatch((new $job)->onConnection('my-other-cloudtasks-connection'))->run(); + + // Assert + Event::assertDispatched(function (TaskIncoming $event) { + return $event->task->connection() === 'my-other-cloudtasks-connection' + && $event->task->queue() === 'other-barbequeue'; + }); + } + + #[Test] + #[TestWith([SimpleJob::class, 'cloudtasks'])] + #[TestWith([SimpleJob::class, 'appengine'])] + #[TestWith([EncryptedJob::class, 'cloudtasks'])] + #[TestWith([EncryptedJob::class, 'appengine'])] + public function it_reads_the_custom_connection_with_custom_queue(string $job, string $taskType) + { + // Arrange + $this->withTaskType($taskType); + + // Act + $this->dispatch( + (new $job) + ->onConnection('my-other-cloudtasks-connection') + ->onQueue('custom-barbequeue') + )->run(); + + // Assert + Event::assertDispatched(function (TaskIncoming $event) { + return $event->task->connection() === 'my-other-cloudtasks-connection' + && $event->task->queue() === 'custom-barbequeue'; + }); + } + + #[Test] + public function it_can_convert_the_incoming_task_to_array() + { + // Act + $incomingTask = IncomingTask::fromJson('{"internal":{"connection":"my-other-cloudtasks-connection","queue":"custom-barbequeue","taskName":"projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/01HSR4V9QE2F4T0K8RBAYQ88KE-SimpleJob"}}'); + + // Act + $array = $incomingTask->toArray(); + + // Assert + $this->assertIsArray($array); + $this->assertSame('my-other-cloudtasks-connection', $array['internal']['connection']); + } + + #[Test] + public function test_invalid_function() + { + // Act + $incomingTask = IncomingTask::fromJson('{ invalid json }'); + + // Act + $this->assertTrue($incomingTask->isInvalid()); + } +} diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 488a6dd..ab33f33 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -20,6 +20,7 @@ use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi; use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; +use Stackkit\LaravelGoogleCloudTasksQueue\IncomingTask; use Tests\Support\FailingJob; use Tests\Support\FailingJobWithExponentialBackoff; use Tests\Support\JobOutput; @@ -139,23 +140,6 @@ public function it_will_set_the_scheduled_time_when_dispatching_later() }); } - #[Test] - public function test_dispatch_deadline_config() - { - // Arrange - CloudTasksApi::fake(); - $this->setConfigValue('dispatch_deadline', 30); - - // Act - $this->dispatch(new SimpleJob()); - - // Assert - CloudTasksApi::assertTaskCreated(function (Task $task) { - return $task->hasDispatchDeadline() - && $task->getDispatchDeadline()->getSeconds() === 30; - }); - } - #[Test] public function it_posts_the_task_the_correct_queue() { @@ -169,7 +153,7 @@ public function it_posts_the_task_the_correct_queue() // Assert CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool { $decoded = json_decode($task->getHttpRequest()->getBody(), true); - $command = $this->getCommandProperties($decoded['data']['command']); + $command = IncomingTask::fromJson($task->getHttpRequest()->getBody())->command(); return $decoded['displayName'] === SimpleJob::class && ($command['queue'] ?? null) === null @@ -178,7 +162,7 @@ public function it_posts_the_task_the_correct_queue() CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool { $decoded = json_decode($task->getHttpRequest()->getBody(), true); - $command = $this->getCommandProperties($decoded['data']['command']); + $command = IncomingTask::fromJson($task->getHttpRequest()->getBody())->command(); return $decoded['displayName'] === FailingJob::class && $command['queue'] === 'my-special-queue' @@ -238,17 +222,12 @@ public function jobs_can_be_released() ]); // Act - $this->dispatch(new JobThatWillBeReleased())->run(); + $this->dispatch(new JobThatWillBeReleased()) + ->runAndGetReleasedJob() + ->run(); - // Assert - Event::assertNotDispatched(JobReleasedAfterException::class); - CloudTasksApi::assertDeletedTaskCount(0); // it returned 200 OK so we dont delete it, but Google does - $releasedJob = null; - Event::assertDispatched(JobReleased::class, function (JobReleased $event) use (&$releasedJob) { - $releasedJob = $event->job; - return true; - }); + // Assert CloudTasksApi::assertTaskCreated(function (Task $task) { $body = $task->getHttpRequest()->getBody(); $decoded = json_decode($body, true); @@ -257,9 +236,6 @@ public function jobs_can_be_released() && $decoded['internal']['attempts'] === 1; }); - $this->runFromPayload($releasedJob->getRawBody()); - - CloudTasksApi::assertDeletedTaskCount(0); CloudTasksApi::assertTaskCreated(function (Task $task) { $body = $task->getHttpRequest()->getBody(); $decoded = json_decode($body, true); @@ -455,11 +431,11 @@ public function test_ignoring_jobs_with_deleted_models() ]); // Act - $this->dispatch(new UserJob($user1))->runWithoutExceptionHandler(); + $this->dispatch(new UserJob($user1))->run(); $job = $this->dispatch(new UserJob($user2)); $user2->delete(); - $job->runWithoutExceptionHandler(); + $job->run(); // Act Event::assertDispatched(fn (JobOutput $event) => $event->output === 'UserJob:John'); diff --git a/tests/Support/DispatchedJob.php b/tests/Support/DispatchedJob.php new file mode 100644 index 0000000..a6fcf7e --- /dev/null +++ b/tests/Support/DispatchedJob.php @@ -0,0 +1,63 @@ +payload = $payload; + $this->task = $task; + $this->testCase = $testCase; + } + + public function run(): void + { + $header = match (true) { + $this->task->hasHttpRequest() => 'HTTP_X_CLOUDTASKS_TASKNAME', + $this->task->hasAppEngineHttpRequest() => 'HTTP_X_APPENGINE_TASKNAME', + default => throw new Error('Task does not have a request.'), + }; + + $this->testCase->call( + method: 'POST', + uri: route('cloud-tasks.handle-task'), + server: [ + $header => $this->task->getName(), + ], + content: $this->payload, + ); + } + + public function runAndGetReleasedJob(): self + { + $this->run(); + + $releasedTask = end($this->testCase->createdTasks); + + if (! $releasedTask) { + $this->testCase->fail('No task was released.'); + } + + $payload = $releasedTask->getAppEngineHttpRequest()?->getBody() + ?: $releasedTask->getHttpRequest()->getBody(); + + return new self( + $payload, + $releasedTask, + $this->testCase + ); + } +} diff --git a/tests/TaskHandlerTest.php b/tests/TaskHandlerTest.php index 8faa037..1c2359c 100644 --- a/tests/TaskHandlerTest.php +++ b/tests/TaskHandlerTest.php @@ -35,7 +35,7 @@ public function it_can_run_a_task() Event::fake(JobOutput::class); // Act - $this->dispatch(new SimpleJob())->runWithoutExceptionHandler(); + $this->dispatch(new SimpleJob())->run(); // Assert Event::assertDispatched(fn (JobOutput $event) => $event->output === 'SimpleJob:success'); @@ -52,7 +52,7 @@ public function it_can_run_a_task_using_the_task_connection() // Act $job = new SimpleJob(); $job->connection = 'my-cloudtasks-connection'; - $this->dispatch($job)->runWithoutExceptionHandler(); + $this->dispatch($job)->run(); // Assert Event::assertDispatched(fn (JobOutput $event) => $event->output === 'SimpleJob:success'); @@ -179,11 +179,6 @@ public function it_can_handle_encrypted_jobs() $job->run(); // Assert - $this->assertStringContainsString( - 'O:26:"Tests\Support\EncryptedJob"', - decrypt($job->payloadAsArray('data.command')), - ); - Event::assertDispatched(fn (JobOutput $event) => $event->output === 'EncryptedJob:success'); } diff --git a/tests/TestCase.php b/tests/TestCase.php index b8fddd8..026b3c3 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,28 +4,18 @@ namespace Tests; -use Google\ApiCore\ApiException; use Google\Cloud\Tasks\V2\Client\CloudTasksClient; -use Google\Cloud\Tasks\V2\Task; -use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Queue\Events\JobReleasedAfterException; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; -use Illuminate\Support\Str; +use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksServiceProvider; use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated; -use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler; +use Tests\Support\DispatchedJob; class TestCase extends \Orchestra\Testbench\TestCase { use DatabaseTransactions; - /** - * @var CloudTasksClient - */ - public $client; - - public string $releasedJobPayload; + public CloudTasksClient $client; public array $createdTasks = []; @@ -33,59 +23,27 @@ protected function setUp(): void { parent::setUp(); - $this->withFactories(__DIR__.'/../factories'); - Event::listen(TaskCreated::class, function (TaskCreated $event) { $this->createdTasks[] = $event->task; }); - - Event::listen( - JobReleasedAfterException::class, - function ($event) { - $this->releasedJobPayload = $event->job->getRawBody(); - } - ); } - /** - * Get package providers. At a minimum this is the package being tested, but also - * would include packages upon which our package depends, e.g. Cartalyst/Sentry - * In a normal app environment these would be added to the 'providers' array in - * the config/app.php file. - * - * @param \Illuminate\Foundation\Application $app - * @return array - */ protected function getPackageProviders($app) { return [ - \Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksServiceProvider::class, + CloudTasksServiceProvider::class, ]; } - /** - * Define database migrations. - * - * @return void - */ protected function defineDatabaseMigrations() { - $this->loadMigrationsFrom(__DIR__.'/../migrations'); + // Necessary to test the [failed_jobs] table. + $this->loadMigrationsFrom(__DIR__.'/../vendor/orchestra/testbench-core/laravel/migrations'); } - /** - * Define environment setup. - * - * @param \Illuminate\Foundation\Application $app - * @return void - */ protected function getEnvironmentSetUp($app) { - foreach (glob(storage_path('framework/cache/data/*/*/*')) as $file) { - unlink($file); - } - $app['config']->set('database.default', 'testbench'); $port = env('DB_DRIVER') === 'mysql' ? 3307 : 5432; $app['config']->set('database.connections.testbench', [ @@ -108,17 +66,15 @@ protected function getEnvironmentSetUp($app) 'handler' => env('CLOUD_TASKS_HANDLER', 'https://docker.for.mac.localhost:8080'), 'service_account_email' => 'info@stackkit.io', ]); - $app['config']->set('queue.failed.driver', 'database-uuids'); - $app['config']->set('queue.failed.database', 'testbench'); - $disableDashboardPrefix = 'when_dashboard_is_disabled'; + $app['config']->set('queue.connections.my-other-cloudtasks-connection', [ + ...config('queue.connections.my-cloudtasks-connection'), + 'queue' => 'other-barbequeue', + 'project' => 'other-my-test-project', + ]); - $testName = method_exists($this, 'name') ? $this->name() : $this->getName(); - if (substr($testName, 0, strlen($disableDashboardPrefix)) === $disableDashboardPrefix) { - $app['config']->set('cloud-tasks.dashboard.enabled', false); - } else { - $app['config']->set('cloud-tasks.dashboard.enabled', true); - } + $app['config']->set('queue.failed.driver', 'database-uuids'); + $app['config']->set('queue.failed.database', 'testbench'); } protected function setConfigValue($key, $value) @@ -126,7 +82,7 @@ protected function setConfigValue($key, $value) $this->app['config']->set('queue.connections.my-cloudtasks-connection.'.$key, $value); } - public function dispatch($job) + public function dispatch($job): DispatchedJob { $payload = null; $task = null; @@ -139,96 +95,7 @@ public function dispatch($job) dispatch($job); - return new class($payload, $task, $this) - { - public string $payload; - - public Task $task; - - public TestCase $testCase; - - public function __construct(string $payload, Task $task, TestCase $testCase) - { - $this->payload = $payload; - $this->task = $task; - $this->testCase = $testCase; - } - - public function run(): void - { - rescue(function (): void { - app(TaskHandler::class)->handle($this->payload); - }); - } - - public function runWithoutExceptionHandler(): void - { - app(TaskHandler::class)->handle($this->payload); - } - - public function runAndGetReleasedJob(): self - { - rescue(function (): void { - app(TaskHandler::class)->handle($this->payload); - }); - - $releasedTask = end($this->testCase->createdTasks); - - if (! $releasedTask) { - $this->testCase->fail('No task was released.'); - } - - $payload = $releasedTask->getAppEngineHttpRequest()?->getBody() - ?: $releasedTask->getHttpRequest()->getBody(); - - return new self( - $payload, - $releasedTask, - $this->testCase - ); - } - - public function payloadAsArray(string $key = '') - { - $decoded = json_decode($this->payload, true); - - return data_get($decoded, $key ?: null); - } - }; - } - - public function runFromPayload(string $payload): void - { - rescue(function () use ($payload) { - app(TaskHandler::class)->handle($payload); - }); - } - - public function assertTaskDeleted(string $taskId): void - { - try { - $this->client->getTask($taskId); - - $this->fail('Getting the task should throw an exception but it did not.'); - } catch (ApiException $e) { - $this->assertStringContainsString('The task no longer exists', $e->getMessage()); - } - } - - public function assertTaskExists(string $taskId): void - { - try { - $task = $this->client->getTask($taskId); - - $this->assertInstanceOf(Task::class, $task); - } catch (ApiException $e) { - $this->fail('Task ['.$taskId.'] should exist but it does not (or something else went wrong).'); - } - } - - protected function assertDatabaseCount($table, int $count, $connection = null) - { - $this->assertEquals($count, DB::connection($connection)->table($table)->count()); + return new DispatchedJob($payload, $task, $this); } public function withTaskType(string $taskType): void @@ -250,20 +117,4 @@ public function withTaskType(string $taskType): void break; } } - - public static function getCommandProperties(string $command): array - { - if (Str::startsWith($command, 'O:')) { - return (array) unserialize($command, ['allowed_classes' => false]); - } - - if (app()->bound(Encrypter::class)) { - return (array) unserialize( - app(Encrypter::class)->decrypt($command), - ['allowed_classes' => ['Illuminate\Support\Carbon']] - ); - } - - return []; - } } From 7ff33684a077e0272efaaa2ce6298af4330cd965 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 31 Mar 2024 18:06:37 +0200 Subject: [PATCH 41/46] Update README.md --- README.md | 93 +++++++------------------------------------------------ 1 file changed, 11 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 633408b..dab5c51 100644 --- a/README.md +++ b/README.md @@ -15,20 +15,11 @@ This package allows Google Cloud Tasks to be used as the queue driver.

-
- -Requirements - +### Requirements -
-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. +This package requires Laravel 10 or 11. -Please check the [Laravel support policy](https://laravel.com/docs/master/releases#support-policy) table for supported -Laravel and PHP versions. -
-
-Installation -
+### Installation Require the package using Composer @@ -63,15 +54,14 @@ Add a new queue connection to `config/queue.php` ], ``` -If you are using separate services for dispatching and handling tasks, you may want to change the following settings: +If you are using separate services for dispatching and handling tasks, and your application only dispatches jobs and should not be able to handle jobs, you may disable the task handler from `config/cloud-tasks.php`: ```php -// config/cloud-tasks.php - -// If the application only dispatches jobs 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), ``` +Finally, change the `QUEUE_CONNECTION` to the newly defined connection. + ```dotenv QUEUE_CONNECTION=cloudtasks ``` @@ -136,11 +126,8 @@ use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksQueue; CloudTasksQueue::configureHandlerUrlUsing(static fn(MyJob $job) => 'https://example.com/my-url/' . $job->something()); ``` -
- -How it works & Differences - -
+### How it works and differences + 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. @@ -149,53 +136,9 @@ your application with the job payload. There is no need to run a `queue:work/lis #### Good to know -- Backoff, retries, max tries, retryUntil are all handled by Laravel. All these options are ignored in the Cloud Tasks - configuration. - -
-
-Dashboard (beta) -
-The package comes with a beautiful dashboard that can be used to monitor all queued jobs. - - - +Cloud Tasks has it's own retry configuration options: maximum number of attempts, retry duration, min/max backoff and max doublings. All of these options are ignored by this package. Instead, you may configure max attempts, retry duration and backoff strategy right from Laravel. ---- - -_Experimental_ - -The dashboard works by storing all outgoing tasks in a database table. When Cloud Tasks calls the application and this -package handles the task, we will automatically update the tasks' status, attempts -and possible errors. - -There is probably a (small) performance penalty because each task dispatch and handling does extra database read and -writes. -Also, the dashboard has not been tested with high throughput queues. - ---- - - -To make use of it, enable it through the `.env` file: - -```dotenv -STACKKIT_CLOUD_TASKS_DASHBOARD_ENABLED=true -STACKKIT_CLOUD_TASKS_DASHBOARD_PASSWORD=MySecretLoginPasswordPleaseChangeThis -``` - -Then publish its assets and migrations: - -```console -php artisan vendor:publish --tag=cloud-tasks -php artisan migrate -``` - -The dashboard is accessible at the URI: /cloud-tasks - -
-
-Authentication -
+### Authentication Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable with a path to the credentials file. @@ -210,20 +153,6 @@ works: 4. Cloud Tasks Task Deleter 5. Service Account User -
-
-Security -
-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. - -This package verifies that the token is digitally signed by Google. Only Google Tasks will be able to call your handler. +### Upgrading -More information about OpenID Connect: - -https://developers.google.com/identity/protocols/oauth2/openid-connect -
-
-Upgrading -
Read [UPGRADING.MD](UPGRADING.md) on how to update versions. -
From 680cc37303d1b76c38d94e00c5ad15070cc164ba Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 31 Mar 2024 18:25:03 +0200 Subject: [PATCH 42/46] Shorten environment names --- README.md | 30 +++++++++++++++--------------- config/cloud-tasks.php | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index dab5c51..9eda4f3 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,17 @@ Add a new queue connection to `config/queue.php` ```php 'cloudtasks' => [ 'driver' => 'cloudtasks', - 'project' => env('STACKKIT_CLOUD_TASKS_PROJECT', ''), - 'location' => env('STACKKIT_CLOUD_TASKS_LOCATION', ''), - 'queue' => env('STACKKIT_CLOUD_TASKS_QUEUE', 'default'), + 'project' => env('CLOUD_TASKS_PROJECT', ''), + 'location' => env('CLOUD_TASKS_LOCATION', ''), + 'queue' => env('CLOUD_TASKS_QUEUE', 'default'), // Required when using AppEngine - 'app_engine' => env('STACKKIT_APP_ENGINE_TASK', false), - 'app_engine_service' => env('STACKKIT_APP_ENGINE_SERVICE', ''), + 'app_engine' => env('APP_ENGINE_TASK', false), + 'app_engine_service' => env('APP_ENGINE_SERVICE', ''), // Required when not using AppEngine - 'handler' => env('STACKKIT_CLOUD_TASKS_HANDLER', ''), - 'service_account_email' => env('STACKKIT_CLOUD_TASKS_SERVICE_EMAIL', ''), + 'handler' => env('CLOUD_TASKS_HANDLER', ''), + 'service_account_email' => env('CLOUD_TASKS_SERVICE_EMAIL', ''), 'backoff' => 0, ], @@ -57,7 +57,7 @@ Add a new queue connection to `config/queue.php` If you are using separate services for dispatching and handling tasks, and your application only dispatches jobs and should not be able to handle jobs, you may disable the task handler from `config/cloud-tasks.php`: ```php -'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), +'disable_task_handler' => env('CLOUD_TASKS_DISABLE_TASK_HANDLER', false), ``` Finally, change the `QUEUE_CONNECTION` to the newly defined connection. @@ -72,15 +72,15 @@ Please check the table below on what the values mean and what their value should | Environment variable | Description | Example ---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------- -| `STACKKIT_CLOUD_TASKS_PROJECT` | The project your queue belongs to. | `my-project` -| `STACKKIT_CLOUD_TASKS_LOCATION` | The region where the project is hosted. | `europe-west6` -| `STACKKIT_CLOUD_TASKS_QUEUE` | The default queue a job will be added to. | `emails` +| `CLOUD_TASKS_PROJECT` | The project your queue belongs to. | `my-project` +| `CLOUD_TASKS_LOCATION` | The region where the project is hosted. | `europe-west6` +| `CLOUD_TASKS_QUEUE` | The default queue a job will be added to. | `emails` | **App Engine** -| `STACKKIT_APP_ENGINE_TASK` (optional) | Set to true to use App Engine task (else a Http task will be used). Defaults to false. | `true` -| `STACKKIT_APP_ENGINE_SERVICE` (optional) | The App Engine service to handle the task (only if using App Engine task). | `api` +| `APP_ENGINE_TASK` (optional) | Set to true to use App Engine task (else a Http task will be used). Defaults to false. | `true` +| `APP_ENGINE_SERVICE` (optional) | The App Engine service to handle the task (only if using App Engine task). | `api` | **Non- App Engine apps** -| `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. | `my-service-account@appspot.gserviceaccount.com` -| `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://.com` +| `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. | `my-service-account@appspot.gserviceaccount.com` +| `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://.com`
diff --git a/config/cloud-tasks.php b/config/cloud-tasks.php index b9f2dc7..4a77375 100644 --- a/config/cloud-tasks.php +++ b/config/cloud-tasks.php @@ -4,8 +4,8 @@ return [ // The URI of the endpoint that will handle the task - 'uri' => env('STACKKIT_CLOUD_TASKS_URI', 'handle-task'), + 'uri' => env('CLOUD_TASKS_URI', 'handle-task'), // If the application only dispatches jobs - 'disable_task_handler' => env('STACKKIT_CLOUD_TASKS_DISABLE_TASK_HANDLER', false), + 'disable_task_handler' => env('CLOUD_TASKS_DISABLE_TASK_HANDLER', false), ]; From adb22a3b1ff75a47bf7bc85355dadc8d9d647122 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 31 Mar 2024 18:25:10 +0200 Subject: [PATCH 43/46] Update UPGRADING.md --- UPGRADING.md | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index ff8fed8..f68380c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,10 +1,40 @@ # From 3.x to 4.x -## New task internal metadata (Impact: high) +## Renamed environment names (Impact: high) + +The following environment variables have been shortened: +- `STACKKIT_CLOUD_TASKS_PROJECT` → `CLOUD_TASKS_PROJECT` +- `STACKKIT_CLOUD_TASKS_LOCATION` → `CLOUD_TASKS_LOCATION` +- `STACKKIT_CLOUD_TASKS_QUEUE` → `CLOUD_TASKS_QUEUE` +- `STACKKIT_CLOUD_TASKS_HANDLER` → `CLOUD_TASKS_HANDLER` +- `STACKKIT_CLOUD_TASKS_SERVICE_EMAIL` → `CLOUD_TASKS_SERVICE_EMAIL` + +The following environment variables have been renamed to be more consistent: + +- `STACKKIT_APP_ENGINE_TASK` → `CLOUD_TASKS_APP_ENGINE_TASK` +- `STACKKIT_APP_ENGINE_SERVICE` → `CLOUD_TASKS_APP_ENGINE_SERVICE` + +The following environment variable has been removed: +- `STACKKIT_CLOUD_TASKS_SIGNED_AUDIENCE` + +## Removed dashboard (Impact: high) + +The dashboard has been removed to keep the package minimal. A separate composer package might be created with an updated version of the dashboard. + +## New configuration file (Impact: medium) + +The configuration file has been updated to reflect the removed dashboard and to add new configurable options. + +Please publish the new configuration file: + +```shell +php artisan vendor:publish --tag=cloud-tasks --force +``` + +## Dispatch deadline (Impact: medium) + +The `dispatch_deadline` has been removed from the task configuration. You may now use Laravel's timeout configuration to control the maximum execution time of a task. -The task internal metadata has been enriched with `queue`, `taskName`, `connection` and `securityKey`. -Existing tasks in the queue cannot be processed because they are missing these fields. -Please ensure that all tasks in the queue are processed before upgrading to 4.x. # From 2.x to 3.x From a84a2b5467a86968ae387163660112278736a704 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 31 Mar 2024 18:25:32 +0200 Subject: [PATCH 44/46] Pint --- src/CloudTasksQueue.php | 11 ++++++----- src/CloudTasksServiceProvider.php | 2 -- tests/QueueTest.php | 7 +++---- tests/Support/SimpleJob.php | 1 + 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/CloudTasksQueue.php b/src/CloudTasksQueue.php index 1186815..15738eb 100644 --- a/src/CloudTasksQueue.php +++ b/src/CloudTasksQueue.php @@ -24,13 +24,14 @@ class CloudTasksQueue extends LaravelQueue implements QueueContract { private static ?Closure $handlerUrlCallback = null; + private static ?Closure $taskHeadersCallback = null; public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false) { // } - + public static function configureHandlerUrlUsing(Closure $callback): void { static::$handlerUrlCallback = $callback; @@ -126,7 +127,7 @@ function ($payload, $queue, $delay) use ($job) { * @param string|null $queue * @param string $payload * @param \DateTimeInterface|\DateInterval|int $delay - * @param string|object $job + * @param string|object $job * @return string */ protected function pushToCloudTasks($queue, $payload, $delay, mixed $job) @@ -257,12 +258,12 @@ public function getHandler(mixed $job): string } /** - * @param array $payload - * @return array + * @param array $payload + * @return array */ private function headers(mixed $payload): array { - if (!static::$taskHeadersCallback) { + if (! static::$taskHeadersCallback) { return []; } diff --git a/src/CloudTasksServiceProvider.php b/src/CloudTasksServiceProvider.php index ca54054..d6fbe1e 100644 --- a/src/CloudTasksServiceProvider.php +++ b/src/CloudTasksServiceProvider.php @@ -9,8 +9,6 @@ use Illuminate\Foundation\Application; use Illuminate\Queue\Events\JobExceptionOccurred; use Illuminate\Queue\Events\JobFailed; -use Illuminate\Queue\Events\JobProcessed; -use Illuminate\Queue\Events\JobProcessing; use Illuminate\Support\ServiceProvider as LaravelServiceProvider; use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased; diff --git a/tests/QueueTest.php b/tests/QueueTest.php index ab33f33..c24c8f3 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -92,7 +92,7 @@ public function it_posts_to_the_callback_handler_url() // Arrange $this->setConfigValue('handler', 'https://docker.for.mac.localhost:8081'); CloudTasksApi::fake(); - CloudTasksQueue::configureHandlerUrlUsing(static fn(SimpleJob $job) => 'https://example.com/api/my-custom-route?job=' . $job->id); + CloudTasksQueue::configureHandlerUrlUsing(static fn (SimpleJob $job) => 'https://example.com/api/my-custom-route?job='.$job->id); // Act $job = new SimpleJob(); @@ -226,7 +226,6 @@ public function jobs_can_be_released() ->runAndGetReleasedJob() ->run(); - // Assert CloudTasksApi::assertTaskCreated(function (Task $task) { $body = $task->getHttpRequest()->getBody(); @@ -465,7 +464,7 @@ public function headers_can_be_added_to_the_task() CloudTasksApi::fake(); // Act - CloudTasksQueue::setTaskHeadersUsing(static fn() => [ + CloudTasksQueue::setTaskHeadersUsing(static fn () => [ 'X-MyHeader' => 'MyValue', ]); @@ -484,7 +483,7 @@ public function headers_can_be_added_to_the_task_with_job_context() CloudTasksApi::fake(); // Act - CloudTasksQueue::setTaskHeadersUsing(static fn(array $payload) => [ + CloudTasksQueue::setTaskHeadersUsing(static fn (array $payload) => [ 'X-MyHeader' => $payload['displayName'], ]); diff --git a/tests/Support/SimpleJob.php b/tests/Support/SimpleJob.php index d443116..4825355 100644 --- a/tests/Support/SimpleJob.php +++ b/tests/Support/SimpleJob.php @@ -15,6 +15,7 @@ class SimpleJob implements ShouldQueue use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $tries = 3; + public $id = 0; /** From 90d88686500fabc8f94a84b0bd696b8400225b7e Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 7 Apr 2024 13:48:43 +0200 Subject: [PATCH 45/46] Fix short task name passed instead of fully qualified --- src/IncomingTask.php | 15 ++++++++++++++- src/TaskHandler.php | 2 +- tests/IncomingTaskTest.php | 2 +- tests/Support/DispatchedJob.php | 3 ++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/IncomingTask.php b/src/IncomingTask.php index f433c45..5d4a664 100644 --- a/src/IncomingTask.php +++ b/src/IncomingTask.php @@ -5,6 +5,7 @@ namespace Stackkit\LaravelGoogleCloudTasksQueue; use Error; +use Google\Cloud\Tasks\V2\Client\CloudTasksClient; use Illuminate\Contracts\Encryption\Encrypter; use Safe\Exceptions\JsonException; @@ -51,13 +52,25 @@ public function queue(): string return config('queue.connections.'.$this->connection().'.queue'); } - public function taskName(): string + public function shortTaskName(): string { return request()->header('X-CloudTasks-TaskName') ?? request()->header('X-AppEngine-TaskName') ?? throw new Error('Unable to extract taskname from header'); } + public function fullyQualifiedTaskName(): string + { + $config = config('queue.connections.'.$this->connection()); + + return CloudTasksClient::taskName( + project: $config['project'], + location: $config['location'], + queue: $this->queue(), + task: $this->shortTaskName(), + ); + } + public function command(): array { $command = $this->task['data']['command']; diff --git a/src/TaskHandler.php b/src/TaskHandler.php index 68391e6..2cab73e 100644 --- a/src/TaskHandler.php +++ b/src/TaskHandler.php @@ -28,7 +28,7 @@ public function handle(?string $task = null): void abort(422, 'Invalid task payload'); } - if (! CloudTasksApi::exists($task->taskName())) { + if (! CloudTasksApi::exists($task->fullyQualifiedTaskName())) { abort(404); } diff --git a/tests/IncomingTaskTest.php b/tests/IncomingTaskTest.php index c5002e9..2a3d595 100644 --- a/tests/IncomingTaskTest.php +++ b/tests/IncomingTaskTest.php @@ -41,7 +41,7 @@ public function it_reads_the_incoming_task(string $job, string $taskType) // Assert Event::assertDispatched(function (TaskIncoming $event) use ($job) { - return $event->task->taskName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/01HSR4V9QE2F4T0K8RBAYQ88KE-'.class_basename($job) + return $event->task->shortTaskName() === '01HSR4V9QE2F4T0K8RBAYQ88KE-'.class_basename($job) && $event->task->connection() === 'my-cloudtasks-connection' && $event->task->queue() === 'barbequeue'; }); diff --git a/tests/Support/DispatchedJob.php b/tests/Support/DispatchedJob.php index a6fcf7e..781ef17 100644 --- a/tests/Support/DispatchedJob.php +++ b/tests/Support/DispatchedJob.php @@ -31,11 +31,12 @@ public function run(): void default => throw new Error('Task does not have a request.'), }; + $this->testCase->call( method: 'POST', uri: route('cloud-tasks.handle-task'), server: [ - $header => $this->task->getName(), + $header => (string) str($this->task->getName())->after('/tasks/'), ], content: $this->payload, ); From 1d65da7a2cfa455c82d1edd8773dcdc38e75b07c Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Sun, 7 Apr 2024 13:50:28 +0200 Subject: [PATCH 46/46] Pint --- tests/IncomingTaskTest.php | 2 +- tests/Support/DispatchedJob.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/IncomingTaskTest.php b/tests/IncomingTaskTest.php index 2a3d595..16b49b8 100644 --- a/tests/IncomingTaskTest.php +++ b/tests/IncomingTaskTest.php @@ -41,7 +41,7 @@ public function it_reads_the_incoming_task(string $job, string $taskType) // Assert Event::assertDispatched(function (TaskIncoming $event) use ($job) { - return $event->task->shortTaskName() === '01HSR4V9QE2F4T0K8RBAYQ88KE-'.class_basename($job) + return $event->task->fullyQualifiedTaskName() === 'projects/my-test-project/locations/europe-west6/queues/barbequeue/tasks/01HSR4V9QE2F4T0K8RBAYQ88KE-'.class_basename($job) && $event->task->connection() === 'my-cloudtasks-connection' && $event->task->queue() === 'barbequeue'; }); diff --git a/tests/Support/DispatchedJob.php b/tests/Support/DispatchedJob.php index 781ef17..2ee248a 100644 --- a/tests/Support/DispatchedJob.php +++ b/tests/Support/DispatchedJob.php @@ -31,7 +31,6 @@ public function run(): void default => throw new Error('Task does not have a request.'), }; - $this->testCase->call( method: 'POST', uri: route('cloud-tasks.handle-task'),

&0uJRB@@Ukr?^A|4 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 z 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�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 )oG`spJ&pO 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