PHPackages                             rakko-inc/laravel-graceful-schedule-worker - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. rakko-inc/laravel-graceful-schedule-worker

ActiveLibrary[Queues &amp; Workers](/categories/queues)

rakko-inc/laravel-graceful-schedule-worker
==========================================

0.3.0(2mo ago)0305↓50%MITPHPPHP ^7.2.5 || ~8.0CI passing

Since Aug 26Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/rakkofield/laravel-graceful-schedule-worker)[ Packagist](https://packagist.org/packages/rakko-inc/laravel-graceful-schedule-worker)[ RSS](/packages/rakko-inc-laravel-graceful-schedule-worker/feed)WikiDiscussions 1.x Synced 1mo ago

READMEChangelog (3)Dependencies (24)Versions (5)Used By (0)

rakko-inc/laravel-graceful-schedule-worker
==========================================

[](#rakko-inclaravel-graceful-schedule-worker)

A graceful schedule worker for Laravel 6 &amp; 7 with missed-task recovery and optional AWS Step Functions integration.

Overview
--------

[](#overview)

Replace Laravel's `schedule:work` with a long-running worker that handles shutdown signals gracefully and recovers missed tasks automatically.

```
// app/Console/Kernel.php
use RakkoInc\LaravelGracefulScheduleWorker\Console\UsesClockAwareSchedule;
use RakkoInc\LaravelGracefulScheduleWorker\Scheduling\ClockAwareSchedule;

class Kernel extends ConsoleKernel
{
    use UsesClockAwareSchedule;

    protected function gracefulSchedule(ClockAwareSchedule $schedule)
    {
        $schedule->command('reports:daily')->dailyAt('02:00')
            ->runInBackground()
            ->withGracePeriod(30);
    }
}
```

```
php artisan schedule:graceful-work
```

Features
--------

[](#features)

- **Graceful shutdown** — Catches SIGTERM/SIGINT and waits for running tasks to finish before exiting
- **Clock abstraction** — Consistent time evaluation across long-running worker cycles
- **At-least-once semantics** — Detects and recovers missed tasks within a configurable grace period
- **Execution tracking** — Redis or Memcached-backed tracking to prevent duplicate dispatch
- **AWS Step Functions integration** — Optionally delegate task execution to Step Functions for managed retries and timeouts
- **High compatibility** — Works with most Laravel scheduling methods (`everyMinute()`, `when()`, `between()`, `withoutOverlapping()`, etc.)

Requirements
------------

[](#requirements)

RequirementVersionPHP^7.2.5 || ~8.0Laravel6.x / 7.xext-pcntlrequiredaws/aws-sdk-php^3.20.1 (optional, for Step Functions)Redis / Memcachedoptional, for execution trackingInstallation
------------

[](#installation)

### 1. Install the package

[](#1-install-the-package)

```
composer require rakko-inc/laravel-graceful-schedule-worker
```

The ServiceProvider is auto-discovered — no manual registration needed.

### 2. Publish the config

[](#2-publish-the-config)

```
php artisan vendor:publish --provider="RakkoInc\LaravelGracefulScheduleWorker\Providers\GracefulScheduleWorkerProvider"
```

### 3. Update your Kernel

[](#3-update-your-kernel)

**Before:**

```
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('reports:daily')->dailyAt('02:00');
    }
}
```

**After:**

```
+use RakkoInc\LaravelGracefulScheduleWorker\Console\UsesClockAwareSchedule;
+use RakkoInc\LaravelGracefulScheduleWorker\Scheduling\ClockAwareSchedule;
 use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

 class Kernel extends ConsoleKernel
 {
+    use UsesClockAwareSchedule;
+
-    protected function schedule(Schedule $schedule)
+    protected function gracefulSchedule(ClockAwareSchedule $schedule)
     {
-        $schedule->command('reports:daily')->dailyAt('02:00');
+        $schedule->command('reports:daily')->dailyAt('02:00')
+            ->runInBackground();
     }
 }
```

### 4. Run the worker

[](#4-run-the-worker)

```
php artisan schedule:graceful-work
```

Quick Start
-----------

[](#quick-start)

### Minimal setup (local dispatch)

[](#minimal-setup-local-dispatch)

The installation steps above give you a fully working graceful worker with local process dispatch. All existing scheduling methods work as-is.

### Enable recovery

[](#enable-recovery)

Add execution tracking to detect and recover missed tasks:

```
SCHEDULE_TRACKER_ENABLED=true
SCHEDULE_TRACKER_STORE=redis
```

Then mark tasks as recoverable:

```
$schedule->command('reports:daily')->dailyAt('02:00')
    ->runInBackground()
    ->withGracePeriod(30); // recover if missed within 30 minutes
```

> **Important:** Recoverable tasks must be idempotent. See [docs/guide/IDEMPOTENCY\_GUIDE.md](docs/guide/IDEMPOTENCY_GUIDE.md).

### Step Functions integration

[](#step-functions-integration)

For managed retries and timeouts via AWS Step Functions:

```
SCHEDULE_DISPATCH=stepfunctions
SCHEDULE_STATE_MACHINE_ARN=arn:aws:states:ap-northeast-1:123456789:stateMachine:my-scheduler
```

```
$schedule->command('reports:daily')->dailyAt('02:00')
    ->dispatchVia('stepfunctions')
    ->withGracePeriod(30);
```

See [docs/internals/STEPFUNCTIONS\_IMPLEMENTATION.md](docs/internals/STEPFUNCTIONS_IMPLEMENTATION.md) for full setup.

Configuration
-------------

[](#configuration)

Environment VariableDefaultDescription`SCHEDULE_DISPATCH``local`Dispatch method: `local` or `stepfunctions``SCHEDULE_TRACKER_ENABLED``false`Enable execution tracking for recovery`SCHEDULE_TRACKER_STORE``null`Cache store for tracking (`redis`, etc.)`SCHEDULE_TRACKER_LOCK_TTL``3600`Lock TTL in seconds`SCHEDULE_STATE_MACHINE_ARN``null`Step Functions state machine ARN`AWS_DEFAULT_REGION``ap-northeast-1`AWS regionClockAwareEvent API
-------------------

[](#clockawareevent-api)

### Additional methods

[](#additional-methods)

MethodDescription`withGracePeriod($minutes)`Enable recovery with a grace period (minutes). Pass `null` for unlimited.`enableRecovery()`Enable recovery without a grace period`dispatchVia($type)`Set dispatcher type: `'local'` or `'stepfunctions'`### Compatibility

[](#compatibility)

Most Laravel scheduling methods work unchanged:

FeatureStatus`everyMinute()`, `hourly()`, `daily()`, `cron()`, etc.Supported`when()` / `skip()`Supported`between()` / `unlessBetween()`Supported (clock-aware)`withoutOverlapping()`Supported`runInBackground()`Supported (recommended)`environments()` / `evenInMaintenanceMode()`Supported`timezone()`Supported### Limitations

[](#limitations)

FeatureLimitation`before()` / `after()` / `onSuccess()` / `onFailure()`Local dispatch only (not available with Step Functions)`appendOutputTo()` / `sendOutputTo()`Local dispatch only`pingBefore()` / `thenPing()` / `emailOutputTo()`Local dispatch only`$schedule->call(Closure)`Not supported — convert to Artisan commands`lastDayOfMonth()`May be inaccurate across month boundaries in long-running workersSee [docs/internals/SCHEDULER\_COMPATIBILITY.md](docs/internals/SCHEDULER_COMPATIBILITY.md) for details.

Migration from Laravel Scheduler
--------------------------------

[](#migration-from-laravel-scheduler)

Migration requires minimal changes — your existing `schedule()` body can be copied almost as-is into `gracefulSchedule()`. For projects with many tasks, gradual migration is also supported: keep `schedule()` as-is and move tasks one by one to `gracefulSchedule()`. See [docs/guide/MIGRATION.md](docs/guide/MIGRATION.md) for a step-by-step guide.

Documentation
-------------

[](#documentation)

### Usage Guides

[](#usage-guides)

- [Quick Start Guide](docs/guide/QUICKSTART.md)
- [Migration Guide](docs/guide/MIGRATION.md)
- [Idempotency Guide](docs/guide/IDEMPOTENCY_GUIDE.md)
- [Step Functions Considerations](docs/guide/STEPFUNCTIONS_CONSIDERATIONS.md)

### Internal Design

[](#internal-design)

- [Design Specification](docs/internals/DESIGN.md)
- [Architecture](docs/internals/ARCHITECTURE.md)
- [Scheduler Compatibility](docs/internals/SCHEDULER_COMPATIBILITY.md)
- [Execution Semantics](docs/internals/SCHEDULE_EXECUTION_SEMANTICS.md)
- [Step Functions Implementation](docs/internals/STEPFUNCTIONS_IMPLEMENTATION.md)
- [Scheduler Comparison](docs/internals/SCHEDULER_COMPARISON.md)

Demo
----

[](#demo)

A ready-to-run sample application is in the `demo/` directory. It demonstrates:

- **Gradual migration** — `schedule()` (native) and `gracefulSchedule()` (clock-aware) coexisting
- **Grace period &amp; recovery** — `withGracePeriod(30)` vs `enableRecovery()`
- **Clock-aware filters** — `between('08:00', '22:00')`
- **Step Functions dispatch** — `dispatchVia('stepfunctions')` via moto (local AWS mock)

### With Docker (recommended)

[](#with-docker-recommended)

Docker Compose starts moto (AWS Step Functions mock) automatically, so all features including Step Functions dispatch work out of the box.

```
cd demo
docker compose up --build
```

Send `SIGTERM` to verify graceful shutdown:

```
docker compose kill -s SIGTERM php
```

### Without Docker

[](#without-docker)

Local execution supports local dispatch only. Step Functions dispatch requires moto.

```
cd demo
composer install
cp .env.example .env
php artisan key:generate
php artisan schedule:graceful-work
```

### After changing library source

[](#after-changing-library-source)

Reflect the latest library code into the demo:

```
composer demo:update
```

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance87

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~63 days

Total

4

Last Release

70d ago

Major Versions

0.3.0 → 1.x-dev2026-03-04

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/194480335?v=4)[Rakko, Inc.](/maintainers/rakko-inc)[@rakko-inc](https://github.com/rakko-inc)

---

Top Contributors

[![NaokiTsuchiya](https://avatars.githubusercontent.com/u/17171732?v=4)](https://github.com/NaokiTsuchiya "NaokiTsuchiya (35 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/rakko-inc-laravel-graceful-schedule-worker/health.svg)

```
[![Health](https://phpackages.com/badges/rakko-inc-laravel-graceful-schedule-worker/health.svg)](https://phpackages.com/packages/rakko-inc-laravel-graceful-schedule-worker)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.6k509.9M17.0k](/packages/laravel-framework)[laravel-zero/framework

The Laravel Zero Framework.

3371.4M369](/packages/laravel-zero-framework)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k36.7M259](/packages/laravel-dusk)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
