Search by

Non-blocking cron scheduler with forked PHP workers

Package info

github.com/wolfcharaa/cron-worker

pkg:composer/romanfedorskij/cron

Statistics

Installs: 12

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-10-10 11:35 UTC

This package is auto-updated.

Last update: 2026-10-10 11:37:05 UTC


README

Подключаемая PHP-библиотека для запуска cron-задач в отдельных fork-процессах. Master использует Revolt для неблокирующего ожидания таймеров и сигналов, а блокирующая работа выполняется только внутри child-worker.

Зачем это ставить

Библиотека полезна, когда приложению нужно:

  • держать один long-running scheduler вместо отдельного процесса cron на каждую задачу;
  • описывать расписания fluent API, атрибутами, YAML или обычным crontab;
  • выбирать независимые планы dev, stage, prod или серверные профили;
  • получать свежий PSR-11 container scope и новые подключения на каждый запуск;
  • последовательно запускать одноразовые шаги только после exit code 0;
  • ограничивать пересечения и общее число одновременно работающих процессов;
  • находить ошибки callable и конфигурации до запуска event loop.

Что предоставляет библиотека

Возможность Для чего нужна Подробности
Fluent schedule API everyMinutes(), dailyAt(), weekdays() без ручного cron Scheduling и profiles
Configuration loaders Manual API, attributes, YAML и классический crontab Configuration sources
Symfony Console tasks Именованные arguments/options через InputInterface без callback-обёрток Symfony Console tasks
Guided migration Готовый Codex skill для переноса cron реального приложения Application migration
Success chains Одноразовые callable, service, static, container и exec шаги Task chains
PSR-11 integration Новый container scope внутри каждого child-worker Container contract
Preflight validation Ошибки карты и callable до регистрации задач Configuration validation
Revolt runtime Таймеры, сигналы и неблокирующий master process Runtime
Worker bootstrap Явная композиция loaders и приложения в bin/cron.php Application worker
Crontab conversion Перенос crontab -l в управляемый YAML Configuration sources

Общая модель

manual / attributes / YAML / crontab
                 |
                 v
          CronProfileMap
                 |
                 v
       preflight validation
                 |
                 v
      Revolt scheduler master
                 |
                 v
        forked task process
                 |
          exit code == 0
                 |
                 v
       next one-shot task

Расписание принадлежит только корневой задаче. Шаги then*() не получают собственный cron и ставятся во внутреннюю очередь лишь после успешного завершения предыдущего процесса.

Что остаётся на стороне приложения

Библиотека планирует и исполняет задачи, но не заменяет framework, DI container или process supervisor. Приложение определяет:

  • какие команды и services существуют;
  • как создаётся свежий PSR-11 container;
  • какой профиль активен на конкретном runtime;
  • где хранятся YAML/crontab файлы;
  • как scheduler запускается и перезапускается через systemd, Docker или supervisor;
  • куда отправляются lifecycle-логи.

Как читать документацию

  1. Quick start — первый ручной scheduler.
  2. Configuration sources — выбор loader-а и profiles.
  3. Symfony Console tasks — input, container, chain и troubleshooting.
  4. Application migration — перенос существующих cron-задач с помощью skill.
  5. Task chains — service/static/container pipelines.
  6. Application worker — полный bin/cron.php.
  7. Runtime — fork, Revolt, overlap и shutdown.
  8. Configuration validation — fail-fast контракт.

Установка

composer require romanfedorskij/cron

Требования:

  • PHP ^8.2 на Unix-like системе;
  • ext-pcntl и ext-posix;
  • Revolt event loop;
  • PSR-11 container нужен для service/container и Symfony Console задач.

Quick start

<?php

declare(strict_types=1);

use Wolfcharaa\Cron\Runtime\SchedulerOptions;
use Wolfcharaa\Cron\Scheduler;

require __DIR__ . '/vendor/autoload.php';

$scheduler = new Scheduler(
    new SchedulerOptions(
        maxConcurrency: 4,
        profile: 'default',
        timezone: 'Europe/Moscow',
    ),
);

$scheduler
    ->task('cleanup', static function (): int {
        // Код выполняется в child-worker и не блокирует master event loop.
        return 0;
    })
    ->everyMinutes(5)
    ->weekdays()
    ->withoutOverlapping();

$scheduler->run();

Полный разбор: docs/guides/quick-start.md.

Chain quick start

$scheduler
    ->serviceTask('import', ImportCommand::class, 'run')
    ->everyMinutes(15)
    ->thenStatic('reindex', SearchIndex::class, 'rebuild', ['products'])
    ->thenContainer(
        'notify',
        [PipelineCallbacks::class, 'notify'],
        ['operations'],
    );

Static callback для thenContainer() получает container и context перед настроенными аргументами:

public static function notify(
    ContainerInterface $container,
    TaskExecutionContext $context,
    string $channel,
): int {
    return 0;
}

В атрибутах те же шаги задаются через StaticTaskConfig, ContainerTaskConfig и SymfonyCommandTaskConfig. См. полный пример attribute pipeline и Symfony Console tasks.

Документация по разделам

Guides

Reference

Examples

Разработка

make check
make test-php-matrix

Матрица проверяет PHP 8.2–8.5 с минимально допустимыми и последними совместимыми версиями зависимостей. Один вариант можно запустить отдельно:

make test-php-version PHP_VERSION=8.4 DEPENDENCY_MODE=lowest