laravel-queueable-action

repository·main·Indexed 20 days ago

https://github.com/spatie/laravel-queueable-action

A Laravel package for structuring business logic using Actions that can be executed synchronously or dispatched to queues. It supports constructor injection via the Laravel container, invokeable actions, action chaining via ActionJob, and custom Horizon tags and job middleware.

Tokens
2K
Snippets
12
Records
12
Agent score
22%

What's inside spatie/laravel-queueable-action

  1. Publish the package configuration

    main

    You can optionally publish the configuration file to customize the job class used for dispatching actions. If you provide a custom job class, it must extend \Spatie\QueueableAction\ActionJob.

    php artisan vendor:publish --provider="Spatie\QueueableAction\QueueableActionServiceProvider" --tag="config"
  2. Chain actions using ActionJob

    main

    You can chain multiple actions together by wrapping subsequent actions in an ActionJob. The ActionJob constructor accepts the action class (or instance) as the first argument and an array of the action's arguments as the second.

    use Spatie\QueueableAction\ActionJob;
    
    $args = [$userId, $data];
    
    app(MyAction::class)
        ->onQueue()
        ->execute(...$args)
        ->chain([
            new ActionJob(AnotherAction::class, $args),
        ]);
  3. Execute actions synchronously or on a queue

    main

    Once an action is defined with the QueueableAction trait, you can choose to run it immediately or dispatch it to a queue.

    • Synchronous: Call execute() directly.
    • Asynchronous: Call onQueue() followed by execute().
    • Specific Queue: Pass a queue name to onQueue('queue-name').
    // Execute on the default queue
    $action->onQueue()->execute($model, $requestData);
    
    // Execute on a specific queue
    $action->onQueue('my-favorite-queue')->execute($model, $requestData);
    
    // Execute synchronously (right now)
    $action->execute($model, $requestData);
  4. Create a queueable action class

    main

    To create an action, use the QueueableAction trait. You can use the Artisan command to generate these classes automatically. Actions can use standard methods (like execute()) or the __invoke() magic method. Constructor arguments are resolved from the Laravel container.

    php artisan make:action MyAction [--sync]
    class MyAction
    {
        use QueueableAction;
    
        public function __construct(
            OtherAction $otherAction,
            ServiceFromTheContainer $service
        ) {
            $this->otherAction = $otherAction;
            $this->service = $service;
        }
    
        public function execute(
            MyModel $model,
            RequestData $requestData
        ) {
            // Business logic
        }
    }
  5. How to use invokeable actions

    main

    The package automatically detects actions that implement the __invoke() method. To queue an invokeable action, you still use the onQueue()->execute() pattern.

    class MyInvokeableAction
    {
        use QueueableAction;
    
        public function __invoke(
            MyModel $model,
            RequestData $requestData
        ) {
            // Business logic
        }
    }
    
    // To queue it:
    $myInvokeableAction->onQueue()->execute($model, $requestData);
  6. Test queued actions with QueueableActionFake

    main

    Use Spatie\QueueableAction\Testing\QueueableActionFake to assert that actions were pushed to the queue. Note: You must call Queue::fake() before using these assertions.

    /** @test */
    public function it_queues_an_action()
    {
        Queue::fake();
    
        (new DoSomethingAction)->onQueue()->execute();
    
        QueueableActionFake::assertPushed(DoSomethingAction::class);
    }
  7. Configure Action Backoff

    main

    You can define how long Laravel should wait before retrying an action that fails. You can do this by defining a $backoff property or a backoff() method.

    // Using a property
    class BackoffAction
    {
        use QueueableAction;
        
        public $backoff = 3;
    }
    
    // Using a method for complex logic
    class BackoffAction
    {
        use QueueableAction;
    
        public function backoff(): int
        {
            return 3;
        }
    }
    
    // Using an array for exponential backoff
    class BackoffAction
    {
        use QueueableAction;
    
        public function backoff(): array
        {
            return [1, 5, 10]; // 1s, then 5s, then 10s
        }
    }
  8. Reference: QueueableActionFake assertions

    main

    The following assertions are available in the QueueableActionFake class for testing action dispatching.

    QueueableActionFake::assertPushed(string $actionClass);
    QueueableActionFake::assertPushedTimes(string $actionClass, int $times = 1);
    QueueableActionFake::assertNotPushed(string $actionClass);
    QueueableActionFake::assertPushedWithChain(string $actionClass, array $expextedActionChain = []);
    QueueableActionFake::assertPushedWithoutChain(string $actionClass);
  9. Generate a new action class with make:action

    main

    Use the make:action Artisan command to scaffold a new action class. By default, the command generates a queued action class located in the App\Actions namespace. If you want the action to be synchronous (not queued), use the --sync flag.

    php artisan make:action MyNewAction
    
    # To create a synchronous action instead of a queued one:
    php artisan make:action MySyncAction --sync