From d9af356e9ddb4cec4a9677e5b0b2dcbc4158fd4f Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Wed, 6 Sep 2023 12:09:23 +1000 Subject: [PATCH 1/3] Move updates to concern of the storage driver --- src/Entries/SlowJobFinished.php | 13 ------- src/Entries/Update.php | 5 --- src/PulseServiceProvider.php | 2 ++ src/Storage/Database.php | 49 ++++++++++++++++++++++++++- tests/Feature/DatabaseStorageTest.php | 42 +++++++++++++++++++++++ 5 files changed, 92 insertions(+), 19 deletions(-) create mode 100644 tests/Feature/DatabaseStorageTest.php diff --git a/src/Entries/SlowJobFinished.php b/src/Entries/SlowJobFinished.php index 1d152a9f..1765a1df 100644 --- a/src/Entries/SlowJobFinished.php +++ b/src/Entries/SlowJobFinished.php @@ -19,19 +19,6 @@ public function __construct( // } - /** - * Perform the update. - */ - public function perform(Connection $db): void - { - $db->table($this->table()) - ->where('job_uuid', $this->jobUuid) - ->update([ - 'slowest' => $db->raw("COALESCE(GREATEST(`slowest`,{$this->duration}),{$this->duration})"), - 'slow' => $db->raw('`slow` + 1'), - ]); - } - /** * The update's table. */ diff --git a/src/Entries/Update.php b/src/Entries/Update.php index 61171b71..590ef466 100644 --- a/src/Entries/Update.php +++ b/src/Entries/Update.php @@ -11,11 +11,6 @@ abstract class Update */ abstract public function table(): string; - /** - * Perform the update. - */ - abstract public function perform(Connection $db): void; - /** * Resolve the update for ingest and storage. */ diff --git a/src/PulseServiceProvider.php b/src/PulseServiceProvider.php index 9a0d67b8..ca75d2be 100644 --- a/src/PulseServiceProvider.php +++ b/src/PulseServiceProvider.php @@ -52,6 +52,8 @@ public function register(): void } $this->app->singleton(Pulse::class); + $this->app->singleton(DatabaseStorage::class); + $this->app->singleton(RedisIngest::class); $this->app->bind(Storage::class, DatabaseStorage::class); diff --git a/src/Storage/Database.php b/src/Storage/Database.php index a20de09a..72d800a5 100644 --- a/src/Storage/Database.php +++ b/src/Storage/Database.php @@ -4,16 +4,26 @@ use Carbon\CarbonImmutable; use Carbon\CarbonInterval as Interval; +use Closure; use Illuminate\Config\Repository; use Illuminate\Database\Connection; use Illuminate\Database\DatabaseManager; use Illuminate\Support\Collection; +use Illuminate\Support\Traits\ReflectsClosures; use Laravel\Pulse\Contracts\Storage; use Laravel\Pulse\Entries\Entry; +use Laravel\Pulse\Entries\SlowJobFinished; use Laravel\Pulse\Entries\Update; class Database implements Storage { + use ReflectsClosures; + + /** + * Additional storage update handlers. + */ + protected array $updateHandlers = []; + /** * Create a new Database storage instance. */ @@ -24,6 +34,20 @@ public function __construct( // } + /** + * Handle the update using the closure. + * + * @param (callable(Update): void) $callback + */ + public function handleUpdateUsing($callback): self + { + foreach ($this->firstClosureParameterTypes(Closure::fromCallable($callback)) as $class) { + $this->updateHandlers[$class] = $callback; + } + + return $this; + } + /** * Store the entries and updates. * @@ -43,7 +67,30 @@ public function store(Collection $items): void ->map(fn (Collection $inserts) => $inserts->pluck('attributes')->all()) ->each($this->connection()->table($table)->insert(...))); - $updates->each(fn (Update $update) => $update->perform($this->connection())); + $this->perform($updates); + }); + } + + /** + * Perform the given updates. + */ + protected function perform($updates) + { + $updates->each(function (Update $update) { + if ($this->updateHandlers[$update::class] ?? false) { + $this->updateHandlers[$update::class]($update); + + return; + } + + if ($update instanceof SlowJobFinished) { + $this->connection()->table($update->table()) + ->where('job_uuid', $update->jobUuid) + ->update([ + 'slowest' => $this->connection()->raw("COALESCE(GREATEST(`slowest`,{$update->duration}),{$update->duration})"), + 'slow' => $this->connection()->raw('`slow` + 1'), + ]); + } }); } diff --git a/tests/Feature/DatabaseStorageTest.php b/tests/Feature/DatabaseStorageTest.php new file mode 100644 index 00000000..bf21df0e --- /dev/null +++ b/tests/Feature/DatabaseStorageTest.php @@ -0,0 +1,42 @@ +store(collect([ + new Entry('pulse_jobs', [ + 'date' => now()->toDateTimeString(), + 'job' => 'MyJob', + 'job_uuid' => 'job-uuid', + 'user_id' => '55' + ]), + ])); + + $storage->store(collect([ + new SlowJobFinished('job-uuid', 456) + ])); + + $jobs = DB::table('pulse_jobs')->get(); + $this->assertCount(1, $jobs); + $this->assertSame(1, $jobs[0]->slow); + $this->assertSame(456, $jobs[0]->slowest); +}); + +it('allows custom update handlers', function () { + $captured = null; + App::make(Database::class)->handleUpdateUsing(function (SlowJobFinished $update) use (&$captured) { + $captured = $update; + }); + + $update = new SlowJobFinished('job-uuid', 321); + App::make(Database::class)->store(collect([$update])); // resolve again to ensure that the handlers persist across different resolves from container. + + $this->assertSame($update, $captured); +}); From 7de395f01ad82cc2c0e7e13a0d0c2f3867894092 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Wed, 6 Sep 2023 12:14:26 +1000 Subject: [PATCH 2/3] Expose connection methods --- src/Ingests/Redis.php | 2 +- src/Storage/Database.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ingests/Redis.php b/src/Ingests/Redis.php index 2f2e9c42..f8242dc0 100644 --- a/src/Ingests/Redis.php +++ b/src/Ingests/Redis.php @@ -90,7 +90,7 @@ protected function trimAfter(): Interval /** * Get the redis connection. */ - protected function connection(): RedisAdapter + public function connection(): RedisAdapter { return new RedisAdapter($this->config, $this->manager->connection( $this->config->get('pulse.ingest.redis.connection') diff --git a/src/Storage/Database.php b/src/Storage/Database.php index 72d800a5..4fde727f 100644 --- a/src/Storage/Database.php +++ b/src/Storage/Database.php @@ -116,7 +116,7 @@ protected function trimAfter(): Interval /** * Get the database connection. */ - protected function connection(): Connection + public function connection(): Connection { return $this->manager->connection( $this->config->get('pulse.storage.database.connection') ?? $this->config->get('database.default') From a3258ca4cc1da68991251d453a2120768927a2e1 Mon Sep 17 00:00:00 2001 From: timacdonald Date: Wed, 6 Sep 2023 02:15:28 +0000 Subject: [PATCH 3/3] Fix code styling --- src/Commands/CheckCommand.php | 2 +- src/Commands/WorkCommand.php | 2 +- src/Entries/SlowJobFinished.php | 2 -- src/Entries/Update.php | 2 -- tests/Feature/DatabaseStorageTest.php | 5 ++--- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Commands/CheckCommand.php b/src/Commands/CheckCommand.php index c8a3dfe1..a09e2394 100644 --- a/src/Commands/CheckCommand.php +++ b/src/Commands/CheckCommand.php @@ -48,7 +48,7 @@ public function handle( while (true) { $now = new CarbonImmutable(); - if ($cache->get('laravel:pulse:restart') !== $lastRestart) { + if ($lastRestart !== $cache->get('laravel:pulse:restart')) { return self::SUCCESS; } diff --git a/src/Commands/WorkCommand.php b/src/Commands/WorkCommand.php index 6225ec53..5a86431d 100644 --- a/src/Commands/WorkCommand.php +++ b/src/Commands/WorkCommand.php @@ -44,7 +44,7 @@ public function handle( while (true) { $now = new CarbonImmutable; - if ($cache->get('laravel:pulse:restart') !== $lastRestart) { + if ($lastRestart !== $cache->get('laravel:pulse:restart')) { return self::SUCCESS; } diff --git a/src/Entries/SlowJobFinished.php b/src/Entries/SlowJobFinished.php index 1765a1df..f1098678 100644 --- a/src/Entries/SlowJobFinished.php +++ b/src/Entries/SlowJobFinished.php @@ -2,8 +2,6 @@ namespace Laravel\Pulse\Entries; -use Illuminate\Database\Connection; - /** * @internal */ diff --git a/src/Entries/Update.php b/src/Entries/Update.php index 590ef466..672b3964 100644 --- a/src/Entries/Update.php +++ b/src/Entries/Update.php @@ -2,8 +2,6 @@ namespace Laravel\Pulse\Entries; -use Illuminate\Database\Connection; - abstract class Update { /** diff --git a/tests/Feature/DatabaseStorageTest.php b/tests/Feature/DatabaseStorageTest.php index bf21df0e..daea5f5c 100644 --- a/tests/Feature/DatabaseStorageTest.php +++ b/tests/Feature/DatabaseStorageTest.php @@ -1,7 +1,6 @@ now()->toDateTimeString(), 'job' => 'MyJob', 'job_uuid' => 'job-uuid', - 'user_id' => '55' + 'user_id' => '55', ]), ])); $storage->store(collect([ - new SlowJobFinished('job-uuid', 456) + new SlowJobFinished('job-uuid', 456), ])); $jobs = DB::table('pulse_jobs')->get();