diff --git a/src/Auth/NullAuthenticator.php b/src/Auth/NullAuthenticator.php new file mode 100644 index 0000000..ee304f0 --- /dev/null +++ b/src/Auth/NullAuthenticator.php @@ -0,0 +1,15 @@ +header(config('workflows.webhook_auth.signature.header')) ?? '', + hash_hmac('sha256', $request->getContent(), config('workflows.webhook_auth.signature.secret')) + ); + } +} diff --git a/src/Auth/TokenAuthenticator.php b/src/Auth/TokenAuthenticator.php new file mode 100644 index 0000000..04cf1ec --- /dev/null +++ b/src/Auth/TokenAuthenticator.php @@ -0,0 +1,17 @@ +header(config('workflows.webhook_auth.token.header')) === config( + 'workflows.webhook_auth.token.token' + ); + } +} diff --git a/src/Auth/WebhookAuthenticator.php b/src/Auth/WebhookAuthenticator.php new file mode 100644 index 0000000..b74b153 --- /dev/null +++ b/src/Auth/WebhookAuthenticator.php @@ -0,0 +1,12 @@ +auth(); - - Http::withToken($auth['token']) - ->withHeaders([ - 'apiKey' => $auth['public'], - ]) - ->withOptions([ - 'query' => [ - 'id' => 'eq.' . $event->activityId, - ], - ]) - ->patch(config('workflows.monitor_url') . '/rest/v1/activities', [ - 'output' => $event->output, - 'status' => 'completed', - 'updated_at' => $event->timestamp, - ]); - } -} diff --git a/src/Listeners/MonitorActivityFailed.php b/src/Listeners/MonitorActivityFailed.php deleted file mode 100644 index e1d331c..0000000 --- a/src/Listeners/MonitorActivityFailed.php +++ /dev/null @@ -1,37 +0,0 @@ -auth(); - - Http::withToken($auth['token']) - ->withHeaders([ - 'apiKey' => $auth['public'], - ]) - ->withOptions([ - 'query' => [ - 'id' => 'eq.' . $event->activityId, - ], - ]) - ->patch(config('workflows.monitor_url') . '/rest/v1/activities', [ - 'output' => $event->output, - 'status' => 'failed', - 'updated_at' => $event->timestamp, - ]); - } -} diff --git a/src/Listeners/MonitorActivityStarted.php b/src/Listeners/MonitorActivityStarted.php deleted file mode 100644 index 60314c1..0000000 --- a/src/Listeners/MonitorActivityStarted.php +++ /dev/null @@ -1,37 +0,0 @@ -auth(); - - Http::withToken($auth['token']) - ->withHeaders([ - 'apiKey' => $auth['public'], - ]) - ->post(config('workflows.monitor_url') . '/rest/v1/activities', [ - 'id' => $event->activityId, - 'user_id' => $auth['user'], - 'workflow_id' => $event->workflowId, - 'class' => $event->class, - 'index' => $event->index, - 'arguments' => $event->arguments, - 'status' => 'running', - 'created_at' => $event->timestamp, - ]); - } -} diff --git a/src/Listeners/MonitorWorkflowCompleted.php b/src/Listeners/MonitorWorkflowCompleted.php deleted file mode 100644 index e9e77c8..0000000 --- a/src/Listeners/MonitorWorkflowCompleted.php +++ /dev/null @@ -1,38 +0,0 @@ -auth(); - - Http::withToken($auth['token']) - ->withHeaders([ - 'apiKey' => $auth['public'], - ]) - ->withOptions([ - 'query' => [ - 'user_id' => 'eq.' . $auth['user'], - 'workflow_id' => 'eq.' . $event->workflowId, - ], - ]) - ->patch(config('workflows.monitor_url') . '/rest/v1/workflows', [ - 'output' => $event->output, - 'status' => 'completed', - 'updated_at' => $event->timestamp, - ]); - } -} diff --git a/src/Listeners/MonitorWorkflowFailed.php b/src/Listeners/MonitorWorkflowFailed.php deleted file mode 100644 index 62d6422..0000000 --- a/src/Listeners/MonitorWorkflowFailed.php +++ /dev/null @@ -1,38 +0,0 @@ -auth(); - - Http::withToken($auth['token']) - ->withHeaders([ - 'apiKey' => $auth['public'], - ]) - ->withOptions([ - 'query' => [ - 'user_id' => 'eq.' . $auth['user'], - 'workflow_id' => 'eq.' . $event->workflowId, - ], - ]) - ->patch(config('workflows.monitor_url') . '/rest/v1/workflows', [ - 'output' => $event->output, - 'status' => 'failed', - 'updated_at' => $event->timestamp, - ]); - } -} diff --git a/src/Listeners/MonitorWorkflowStarted.php b/src/Listeners/MonitorWorkflowStarted.php deleted file mode 100644 index 7e6851d..0000000 --- a/src/Listeners/MonitorWorkflowStarted.php +++ /dev/null @@ -1,35 +0,0 @@ -auth(); - - Http::withToken($auth['token']) - ->withHeaders([ - 'apiKey' => $auth['public'], - ]) - ->post(config('workflows.monitor_url') . '/rest/v1/workflows', [ - 'user_id' => $auth['user'], - 'workflow_id' => $event->workflowId, - 'class' => $event->class, - 'arguments' => $event->arguments, - 'status' => 'running', - 'created_at' => $event->timestamp, - ]); - } -} diff --git a/src/Providers/WorkflowServiceProvider.php b/src/Providers/WorkflowServiceProvider.php index ba91d9d..945e1a1 100644 --- a/src/Providers/WorkflowServiceProvider.php +++ b/src/Providers/WorkflowServiceProvider.php @@ -5,23 +5,10 @@ namespace Workflow\Providers; use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; use Laravel\SerializableClosure\SerializableClosure; use Workflow\Commands\ActivityMakeCommand; use Workflow\Commands\WorkflowMakeCommand; -use Workflow\Events\ActivityCompleted; -use Workflow\Events\ActivityFailed; -use Workflow\Events\ActivityStarted; -use Workflow\Events\WorkflowCompleted; -use Workflow\Events\WorkflowFailed; -use Workflow\Events\WorkflowStarted; -use Workflow\Listeners\MonitorActivityCompleted; -use Workflow\Listeners\MonitorActivityFailed; -use Workflow\Listeners\MonitorActivityStarted; -use Workflow\Listeners\MonitorWorkflowCompleted; -use Workflow\Listeners\MonitorWorkflowFailed; -use Workflow\Listeners\MonitorWorkflowStarted; final class WorkflowServiceProvider extends ServiceProvider { @@ -33,15 +20,6 @@ class_alias(config('workflows.base_model', Model::class), 'Workflow\Models\Model SerializableClosure::setSecretKey(config('app.key')); - if (config('workflows.monitor', false)) { - Event::listen(WorkflowStarted::class, [MonitorWorkflowStarted::class, 'handle']); - Event::listen(WorkflowCompleted::class, [MonitorWorkflowCompleted::class, 'handle']); - Event::listen(WorkflowFailed::class, [MonitorWorkflowFailed::class, 'handle']); - Event::listen(ActivityStarted::class, [MonitorActivityStarted::class, 'handle']); - Event::listen(ActivityCompleted::class, [MonitorActivityCompleted::class, 'handle']); - Event::listen(ActivityFailed::class, [MonitorActivityFailed::class, 'handle']); - } - $this->publishes([ __DIR__ . '/../config/workflows.php' => config_path('workflows.php'), ], 'config'); @@ -52,9 +30,4 @@ class_alias(config('workflows.base_model', Model::class), 'Workflow\Models\Model $this->commands([ActivityMakeCommand::class, WorkflowMakeCommand::class]); } - - public function register(): void - { - // - } } diff --git a/src/Traits/FetchesMonitorAuth.php b/src/Traits/FetchesMonitorAuth.php deleted file mode 100644 index e06546e..0000000 --- a/src/Traits/FetchesMonitorAuth.php +++ /dev/null @@ -1,20 +0,0 @@ -get(config('workflows.monitor_url') . '/functions/v1/get-user') - ->json(); - }); - } -} diff --git a/src/Traits/MonitorQueueConnection.php b/src/Traits/MonitorQueueConnection.php deleted file mode 100644 index 9bbcc76..0000000 --- a/src/Traits/MonitorQueueConnection.php +++ /dev/null @@ -1,21 +0,0 @@ -viaConnection() . '.queue', 'default') - ); - } -} diff --git a/src/Webhooks.php b/src/Webhooks.php index 559ac94..2005d89 100644 --- a/src/Webhooks.php +++ b/src/Webhooks.php @@ -9,6 +9,10 @@ use Illuminate\Support\Str; use ReflectionClass; use ReflectionMethod; +use Workflow\Auth\NullAuthenticator; +use Workflow\Auth\SignatureAuthenticator; +use Workflow\Auth\TokenAuthenticator; +use Workflow\Auth\WebhookAuthenticator; class Webhooks { @@ -162,25 +166,16 @@ private static function resolveNamedParameters($class, $method, $payload) private static function validateAuth(Request $request): bool { - $config = config('workflows.webhook_auth', [ - 'method' => 'none', - ]); - - if ($config['method'] === 'none') { - return true; - } - - if ($config['method'] === 'signature') { - $secret = $config['signature']['secret']; - $header = $config['signature']['header']; - $expectedSignature = hash_hmac('sha256', $request->getContent(), $secret); - return $request->header($header) === $expectedSignature; - } - - if ($config['method'] === 'token') { - $token = $config['token']['token']; - $header = $config['token']['header']; - return $request->header($header) === $token; + $authenticatorClass = match (config('workflows.webhook_auth.method', 'none')) { + 'none' => NullAuthenticator::class, + 'signature' => SignatureAuthenticator::class, + 'token' => TokenAuthenticator::class, + 'custom' => config('workflows.webhook_auth.custom.class'), + default => null, + }; + + if (is_subclass_of($authenticatorClass, WebhookAuthenticator::class)) { + return (new $authenticatorClass())->validate($request); } return false; diff --git a/src/config/workflows.php b/src/config/workflows.php index 702c9fc..c01308a 100644 --- a/src/config/workflows.php +++ b/src/config/workflows.php @@ -37,18 +37,9 @@ 'header' => env('WORKFLOW_WEBHOOKS_TOKEN_HEADER', 'Authorization'), 'token' => env('WORKFLOW_WEBHOOKS_TOKEN'), ], - ], - - 'monitor' => env('WORKFLOW_MONITOR', false), - - 'monitor_url' => env('WORKFLOW_MONITOR_URL'), - - 'monitor_api_key' => env('WORKFLOW_MONITOR_API_KEY'), - 'monitor_connection' => env('WORKFLOW_MONITOR_CONNECTION', config('queue.default')), - - 'monitor_queue' => env( - 'WORKFLOW_MONITOR_QUEUE', - config('queue.connections.' . config('queue.default') . '.queue', 'default') - ), + 'custom' => [ + 'class' => env('WORKFLOW_WEBHOOKS_CUSTOM_AUTH_CLASS', null), + ], + ], ]; diff --git a/tests/Unit/Config/WorkflowsConfigTest.php b/tests/Unit/Config/WorkflowsConfigTest.php index 96f9dbc..28ad829 100644 --- a/tests/Unit/Config/WorkflowsConfigTest.php +++ b/tests/Unit/Config/WorkflowsConfigTest.php @@ -26,14 +26,6 @@ public function testConfigIsLoaded(): void 'serializer' => \Workflow\Serializers\Y::class, 'prune_age' => '1 month', 'webhooks_route' => env('WORKFLOW_WEBHOOKS_ROUTE', 'webhooks'), - 'monitor' => env('WORKFLOW_MONITOR', false), - 'monitor_url' => env('WORKFLOW_MONITOR_URL'), - 'monitor_api_key' => env('WORKFLOW_MONITOR_API_KEY'), - 'monitor_connection' => env('WORKFLOW_MONITOR_CONNECTION', config('queue.default')), - 'monitor_queue' => env( - 'WORKFLOW_MONITOR_QUEUE', - config('queue.connections.' . config('queue.default') . '.queue', 'default') - ), ]; foreach ($expectedConfig as $key => $expectedValue) { diff --git a/tests/Unit/Listeners/MonitorActivityCompletedTest.php b/tests/Unit/Listeners/MonitorActivityCompletedTest.php deleted file mode 100644 index 0e09da2..0000000 --- a/tests/Unit/Listeners/MonitorActivityCompletedTest.php +++ /dev/null @@ -1,59 +0,0 @@ -app->make('cache') - ->store() - ->clear(); - - config([ - 'workflows.monitor_url' => 'http://test', - ]); - config([ - 'workflows.monitor_api_key' => 'key', - ]); - - $activityId = (string) Str::uuid(); - - Http::fake([ - 'functions/v1/get-user' => Http::response([ - 'user' => 'user', - 'public' => 'public', - 'token' => 'token', - ]), - "rest/v1/activities?id=eq.{$activityId}" => Http::response(), - ]); - - $event = new ActivityCompleted(1, $activityId, 'output', 'time'); - $listener = new MonitorActivityCompleted(); - $listener->handle($event); - - Http::assertSent(static function (Request $request) { - return $request->hasHeader('Authorization', 'Bearer key') && - $request->url() === 'http://test/functions/v1/get-user'; - }); - - Http::assertSent(static function (Request $request) use ($activityId) { - $data = json_decode($request->body()); - return $request->hasHeader('apiKey', 'public') && - $request->hasHeader('Authorization', 'Bearer token') && - $request->url() === "http://test/rest/v1/activities?id=eq.{$activityId}" && - $data->status === 'completed' && - $data->output === 'output' && - $data->updated_at === 'time'; - }); - } -} diff --git a/tests/Unit/Listeners/MonitorActivityFailedTest.php b/tests/Unit/Listeners/MonitorActivityFailedTest.php deleted file mode 100644 index 994ad6d..0000000 --- a/tests/Unit/Listeners/MonitorActivityFailedTest.php +++ /dev/null @@ -1,59 +0,0 @@ -app->make('cache') - ->store() - ->clear(); - - config([ - 'workflows.monitor_url' => 'http://test', - ]); - config([ - 'workflows.monitor_api_key' => 'key', - ]); - - $activityId = (string) Str::uuid(); - - Http::fake([ - 'functions/v1/get-user' => Http::response([ - 'user' => 'user', - 'public' => 'public', - 'token' => 'token', - ]), - "rest/v1/activities?id=eq.{$activityId}" => Http::response(), - ]); - - $event = new ActivityFailed(1, $activityId, 'output', 'time'); - $listener = new MonitorActivityFailed(); - $listener->handle($event); - - Http::assertSent(static function (Request $request) { - return $request->hasHeader('Authorization', 'Bearer key') && - $request->url() === 'http://test/functions/v1/get-user'; - }); - - Http::assertSent(static function (Request $request) use ($activityId) { - $data = json_decode($request->body()); - return $request->hasHeader('apiKey', 'public') && - $request->hasHeader('Authorization', 'Bearer token') && - $request->url() === "http://test/rest/v1/activities?id=eq.{$activityId}" && - $data->status === 'failed' && - $data->output === 'output' && - $data->updated_at === 'time'; - }); - } -} diff --git a/tests/Unit/Listeners/MonitorActivityStartedTest.php b/tests/Unit/Listeners/MonitorActivityStartedTest.php deleted file mode 100644 index 6c44307..0000000 --- a/tests/Unit/Listeners/MonitorActivityStartedTest.php +++ /dev/null @@ -1,64 +0,0 @@ -app->make('cache') - ->store() - ->clear(); - - config([ - 'workflows.monitor_url' => 'http://test', - ]); - config([ - 'workflows.monitor_api_key' => 'key', - ]); - - $activityId = (string) Str::uuid(); - - Http::fake([ - 'functions/v1/get-user' => Http::response([ - 'user' => 'user', - 'public' => 'public', - 'token' => 'token', - ]), - 'rest/v1/activities' => Http::response(), - ]); - - $event = new ActivityStarted(1, $activityId, 'class', 0, 'arguments', 'time'); - $listener = new MonitorActivityStarted(); - $listener->handle($event); - - Http::assertSent(static function (Request $request) { - return $request->hasHeader('Authorization', 'Bearer key') && - $request->url() === 'http://test/functions/v1/get-user'; - }); - - Http::assertSent(static function (Request $request) use ($activityId) { - $data = json_decode($request->body()); - return $request->hasHeader('apiKey', 'public') && - $request->hasHeader('Authorization', 'Bearer token') && - $request->url() === 'http://test/rest/v1/activities' && - $data->user_id === 'user' && - $data->workflow_id === 1 && - $data->id === $activityId && - $data->index === 0 && - $data->class === 'class' && - $data->status === 'running' && - $data->arguments === 'arguments' && - $data->created_at === 'time'; - }); - } -} diff --git a/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php b/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php deleted file mode 100644 index 3e1159d..0000000 --- a/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php +++ /dev/null @@ -1,56 +0,0 @@ -app->make('cache') - ->store() - ->clear(); - - config([ - 'workflows.monitor_url' => 'http://test', - ]); - config([ - 'workflows.monitor_api_key' => 'key', - ]); - - Http::fake([ - 'functions/v1/get-user' => Http::response([ - 'user' => 'user', - 'public' => 'public', - 'token' => 'token', - ]), - 'rest/v1/workflows?user_id=eq.user&workflow_id=eq.1' => Http::response(), - ]); - - $event = new WorkflowCompleted(1, 'output', 'time'); - $listener = new MonitorWorkflowCompleted(); - $listener->handle($event); - - Http::assertSent(static function (Request $request) { - return $request->hasHeader('Authorization', 'Bearer key') && - $request->url() === 'http://test/functions/v1/get-user'; - }); - - Http::assertSent(static function (Request $request) { - $data = json_decode($request->body()); - return $request->hasHeader('apiKey', 'public') && - $request->hasHeader('Authorization', 'Bearer token') && - $request->url() === 'http://test/rest/v1/workflows?user_id=eq.user&workflow_id=eq.1' && - $data->status === 'completed' && - $data->output === 'output' && - $data->updated_at === 'time'; - }); - } -} diff --git a/tests/Unit/Listeners/MonitorWorkflowFailedTest.php b/tests/Unit/Listeners/MonitorWorkflowFailedTest.php deleted file mode 100644 index ffd5e5a..0000000 --- a/tests/Unit/Listeners/MonitorWorkflowFailedTest.php +++ /dev/null @@ -1,56 +0,0 @@ -app->make('cache') - ->store() - ->clear(); - - config([ - 'workflows.monitor_url' => 'http://test', - ]); - config([ - 'workflows.monitor_api_key' => 'key', - ]); - - Http::fake([ - 'functions/v1/get-user' => Http::response([ - 'user' => 'user', - 'public' => 'public', - 'token' => 'token', - ]), - 'rest/v1/workflows?user_id=eq.user&workflow_id=eq.1' => Http::response(), - ]); - - $event = new WorkflowFailed(1, 'output', 'time'); - $listener = new MonitorWorkflowFailed(); - $listener->handle($event); - - Http::assertSent(static function (Request $request) { - return $request->hasHeader('Authorization', 'Bearer key') && - $request->url() === 'http://test/functions/v1/get-user'; - }); - - Http::assertSent(static function (Request $request) { - $data = json_decode($request->body()); - return $request->hasHeader('apiKey', 'public') && - $request->hasHeader('Authorization', 'Bearer token') && - $request->url() === 'http://test/rest/v1/workflows?user_id=eq.user&workflow_id=eq.1' && - $data->status === 'failed' && - $data->output === 'output' && - $data->updated_at === 'time'; - }); - } -} diff --git a/tests/Unit/Listeners/MonitorWorkflowStartedTest.php b/tests/Unit/Listeners/MonitorWorkflowStartedTest.php deleted file mode 100644 index 6c2a24e..0000000 --- a/tests/Unit/Listeners/MonitorWorkflowStartedTest.php +++ /dev/null @@ -1,59 +0,0 @@ -app->make('cache') - ->store() - ->clear(); - - config([ - 'workflows.monitor_url' => 'http://test', - ]); - config([ - 'workflows.monitor_api_key' => 'key', - ]); - - Http::fake([ - 'functions/v1/get-user' => Http::response([ - 'user' => 'user', - 'public' => 'public', - 'token' => 'token', - ]), - 'rest/v1/workflows' => Http::response(), - ]); - - $event = new WorkflowStarted(1, 'class', 'arguments', 'time'); - $listener = new MonitorWorkflowStarted(); - $listener->handle($event); - - Http::assertSent(static function (Request $request) { - return $request->hasHeader('Authorization', 'Bearer key') && - $request->url() === 'http://test/functions/v1/get-user'; - }); - - Http::assertSent(static function (Request $request) { - $data = json_decode($request->body()); - return $request->hasHeader('apiKey', 'public') && - $request->hasHeader('Authorization', 'Bearer token') && - $request->url() === 'http://test/rest/v1/workflows' && - $data->user_id === 'user' && - $data->workflow_id === 1 && - $data->class === 'class' && - $data->status === 'running' && - $data->arguments === 'arguments' && - $data->created_at === 'time'; - }); - } -} diff --git a/tests/Unit/Providers/WorkflowServiceProviderTest.php b/tests/Unit/Providers/WorkflowServiceProviderTest.php index 8cbf185..7148c48 100644 --- a/tests/Unit/Providers/WorkflowServiceProviderTest.php +++ b/tests/Unit/Providers/WorkflowServiceProviderTest.php @@ -6,12 +6,6 @@ use Illuminate\Support\Facades\Artisan; use Tests\TestCase; -use Workflow\Events\ActivityCompleted; -use Workflow\Events\ActivityFailed; -use Workflow\Events\ActivityStarted; -use Workflow\Events\WorkflowCompleted; -use Workflow\Events\WorkflowFailed; -use Workflow\Events\WorkflowStarted; use Workflow\Providers\WorkflowServiceProvider; final class WorkflowServiceProviderTest extends TestCase @@ -29,47 +23,6 @@ public function testProviderLoads(): void ); } - public function testEventListenersAreRegistered(): void - { - config([ - 'workflows.monitor' => true, - ]); - - (new WorkflowServiceProvider($this->app))->boot(); - - $dispatcher = app('events'); - - $expectedListeners = [ - WorkflowStarted::class => \Workflow\Listeners\MonitorWorkflowStarted::class, - WorkflowCompleted::class => \Workflow\Listeners\MonitorWorkflowCompleted::class, - WorkflowFailed::class => \Workflow\Listeners\MonitorWorkflowFailed::class, - ActivityStarted::class => \Workflow\Listeners\MonitorActivityStarted::class, - ActivityCompleted::class => \Workflow\Listeners\MonitorActivityCompleted::class, - ActivityFailed::class => \Workflow\Listeners\MonitorActivityFailed::class, - ]; - - foreach ($expectedListeners as $event => $listener) { - $registeredListeners = $dispatcher->getListeners($event); - - $attached = false; - foreach ($registeredListeners as $registeredListener) { - if ($registeredListener instanceof \Closure) { - $closureReflection = new \ReflectionFunction($registeredListener); - $useVariables = $closureReflection->getStaticVariables(); - - if (isset($useVariables['listener']) && is_array($useVariables['listener'])) { - if ($useVariables['listener'][0] === $listener) { - $attached = true; - break; - } - } - } - } - - $this->assertTrue($attached, "Event [{$event}] does not have the [{$listener}] listener attached."); - } - } - public function testConfigIsPublished(): void { Artisan::call('vendor:publish', [ diff --git a/tests/Unit/Traits/MonitorQueueConnectionTest.php b/tests/Unit/Traits/MonitorQueueConnectionTest.php deleted file mode 100644 index f3756d0..0000000 --- a/tests/Unit/Traits/MonitorQueueConnectionTest.php +++ /dev/null @@ -1,67 +0,0 @@ - 'sync', - 'workflows.monitor_connection' => config('queue.default'), - ]); - - $instance = $this->makeAnonymousTraitInstance(); - - $this->assertSame(config('queue.default'), $instance->viaConnection()); - } - - public function testReturnsDefaultQueue(): void - { - config([ - 'queue.default' => 'sync', - 'workflows.monitor_connection' => config('queue.default'), - ]); - - $instance = $this->makeAnonymousTraitInstance(); - - $this->assertSame('default', $instance->viaQueue()); - } - - public function testReturnsCustomConnection(): void - { - config([ - 'queue.default' => 'sync', - 'workflows.monitor_connection' => 'custom_connection', - ]); - - $instance = $this->makeAnonymousTraitInstance(); - - $this->assertSame('custom_connection', $instance->viaConnection()); - } - - public function testReturnsCustomQueue(): void - { - config([ - 'queue.default' => 'sync', - 'workflows.monitor_connection' => config('queue.default'), - 'workflows.monitor_queue' => 'custom_queue', - ]); - - $instance = $this->makeAnonymousTraitInstance(); - - $this->assertSame('custom_queue', $instance->viaQueue()); - } - - private function makeAnonymousTraitInstance(): object - { - return new class() { - use MonitorQueueConnection; - }; - } -} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy