diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d898c..1285b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `SymfonyCommandJob` - `JobInfo` - `getTimeZone()` returns timezone job should run in + - `isForcedRun()`returns whether job was run via $scheduler->runJob() or scheduler:run-job command, ignoring the cron expression ### Changed diff --git a/docs/README.md b/docs/README.md index 021f67c..9814a91 100644 --- a/docs/README.md +++ b/docs/README.md @@ -356,6 +356,7 @@ $errorHandler = function(Throwable $throwable, JobInfo $info, JobResult $result) 'runSecond' => $info->getRunSecond(), 'start' => $info->getStart()->format(DateTimeInterface::ATOM), 'end' => $result->getEnd()->format(DateTimeInterface::ATOM), + 'forcedRun' => $info->isForcedRun(), ]); }, $scheduler = new SimpleScheduler($errorHandler); @@ -602,6 +603,7 @@ $timeZone = $info->getTimeZone(); // DateTimeZone|null $extendedExpression = $info->getExtendedExpression(); // string, e.g. '* * * * * / 30 (Europe/Prague)' $runSecond = $info->getRunSecond(); // int $start = $info->getStart(); // DateTimeImmutable +$forcedRun = $info->isForcedRun(); // bool, happens when running job via $scheduler->runJob() or scheduler:run-job command, ignoring the cron expression ``` Result: diff --git a/src/Executor/ProcessJobExecutor.php b/src/Executor/ProcessJobExecutor.php index 80c9470..cd5a1fc 100644 --- a/src/Executor/ProcessJobExecutor.php +++ b/src/Executor/ProcessJobExecutor.php @@ -82,7 +82,7 @@ public function runJobs( $jobExecutions = $this->startJobs( $jobSchedulesBySecond[$currentSecond], $jobExecutions, - new RunParameters($currentSecond), + new RunParameters($currentSecond, false), ); unset($jobSchedulesBySecond[$currentSecond]); } @@ -182,6 +182,7 @@ private function createSummary(array $raw, JobSchedule $jobSchedule): JobSummary $raw['info']['runSecond'], DateTimeImmutable::createFromFormat('U.u e', $raw['info']['start']), $jobSchedule->getTimeZone(), + $raw['info']['forcedRun'], ), new JobResult( $jobSchedule->getExpression(), diff --git a/src/ManagedScheduler.php b/src/ManagedScheduler.php index 5bbe453..5e5d87c 100644 --- a/src/ManagedScheduler.php +++ b/src/ManagedScheduler.php @@ -86,7 +86,7 @@ public function __construct( fn ($id, JobSchedule $jobSchedule, int $runSecond): array => $this->runInternal( $id, $jobSchedule, - $runSecond, + new RunParameters($runSecond, false), ), ); } @@ -99,7 +99,7 @@ public function getJobSchedules(): array public function runJob($id, bool $force = true, ?RunParameters $parameters = null): ?JobSummary { $jobSchedule = $this->jobManager->getJobSchedule($id); - $parameters ??= new RunParameters(0); + $parameters ??= new RunParameters(0, $force); if ($jobSchedule === null) { $message = Message::create() @@ -126,7 +126,7 @@ public function runJob($id, bool $force = true, ?RunParameters $parameters = nul return null; } - [$summary, $throwable] = $this->runInternal($id, $jobSchedule, $parameters->getSecond()); + [$summary, $throwable] = $this->runInternal($id, $jobSchedule, $parameters); if ($throwable !== null) { throw JobFailure::create($summary, $throwable); @@ -238,10 +238,9 @@ public function run(): RunSummary /** * @param string|int $id - * @param int<0, max> $runSecond * @return array{JobSummary, Throwable|null} */ - private function runInternal($id, JobSchedule $jobSchedule, int $runSecond): array + private function runInternal($id, JobSchedule $jobSchedule, RunParameters $runParameters): array { $job = $jobSchedule->getJob(); $expression = $jobSchedule->getExpression(); @@ -251,9 +250,10 @@ private function runInternal($id, JobSchedule $jobSchedule, int $runSecond): arr $job->getName(), $expression->getExpression(), $jobSchedule->getRepeatAfterSeconds(), - $runSecond, + $runParameters->getSecond(), $this->getCurrentTime($jobSchedule), $jobSchedule->getTimeZone(), + $runParameters->isForcedRun(), ); $lock = $this->lockFactory->createLock("Orisai.Scheduler.Job/$id"); diff --git a/src/Status/JobInfo.php b/src/Status/JobInfo.php index d26b397..eecaf95 100644 --- a/src/Status/JobInfo.php +++ b/src/Status/JobInfo.php @@ -25,6 +25,8 @@ final class JobInfo private ?DateTimeZone $timeZone; + private bool $forcedRun; + /** * @param string|int $id * @param int<0, 30> $repeatAfterSeconds @@ -37,7 +39,8 @@ public function __construct( int $repeatAfterSeconds, int $runSecond, DateTimeImmutable $start, - ?DateTimeZone $timeZone + ?DateTimeZone $timeZone, + bool $forcedRun ) { $this->id = $id; @@ -47,6 +50,7 @@ public function __construct( $this->runSecond = $runSecond; $this->start = $start; $this->timeZone = $timeZone; + $this->forcedRun = $forcedRun; } /** @@ -111,6 +115,11 @@ public function getTimeZone(): ?DateTimeZone return $this->timeZone; } + public function isForcedRun(): bool + { + return $this->forcedRun; + } + /** * @return array */ @@ -123,6 +132,7 @@ public function toArray(): array 'repeatAfterSeconds' => $this->getRepeatAfterSeconds(), 'runSecond' => $this->getRunSecond(), 'start' => $this->getStart()->format('U.u e'), + 'forcedRun' => $this->forcedRun, ]; } diff --git a/src/Status/RunParameters.php b/src/Status/RunParameters.php index ff6a0db..1c5f34c 100644 --- a/src/Status/RunParameters.php +++ b/src/Status/RunParameters.php @@ -11,12 +11,15 @@ final class RunParameters /** @var int<0, max> */ private int $second; + private bool $forcedRun; + /** * @param int<0, max> $second */ - public function __construct(int $second) + public function __construct(int $second, bool $forcedRun) { $this->second = $second; + $this->forcedRun = $forcedRun; } /** @@ -24,7 +27,7 @@ public function __construct(int $second) */ public static function fromArray(array $raw): self { - return new self($raw['second']); + return new self($raw['second'], $raw['forcedRun']); } /** @@ -35,6 +38,11 @@ public function getSecond(): int return $this->second; } + public function isForcedRun(): bool + { + return $this->forcedRun; + } + /** * @return array */ @@ -42,6 +50,7 @@ public function toArray(): array { return [ 'second' => $this->second, + 'forcedRun' => $this->forcedRun, ]; } diff --git a/tests/Unit/Command/RunCommandTest.php b/tests/Unit/Command/RunCommandTest.php index bc18029..eaa6c64 100644 --- a/tests/Unit/Command/RunCommandTest.php +++ b/tests/Unit/Command/RunCommandTest.php @@ -106,7 +106,8 @@ public function testSuccess(): void "expression": "* * * * *", "repeatAfterSeconds": 0, "runSecond": 0, - "start": "1.000000 Europe\/Prague" + "start": "1.000000 Europe\/Prague", + "forcedRun": false }, "result": { "end": "1.000000 Europe\/Prague", @@ -120,7 +121,8 @@ public function testSuccess(): void "expression": "* * * * *", "repeatAfterSeconds": 0, "runSecond": 0, - "start": "1.000000 UTC" + "start": "1.000000 UTC", + "forcedRun": false }, "result": { "end": "1.000000 UTC", @@ -182,7 +184,8 @@ public function testFailure(): void "expression": "* * * * *", "repeatAfterSeconds": 0, "runSecond": 0, - "start": "1.000000 Europe\/Prague" + "start": "1.000000 Europe\/Prague", + "forcedRun": false }, "result": { "end": "1.000000 Europe\/Prague", @@ -196,7 +199,8 @@ public function testFailure(): void "expression": "* * * * *", "repeatAfterSeconds": 0, "runSecond": 0, - "start": "1.000000 Europe\/Prague" + "start": "1.000000 Europe\/Prague", + "forcedRun": false }, "result": { "end": "1.000000 Europe\/Prague", diff --git a/tests/Unit/Command/RunJobCommandTest.php b/tests/Unit/Command/RunJobCommandTest.php index f245b4a..49ad308 100644 --- a/tests/Unit/Command/RunJobCommandTest.php +++ b/tests/Unit/Command/RunJobCommandTest.php @@ -240,7 +240,7 @@ public function testJson(): void $tester->execute([ 'id' => 0, '--json' => true, - '--parameters' => json_encode((new RunParameters(30))->toArray(), JSON_THROW_ON_ERROR), + '--parameters' => json_encode((new RunParameters(30, false))->toArray(), JSON_THROW_ON_ERROR), ]); self::assertSame( @@ -252,7 +252,8 @@ public function testJson(): void "expression": "1 * * * *", "repeatAfterSeconds": 0, "runSecond": 30, - "start": "61.000000 Europe\/Prague" + "start": "61.000000 Europe\/Prague", + "forcedRun": false }, "result": { "end": "61.000000 Europe\/Prague", @@ -311,7 +312,8 @@ public function testEchoingJob(): void "expression": "* * * * *", "repeatAfterSeconds": 0, "runSecond": 0, - "start": "1.000000 Europe\/Prague" + "start": "1.000000 Europe\/Prague", + "forcedRun": true }, "result": { "end": "1.000000 Europe\/Prague", diff --git a/tests/Unit/Exception/JobFailureTest.php b/tests/Unit/Exception/JobFailureTest.php index 54aa234..9d7195b 100644 --- a/tests/Unit/Exception/JobFailureTest.php +++ b/tests/Unit/Exception/JobFailureTest.php @@ -17,7 +17,7 @@ final class JobFailureTest extends TestCase public function test(): void { - $info = new JobInfo('id', 'name', '* * * * *', 0, 0, new DateTimeImmutable(), null); + $info = new JobInfo('id', 'name', '* * * * *', 0, 0, new DateTimeImmutable(), null, false); $result = new JobResult( new CronExpression('* * * * *'), new DateTimeImmutable(), diff --git a/tests/Unit/SimpleSchedulerTest.php b/tests/Unit/SimpleSchedulerTest.php index c89b19a..a59da01 100644 --- a/tests/Unit/SimpleSchedulerTest.php +++ b/tests/Unit/SimpleSchedulerTest.php @@ -258,8 +258,18 @@ public function testJobEvents(): void 0, $now, null, + false, + ), + new JobInfo( + 1, + 'Tests\Orisai\Scheduler\Doubles\CallbackList::job1()', + '* * * * *', + 0, + 0, + $now, + null, + false, ), - new JobInfo(1, 'Tests\Orisai\Scheduler\Doubles\CallbackList::job1()', '* * * * *', 0, 0, $now, null), ], $beforeCollected, ); @@ -275,6 +285,7 @@ public function testJobEvents(): void 0, $now, null, + false, ), new JobResult(new CronExpression('* * * * *'), $now, JobResultState::fail()), ], @@ -287,6 +298,7 @@ public function testJobEvents(): void 0, $now, null, + false, ), new JobResult(new CronExpression('* * * * *'), $now, JobResultState::done()), ], @@ -337,6 +349,7 @@ static function () use ($clock): void { 0, DateTimeImmutable::createFromFormat('U', '1'), null, + false, ), ], $beforeCollected, @@ -352,6 +365,7 @@ static function () use ($clock): void { 0, DateTimeImmutable::createFromFormat('U', '1'), null, + false, ), new JobResult( new CronExpression('* * * * *'), @@ -602,6 +616,7 @@ public function testRunSummary(): void 0, $before, null, + false, ), new JobResult(new CronExpression('* * * * *'), $before, JobResultState::done()), ), @@ -614,6 +629,7 @@ public function testRunSummary(): void 0, $before, null, + false, ), new JobResult(new CronExpression('* * * * *'), $after, JobResultState::done()), ), @@ -650,6 +666,7 @@ public function testJobSummary(?RunParameters $parameters, int $second): void $second, $now, null, + $parameters !== null ? $parameters->isForcedRun() : true, ), $summary->getInfo(), ); @@ -662,8 +679,8 @@ public function testJobSummary(?RunParameters $parameters, int $second): void public function provideJobSummary(): Generator { yield [null, 0]; - yield [new RunParameters(10), 10]; - yield [new RunParameters(30), 30]; + yield [new RunParameters(10, false), 10]; + yield [new RunParameters(30, true), 30]; } public function testTimeZoneExecution(): void @@ -777,11 +794,11 @@ static function () use (&$i2): void { self::assertEquals( [ new JobSummary( - new JobInfo(0, 'job1', '* * * * *', 0, 0, $clock->now(), null), + new JobInfo(0, 'job1', '* * * * *', 0, 0, $clock->now(), null, false), new JobResult(new CronExpression('* * * * *'), $clock->now(), JobResultState::lock()), ), new JobSummary( - new JobInfo(1, 'job2', '* * * * *', 0, 0, $clock->now(), null), + new JobInfo(1, 'job2', '* * * * *', 0, 0, $clock->now(), null, false), new JobResult(new CronExpression('* * * * *'), $clock->now(), JobResultState::done()), ), ], @@ -810,11 +827,11 @@ static function () use (&$i2): void { self::assertEquals( [ new JobSummary( - new JobInfo(0, 'job1', '* * * * *', 0, 0, $clock->now(), null), + new JobInfo(0, 'job1', '* * * * *', 0, 0, $clock->now(), null, false), new JobResult(new CronExpression('* * * * *'), $clock->now(), JobResultState::done()), ), new JobSummary( - new JobInfo(1, 'job2', '* * * * *', 0, 0, $clock->now(), null), + new JobInfo(1, 'job2', '* * * * *', 0, 0, $clock->now(), null, false), new JobResult(new CronExpression('* * * * *'), $clock->now(), JobResultState::done()), ), ], @@ -984,6 +1001,7 @@ public function testLockedJobEvent(): void 0, $now, null, + false, ), new JobResult(new CronExpression('* * * * *'), $now, JobResultState::lock()), ], diff --git a/tests/Unit/Status/JobInfoTest.php b/tests/Unit/Status/JobInfoTest.php index 0fb470e..d87ffc5 100644 --- a/tests/Unit/Status/JobInfoTest.php +++ b/tests/Unit/Status/JobInfoTest.php @@ -26,10 +26,11 @@ public function test( int $runSecond, DateTimeImmutable $start, ?DateTimeZone $timeZone, - string $extendedExpression + string $extendedExpression, + bool $forcedRun ): void { - $info = new JobInfo($id, $name, $expression, $repeatAfterSeconds, $runSecond, $start, $timeZone); + $info = new JobInfo($id, $name, $expression, $repeatAfterSeconds, $runSecond, $start, $timeZone, $forcedRun); self::assertSame($id, $info->getId()); self::assertSame($name, $info->getName()); self::assertSame($expression, $info->getExpression()); @@ -38,6 +39,7 @@ public function test( self::assertSame($extendedExpression, $info->getExtendedExpression()); self::assertSame($runSecond, $info->getRunSecond()); self::assertSame($start, $info->getStart()); + self::assertSame($forcedRun, $info->isForcedRun()); self::assertSame( [ @@ -47,6 +49,7 @@ public function test( 'repeatAfterSeconds' => $repeatAfterSeconds, 'runSecond' => $runSecond, 'start' => $start->format('U.u e'), + 'forcedRun' => $forcedRun, ], $info->toArray(), ); @@ -63,6 +66,7 @@ public function provide(): Generator new DateTimeImmutable(), null, '* * * * *', + true, ]; yield [ @@ -74,6 +78,7 @@ public function provide(): Generator new DateTimeImmutable(), null, '* * * * */5 / 10', + true, ]; yield [ @@ -85,6 +90,7 @@ public function provide(): Generator new DateTimeImmutable(), new DateTimeZone('Europe/Prague'), '* * 6 9 * (Europe/Prague)', + false, ]; yield [ @@ -96,6 +102,7 @@ public function provide(): Generator new DateTimeImmutable(), new DateTimeZone('UTC'), '* 1 9 8 4 / 30 (UTC)', + false, ]; } diff --git a/tests/Unit/Status/JobSummaryTest.php b/tests/Unit/Status/JobSummaryTest.php index 89d4518..1cca065 100644 --- a/tests/Unit/Status/JobSummaryTest.php +++ b/tests/Unit/Status/JobSummaryTest.php @@ -15,7 +15,7 @@ final class JobSummaryTest extends TestCase public function test(): void { - $info = new JobInfo('id', 'name', '* * * * *', 0, 0, new DateTimeImmutable(), null); + $info = new JobInfo('id', 'name', '* * * * *', 0, 0, new DateTimeImmutable(), null, false); $result = new JobResult( new CronExpression('* * * * *'), new DateTimeImmutable(), diff --git a/tests/Unit/Status/RunParametersTest.php b/tests/Unit/Status/RunParametersTest.php index e792a86..09d6d22 100644 --- a/tests/Unit/Status/RunParametersTest.php +++ b/tests/Unit/Status/RunParametersTest.php @@ -2,19 +2,31 @@ namespace Tests\Orisai\Scheduler\Unit\Status; +use Generator; use Orisai\Scheduler\Status\RunParameters; use PHPUnit\Framework\TestCase; final class RunParametersTest extends TestCase { - public function test(): void + /** + * @param int<0, max> $second + * + * @dataProvider provide + */ + public function test(int $second, bool $forcedRun): void { - $second = 1; - $parameters = new RunParameters($second); + $parameters = new RunParameters($second, $forcedRun); self::assertSame($second, $parameters->getSecond()); + self::assertSame($forcedRun, $parameters->isForcedRun()); self::assertEquals($parameters, RunParameters::fromArray($parameters->toArray())); } + public function provide(): Generator + { + yield [1, false]; + yield [10, true]; + } + } diff --git a/tests/Unit/Status/RunSummaryTest.php b/tests/Unit/Status/RunSummaryTest.php index 4203ca5..25face4 100644 --- a/tests/Unit/Status/RunSummaryTest.php +++ b/tests/Unit/Status/RunSummaryTest.php @@ -20,11 +20,11 @@ public function test(): void $end = new DateTimeImmutable(); $jobSummaries = [ new JobSummary( - new JobInfo('id', '1', '* * * * *', 0, 0, new DateTimeImmutable(), null), + new JobInfo('id', '1', '* * * * *', 0, 0, new DateTimeImmutable(), null, false), new JobResult(new CronExpression('* * * * *'), new DateTimeImmutable(), JobResultState::done()), ), new JobSummary( - new JobInfo('id', '2', '1 * * * *', 5, 10, new DateTimeImmutable(), null), + new JobInfo('id', '2', '1 * * * *', 5, 10, new DateTimeImmutable(), null, false), new JobResult(new CronExpression('1 * * * *'), new DateTimeImmutable(), JobResultState::done()), ), ];