Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store schedule monitoring configurations in its own singleton #114

Merged
merged 9 commits into from
Jan 6, 2025
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
php: [8.2, 8.1, 8.0]
php: [8.4, 8.3, 8.2, 8.1]
laravel: ['9.*', '10.*', '11.*']
stability: [prefer-lowest, prefer-stable]
include:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
}
],
"require": {
"php": "^8.0",
"php": "^8.1",
"illuminate/bus": "^9.0|^10.0|^11.0",
"lorisleiva/cron-translator": "^0.3.0|^0.4.0",
"nesbot/carbon": "^2.63|^3.0",
Expand Down
4 changes: 3 additions & 1 deletion src/Models/MonitoredScheduledTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
use Illuminate\Support\Str;
use OhDear\PhpSdk\Resources\CronCheck;
use Spatie\ScheduleMonitor\Jobs\PingOhDearJob;
use Spatie\ScheduleMonitor\Support\Concerns\UsesMonitoredScheduledTasks;
use Spatie\ScheduleMonitor\Support\Concerns\UsesScheduleMonitoringModels;
use Spatie\ScheduleMonitor\Support\ScheduledTasks\ScheduledTaskFactory;

class MonitoredScheduledTask extends Model
{
use UsesScheduleMonitoringModels;
use UsesMonitoredScheduledTasks;
use HasFactory;

public $guarded = [];
Expand Down Expand Up @@ -205,7 +207,7 @@ public function createLogItem(string $type): MonitoredScheduledTaskLogItem
*/
public function getEventTaskOutput($event): ?string
{
if (! ($event->task->storeOutputInDb ?? false)) {
if (! ($this->getMonitoredScheduledTasks()->getStoreOutputInDb($event->task) ?? false)) {
return null;
}

Expand Down
30 changes: 19 additions & 11 deletions src/ScheduleMonitorServiceProvider.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php

namespace Spatie\ScheduleMonitor;

use Illuminate\Console\Events\CommandStarting;
use Illuminate\Console\Scheduling\Event as SchedulerEvent;
use Illuminate\Support\Facades\Event;
Expand All @@ -18,6 +17,7 @@
use Spatie\ScheduleMonitor\Jobs\PingOhDearJob;
use Spatie\ScheduleMonitor\Models\MonitoredScheduledTask;
use Spatie\ScheduleMonitor\Models\MonitoredScheduledTaskLogItem;
use Spatie\ScheduleMonitor\Support\ScheduledTasks\MonitoredScheduledTasks;

class ScheduleMonitorServiceProvider extends PackageServiceProvider
{
Expand Down Expand Up @@ -116,32 +116,40 @@ protected function registerEventHandlers(): self

protected function registerSchedulerEventMacros(): self
{
SchedulerEvent::macro('monitorName', function (string $monitorName) {
$this->monitorName = $monitorName;
$this->app->singleton(
MonitoredScheduledTasks::class,
fn () => new MonitoredScheduledTasks(),
);

/** @var MonitoredScheduledTasks $monitoredScheduledTasks */
$monitoredScheduledTasks = $this->app->make(MonitoredScheduledTasks::class);

SchedulerEvent::macro('monitorName', function (string $monitorName) use ($monitoredScheduledTasks) {
$monitoredScheduledTasks->setMonitorName($this, $monitorName);

return $this;
});

SchedulerEvent::macro('graceTimeInMinutes', function (int $graceTimeInMinutes) {
$this->graceTimeInMinutes = $graceTimeInMinutes;
SchedulerEvent::macro('graceTimeInMinutes', function (int $graceTimeInMinutes) use ($monitoredScheduledTasks) {
$monitoredScheduledTasks->setGraceTimeInMinutes($this, $graceTimeInMinutes);

return $this;
});

SchedulerEvent::macro('doNotMonitor', function (bool $bool = true) {
$this->doNotMonitor = $bool;
SchedulerEvent::macro('doNotMonitor', function (bool $bool = true) use ($monitoredScheduledTasks) {
$monitoredScheduledTasks->setDoNotMonitor($this, $bool);

return $this;
});

SchedulerEvent::macro('doNotMonitorAtOhDear', function (bool $bool = true) {
$this->doNotMonitorAtOhDear = $bool;
SchedulerEvent::macro('doNotMonitorAtOhDear', function (bool $bool = true) use ($monitoredScheduledTasks) {
$monitoredScheduledTasks->setDoNotMonitorAtOhDear($this, $bool);

return $this;
});

SchedulerEvent::macro('storeOutputInDb', function () {
$this->storeOutputInDb = true;
SchedulerEvent::macro('storeOutputInDb', function (bool $bool = true) use ($monitoredScheduledTasks) {
$monitoredScheduledTasks->setStoreOutputInDb($this, $bool);
/** @psalm-suppress UndefinedMethod */
$this->ensureOutputIsBeingCaptured();

Expand Down
13 changes: 13 additions & 0 deletions src/Support/Concerns/UsesMonitoredScheduledTasks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Spatie\ScheduleMonitor\Support\Concerns;

use Spatie\ScheduleMonitor\Support\ScheduledTasks\MonitoredScheduledTasks;

trait UsesMonitoredScheduledTasks
{
public function getMonitoredScheduledTasks(): MonitoredScheduledTasks
{
return app(MonitoredScheduledTasks::class);
}
}
91 changes: 91 additions & 0 deletions src/Support/ScheduledTasks/MonitoredScheduledTasks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Spatie\ScheduleMonitor\Support\ScheduledTasks;

class MonitoredScheduledTasks
{
/**
* Multidimensional array to hold values grouped by class, instance id and property.
*
* Example:
*
* ```
* [ '\Illuminate\Console\Scheduling\Event' => 'obj_234' => [ 'propertyName' => 'some_value' ]]]
* ```
*
* @see self::makeKey()
*
* @var array<string,array<string,array<string,mixed>>>
*/
protected array $store = [];

public function setMonitorName(object $target, string $monitorName): void
{
$this->setProperty($target, 'monitorName', $monitorName);
}

public function getMonitorName(object $target): ?string
{
return $this->getProperty($target, 'monitorName');
}

public function setGraceTimeInMinutes(object $target, int $graceTimeInMinutes): void
{
$this->setProperty($target, 'graceTimeInMinutes', $graceTimeInMinutes);
}

public function getGraceTimeInMinutes(object $target): ?int
{
return $this->getProperty($target, 'graceTimeInMinutes');
}

public function setDoNotMonitor(object $target, bool $doNotMonitor = true): void
{
$this->setProperty($target, 'doNotMonitor', $doNotMonitor);
}

public function getDoNotMonitor(object $target): ?bool
{
return $this->getProperty($target, 'doNotMonitor');
}

public function setDoNotMonitorAtOhDear(object $target, bool $doNotMonitorAtOhDear = true): void
{
$this->setProperty($target, 'doNotMonitorAtOhDear', $doNotMonitorAtOhDear);
}

public function getDoNotMonitorAtOhDear(object $target): ?bool
{
return $this->getProperty($target, 'doNotMonitorAtOhDear');
}

public function setStoreOutputInDb(object $target, bool $storeOutputInDb = true): void
{
$this->setProperty($target, 'storeOutputInDb', $storeOutputInDb);
}

public function getStoreOutputInDb(object $target): ?bool
{
return $this->getProperty($target, 'storeOutputInDb');
}


protected function setProperty(object $target, string $key, mixed $value): void
{
data_set($this->store, $this->makeKey($target, $key), $value);
}

protected function getProperty(object $target, string $key): mixed
{
return data_get($this->store, $this->makeKey($target, $key));
}

protected function makeKey(object $target, string $key): array
{
return [
$target::class,
spl_object_hash($target),
$key,
];
}
}
20 changes: 14 additions & 6 deletions src/Support/ScheduledTasks/Tasks/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
use Lorisleiva\CronTranslator\CronParsingException;
use Lorisleiva\CronTranslator\CronTranslator;
use Spatie\ScheduleMonitor\Models\MonitoredScheduledTask;
use Spatie\ScheduleMonitor\Support\Concerns\UsesMonitoredScheduledTasks;
use Spatie\ScheduleMonitor\Support\Concerns\UsesScheduleMonitoringModels;

abstract class Task
{
use UsesScheduleMonitoringModels;
use UsesMonitoredScheduledTasks;

protected Event $event;

Expand Down Expand Up @@ -46,16 +48,19 @@ public function uniqueId(): string

public function name(): ?string
{
return $this->event->monitorName ?? $this->defaultName();
return $this->getMonitoredScheduledTasks()->getMonitorName($this->event)
?? $this->defaultName();
}

public function shouldMonitor(): bool
{
if (! isset($this->event->doNotMonitor)) {
$doNotMonitor = $this->getMonitoredScheduledTasks()
->getDoNotMonitor($this->event);
if (! isset($doNotMonitor)) {
return true;
}

return ! $this->event->doNotMonitor;
return ! $doNotMonitor;
}

public function isBeingMonitored(): bool
Expand All @@ -65,11 +70,13 @@ public function isBeingMonitored(): bool

public function shouldMonitorAtOhDear(): bool
{
if (! isset($this->event->doNotMonitorAtOhDear)) {
$doNotMonitorAtOhDear = $this->getMonitoredScheduledTasks()
->getDoNotMonitorAtOhDear($this->event);
if (! isset($doNotMonitorAtOhDear)) {
return true;
}

return ! $this->event->doNotMonitorAtOhDear;
return ! $doNotMonitorAtOhDear;
}

public function isBeingMonitoredAtOhDear(): bool
Expand Down Expand Up @@ -163,7 +170,8 @@ public function lastRunFailed(): bool

public function graceTimeInMinutes()
{
return $this->event->graceTimeInMinutes ?? config('schedule-monitor.oh_dear.grace_time_in_minutes', 5);
return $this->getMonitoredScheduledTasks()->getGraceTimeInMinutes($this->event)
?? config('schedule-monitor.oh_dear.grace_time_in_minutes', 5);
}

public function cronExpression(): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
->monitorName('failing-task');
});


$this->artisan(SyncCommand::class)->assertExitCode(0);
$this->artisan('schedule:run')->assertExitCode(0);

Expand Down
2 changes: 1 addition & 1 deletion tests/Support/ScheduledTasksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

it('can get only the tasks that run in the current environment from the schedule', function () {
TestKernel::registerScheduledTasks(function (Schedule $schedule) {
$schedule->command('dummy')->environments('testing'); // current
$schedule->command('dummy')->environments(config('app.env', 'testing')); // current
$schedule->command('other-dummy')->environments('production');
});

Expand Down
14 changes: 14 additions & 0 deletions tests/Traits/UsesMonitoredScheduledTasksTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

use Spatie\ScheduleMonitor\Support\Concerns\UsesMonitoredScheduledTasks;
use Spatie\ScheduleMonitor\Support\ScheduledTasks\MonitoredScheduledTasks;

it('can resolve schedule monitoring configurations repository', function () {
$concern = new class() {
use UsesMonitoredScheduledTasks;
};

$repository = $concern->getMonitoredScheduledTasks();

expect($repository)->toBeInstanceOf(MonitoredScheduledTasks::class);
});
Loading