> $tasks_by_job */ public function __construct( private readonly array $tasks_by_job, private readonly JobLock $lock, private readonly JobStateStore $store, private readonly SchedulerLog $scheduler_log, private readonly Clock $clock ) { } public function run( JobId $job ): void { $this->while_locked( fn() => $this->record_run( $job ) ); } public function step( JobId $job ): void { $this->while_locked( fn() => $this->run_tasks( $job ) ); } private function while_locked( Closure $work ): void { if ( ! $this->lock->acquire() ) { return; } try { $work(); } finally { $this->lock->release(); } } private function record_run( JobId $job ): void { $ran_at = $this->clock->now(); $count = $this->run_tasks( $job ); $state = $this->store->load( $job )->with_run( $ran_at, $count ); $this->store->save( $job, $state ); $this->scheduler_log->record_run( $ran_at ); } private function run_tasks( JobId $job ): int { $count = 0; foreach ( $this->tasks_by_job[ $job->value ] ?? array() as $task ) { $count += $task->run(); } return $count; } }