You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Set up the scheduler with `MaintenanceManager`. Pass the manager to both the scheduler and the run command:
851
+
852
+
```php
853
+
use Orisai\Scheduler\Command\RunCommand;
854
+
use Orisai\Scheduler\Executor\ProcessJobExecutor;
855
+
use Orisai\Scheduler\Maintenance\FileRunRegistry;
856
+
use Orisai\Scheduler\Maintenance\MaintenanceManager;
857
+
use Orisai\Scheduler\SimpleScheduler;
858
+
859
+
$checker = new AppMaintenanceChecker();
860
+
$registry = new FileRunRegistry(__DIR__ . '/var/scheduler-runs');
861
+
$manager = new MaintenanceManager($checker, $registry);
862
+
863
+
$executor = new ProcessJobExecutor();
864
+
865
+
$scheduler = new SimpleScheduler(
866
+
null, // errorHandler
867
+
null, // lockFactory
868
+
$executor,
869
+
null, // clock
870
+
null, // logger
871
+
$manager,
872
+
);
873
+
874
+
$runCommand = new RunCommand($scheduler, null, $manager);
875
+
```
876
+
877
+
The grace period (time before force-kill) defaults to 30 seconds. This matches the Kubernetes
878
+
`terminationGracePeriodSeconds` default - long enough for most jobs to finish DB transactions, API calls
879
+
and file operations, short enough to not block deploys excessively.
880
+
881
+
```php
882
+
$manager = new MaintenanceManager($checker, $registry, 60); // 60 second grace period
883
+
```
884
+
885
+
### Run tracking
886
+
887
+
`RunRegistry` tracks active `scheduler:run` processes so deploy scripts can check if it's safe to proceed.
888
+
Two implementations are provided:
889
+
890
+
**FileRunRegistry** (default, single-server):
891
+
892
+
```php
893
+
use Orisai\Scheduler\Maintenance\FileRunRegistry;
894
+
895
+
$registry = new FileRunRegistry(__DIR__ . '/var/scheduler-runs');
896
+
```
897
+
898
+
Writes a file per active run. Automatically cleans up stale entries older than 1 hour from crashed processes.
899
+
900
+
**LockPoolRunRegistry** (multi-server):
901
+
902
+
```php
903
+
use Orisai\Scheduler\Maintenance\LockPoolRunRegistry;
904
+
use Symfony\Component\Lock\LockFactory;
905
+
906
+
$registry = new LockPoolRunRegistry($lockFactory, 10); // pool of 10 slots
907
+
```
908
+
909
+
Uses `symfony/lock` with a fixed pool of lock keys. Works with any lock store (Redis, database, etc.).
910
+
If all pool slots are taken, throws `LogicException` - increase the pool size.
911
+
912
+
### Status command
913
+
914
+
Check maintenance state and active runs:
915
+
916
+
```bash
917
+
php bin/console scheduler:status
918
+
```
919
+
920
+
Output:
921
+
922
+
```
923
+
Maintenance: ACTIVE
924
+
Active runs: 2
925
+
- 1712345678-a3f2b1 (started 15s ago)
926
+
- 1712345679-d4e5c2 (started 3s ago)
927
+
Ready for shutdown: NO
928
+
```
929
+
930
+
Also available programmatically:
931
+
932
+
```php
933
+
$status = $manager->getStatus();
934
+
$status->isMaintenance(); // bool
935
+
$status->getActiveRunIds(); // list<string>
936
+
$status->isReadyForShutdown(); // true when maintenance active AND no active runs
937
+
```
938
+
939
+
### Signal handling
940
+
941
+
`RunCommand` and `WorkerCommand` handle `SIGTERM` and `SIGINT` signals using Symfony's `SignalRegistry`:
942
+
943
+
-**RunCommand**: first signal triggers graceful shutdown (same as maintenance mode), second signal forces immediate exit
944
+
-**WorkerCommand**: first signal stops spawning new `scheduler:run` processes and waits for current ones to finish, second signal forces immediate exit
945
+
946
+
Signal handling in `RunCommand` requires `MaintenanceManager` to be passed to the command constructor.
947
+
`WorkerCommand` always registers signal handlers when run through a Symfony `Application`.
948
+
949
+
Signal handling requires the `pcntl` extension (available on Linux/macOS CLI, not on Windows).
950
+
When pcntl is not available, signals are silently skipped - the `MaintenanceChecker` polling approach still works.
951
+
952
+
### Deploy integration
953
+
954
+
Typical deploy flow:
955
+
956
+
1. Enable maintenance (create your maintenance flag)
957
+
2. Poll `scheduler:status --fail-when-not-ready` until ready (exits with `0` when ready, `1` when not):
0 commit comments