Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Long Running Tasks Laravel Package

spatie/laravel-long-running-tasks

Monitor and manage external long-running tasks (e.g., AWS Rekognition jobs) in Laravel by polling for status. Define a task with a check() method, store metadata, and keep checking at a configurable interval until completion.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/laravel-long-running-tasks
    php artisan vendor:publish --tag="long-running-tasks-migrations"
    php artisan migrate
    php artisan vendor:publish --tag="long-running-tasks-config"
    
  2. Define a Task Class: Create a class extending Spatie\LongRunningTasks\LongRunningTask with a check() method:

    use Spatie\LongRunningTasks\LongRunningTask;
    use Spatie\LongRunningTasks\Enums\TaskResult;
    
    class ProcessVideoTask extends LongRunningTask
    {
        public function check($logItem): TaskResult
        {
            $status = $this->pollExternalService($logItem->meta['video_id']);
            return $status === 'completed' ? TaskResult::StopChecking : TaskResult::ContinueChecking;
        }
    }
    
  3. Start the Task:

    ProcessVideoTask::make()->meta(['video_id' => 123])->start();
    

First Use Case

Monitor an external API (e.g., AWS Rekognition) that requires polling for task completion. Use the check() method to poll the API and return TaskResult::StopChecking when done.


Implementation Patterns

Core Workflow

  1. Task Definition: Extend LongRunningTask and implement check(). Use $logItem->meta to access task-specific data.

  2. Task Execution:

    // Start with metadata
    MyTask::make()->meta(['key' => 'value'])->start();
    
    // Or inline
    MyTask::make()->start(['key' => 'value']);
    
  3. Polling Logic:

    public function check($logItem): TaskResult
    {
        $response = $this->callExternalService($logItem->meta);
        if ($response->isComplete()) {
            return TaskResult::StopChecking;
        }
        return TaskResult::ContinueChecking;
    }
    

Integration Tips

  • Queue Management: Use onQueue() to route tasks to specific queues (e.g., high-priority queues for time-sensitive tasks):

    MyTask::make()->onQueue('high')->start();
    
  • Dynamic Check Intervals: Override checkFrequencyInSeconds for tasks needing variable polling:

    class MyTask extends LongRunningTask
    {
        public int $checkFrequencyInSeconds = 30; // 30-second interval
    }
    
  • Backoff Strategies: Use StandardBackoffCheckStrategy for exponential delays:

    MyTask::make()
        ->checkStrategy(\Spatie\LongRunningTasks\Strategies\StandardBackoffCheckStrategy::class)
        ->start();
    
  • Event-Driven Extensions: Listen to LongRunningTaskStarted, LongRunningTaskCompleted, or LongRunningTaskFailed events for logging/alerts:

    use Spatie\LongRunningTasks\Events\LongRunningTaskCompleted;
    
    LongRunningTaskCompleted::listen(function ($logItem) {
        Log::info("Task {$logItem->task} completed");
    });
    

Common Patterns

  • Task Metadata: Use meta to pass structured data (e.g., IDs, configs) to the task:

    MyTask::make()->meta(['user_id' => 1, 'options' => ['resize' => true]])->start();
    
  • Error Handling: Implement onFail() to retry or log failures:

    public function onFail($logItem, Exception $e): ?TaskResult
    {
        Log::error("Task failed: " . $e->getMessage());
        return TaskResult::ContinueChecking; // Retry
    }
    
  • Custom Models: Extend LongRunningTaskLogItem for additional fields:

    class CustomTaskLog extends LongRunningTaskLogItem
    {
        protected $casts = ['custom_field' => 'string'];
    }
    

    Update config/long-running-tasks.php:

    'log_model' => App\Models\CustomTaskLog::class,
    

Gotchas and Tips

Pitfalls

  1. Queue Workers:

    • Issue: Forgetting to run queue workers (php artisan queue:work) will halt task polling.
    • Fix: Ensure workers are running in production (e.g., via Supervisor).
  2. Infinite Loops:

    • Issue: Tasks stuck in running state due to misconfigured keepCheckingForInSeconds (default: 300s).
    • Fix: Set a reasonable timeout (e.g., 60 * 60 for 1 hour) or override per task:
      MyTask::make()->keepCheckingForInseconds(60 * 60)->start();
      
  3. Meta Data Serialization:

    • Issue: Complex objects in meta may not serialize correctly.
    • Fix: Use arrays or JSON-serializable data:
      ->meta(['data' => json_encode($complexObject)])
      
  4. Race Conditions:

    • Issue: Concurrent task updates may corrupt meta or state.
    • Fix: Use database transactions in check() for critical operations.
  5. Strategy Misconfiguration:

    • Issue: Incorrect backoff strategies (e.g., ExponentialBackoffCheckStrategy) may cause excessive delays.
    • Fix: Test strategies locally with php artisan queue:work --once.

Debugging Tips

  • Log Task Status: Use LongRunningTaskLogItem::where('status', 'running')->get() to inspect stuck tasks.
  • Simulate Failures: Throw exceptions in check() to test onFail():
    throw new \Exception("Simulated failure");
    
  • Check Queue: Monitor queue jobs with php artisan queue:failed and retry manually if needed.

Extension Points

  1. Custom Jobs: Extend RunLongRunningTaskJob to add pre/post-processing:

    namespace App\Jobs;
    
    use Spatie\LongRunningTasks\Jobs\RunLongRunningTaskJob as BaseJob;
    
    class CustomTaskJob extends BaseJob
    {
        protected function handle()
        {
            // Custom logic before/after task execution
            parent::handle();
        }
    }
    

    Update config:

    'task_job' => App\Jobs\CustomTaskJob::class,
    
  2. Webhooks: Combine with spatie/laravel-webhooks to trigger tasks via external events:

    Webhook::route('video-processed', function (Payload $payload) {
        ProcessVideoTask::make()->meta($payload->data)->start();
    });
    
  3. Rate Limiting: Use spatie/laravel-rate-limiting to throttle polling:

    RateLimiter::for('task-polling')->allow(10)->every(60)->response(function () {
        return TaskResult::StopChecking;
    });
    

Configuration Quirks

  • Queue Defaults: Ensure the configured queue (default in config) exists in .env:
    QUEUE_CONNECTION=database
    
  • Timezones: last_check_started_at/ended_at use the app’s timezone. Set explicitly in config/app.php if needed:
    'timezone' => 'UTC',
    
  • Database Indexes: Add indexes to long_running_task_log_items for large-scale use:
    Schema::table('long_running_task_log_items', function (Blueprint $table) {
        $table->index('status');
        $table->index('task');
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai