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
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 () use ($monitoredScheduledTasks) {
$monitoredScheduledTasks->setStoreOutputInDb($this, true);
/** @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 getScheduleMonitoringConfigurationsRepository(): MonitoredScheduledTasks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this to getMonitoredScheduledTasks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, missed this one.

✅ Renamed

{
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->getScheduleMonitoringConfigurationsRepository()->getMonitorName($this->event)
?? $this->defaultName();
}

public function shouldMonitor(): bool
{
if (! isset($this->event->doNotMonitor)) {
$doNotMonitor = $this->getScheduleMonitoringConfigurationsRepository()
->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->getScheduleMonitoringConfigurationsRepository()
->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->getScheduleMonitoringConfigurationsRepository()->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
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->getScheduleMonitoringConfigurationsRepository();

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