From 48edab013c5dcd38f040d8d9222161996707cdb5 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Wed, 6 Sep 2023 17:09:57 +1000 Subject: [PATCH 1/3] wip --- composer.json | 1 + src/Entry.php | 2 +- src/Update.php | 20 ++++++++++++++++- tests/Feature/RedisIngestTest.php | 32 ++++++++++++++++++++++++++ tests/StorageFake.php | 37 +++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 tests/Feature/RedisIngestTest.php create mode 100644 tests/StorageFake.php diff --git a/composer.json b/composer.json index a000c851..ba03244e 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "illuminate/http": "^9.0 || ^10.0", "illuminate/routing": "^9.0 || ^10.0", "illuminate/support": "^9.0 || ^10.0", + "laravel/serializable-closure": "^1.3", "livewire/livewire": "dev-main", "nesbot/carbon": "^2.67" }, diff --git a/src/Entry.php b/src/Entry.php index f2cc791e..1a755379 100644 --- a/src/Entry.php +++ b/src/Entry.php @@ -15,7 +15,7 @@ public function __construct(public string $table, public array $attributes) } /** - * Resolve the entry for ingest and storage. + * Resolve the entry for ingest. */ public function resolve(): self { diff --git a/src/Update.php b/src/Update.php index d02e2eef..b7f3770b 100644 --- a/src/Update.php +++ b/src/Update.php @@ -3,9 +3,12 @@ namespace Laravel\Pulse; use Closure; +use Laravel\SerializableClosure\SerializableClosure; class Update { + protected array|Closure|SerializableClosure $attributes; + /** * @param array $conditions * @param array|(\Closure(array): array) $attributes @@ -19,10 +22,25 @@ public function __construct( } /** - * Resolve the update for ingest and storage. + * Resolve the update for ingest. */ public function resolve(): self { return $this; } + + public function __sleep() + { + // + } + + public function __wakeup() + { + /// + } + + public function attributes() + { + // + } } diff --git a/tests/Feature/RedisIngestTest.php b/tests/Feature/RedisIngestTest.php new file mode 100644 index 00000000..f256cdfe --- /dev/null +++ b/tests/Feature/RedisIngestTest.php @@ -0,0 +1,32 @@ + 'unique-job-id', + ], function () use ($duration) { + return [ + 'slowest' => $duration, + ]; + }); + + $pulse->record($update); + $pulse->store($ingest); + $ingest->store($storage); + + expect($storage->stored)->toHaveCount(1); + expect($storage->stored[0])->toBeInstanceOf(Update::class); + expect($storage->stored[0])->not->toBe($update); + expect($storage->stored[0]->conditions)->toBe([ + 'job_uuid' => 'unique-job-id', + ]); +}); diff --git a/tests/StorageFake.php b/tests/StorageFake.php new file mode 100644 index 00000000..04af79cb --- /dev/null +++ b/tests/StorageFake.php @@ -0,0 +1,37 @@ + $items + */ + public function store(Collection $items): void + { + $this->stored = $this->stored->merge($items); + } + + /** + * Trim the stored entries from the given tables. + * + * @param \Illuminate\Support\Collection $tables + */ + public function trim(Collection $tables): void + { + // + } +} From 31bcc04e58ab78a53c946af6cd4a7018eab6f001 Mon Sep 17 00:00:00 2001 From: Jess Archer Date: Wed, 6 Sep 2023 17:45:02 +1000 Subject: [PATCH 2/3] Serialize closures --- src/Concerns/SerializesClosures.php | 33 +++++++++++++++++++++++++++++ src/Update.php | 19 ++--------------- 2 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/Concerns/SerializesClosures.php diff --git a/src/Concerns/SerializesClosures.php b/src/Concerns/SerializesClosures.php new file mode 100644 index 00000000..a23a3e30 --- /dev/null +++ b/src/Concerns/SerializesClosures.php @@ -0,0 +1,33 @@ + + */ + public function __serialize(): array + { + return array_map(function ($value) { + return $value instanceof Closure ? new SerializableClosure($value) : $value; + }, get_object_vars($this)); + } + + /** + * Restore the instance values after serialization. + * + * @param array $data + */ + public function __unserialize(array $data): void + { + foreach ($data as $key => $value) { + $this->{$key} = $value instanceof SerializableClosure ? $value->getClosure() : $value; + } + } +} diff --git a/src/Update.php b/src/Update.php index b7f3770b..2eb68550 100644 --- a/src/Update.php +++ b/src/Update.php @@ -3,11 +3,11 @@ namespace Laravel\Pulse; use Closure; -use Laravel\SerializableClosure\SerializableClosure; +use Laravel\Pulse\Concerns\SerializesClosures; class Update { - protected array|Closure|SerializableClosure $attributes; + use SerializesClosures; /** * @param array $conditions @@ -28,19 +28,4 @@ public function resolve(): self { return $this; } - - public function __sleep() - { - // - } - - public function __wakeup() - { - /// - } - - public function attributes() - { - // - } } From beec6b16955abd94295b429256029846f515bffe Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Thu, 7 Sep 2023 09:19:54 +1000 Subject: [PATCH 3/3] Update tests --- tests/Feature/RedisIngestTest.php | 109 +++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/tests/Feature/RedisIngestTest.php b/tests/Feature/RedisIngestTest.php index f256cdfe..42934b3e 100644 --- a/tests/Feature/RedisIngestTest.php +++ b/tests/Feature/RedisIngestTest.php @@ -6,7 +6,34 @@ use Laravel\Pulse\Update; use Tests\StorageFake; -it('can ingest an update with a closure with "use" variables', function () { +it('can ingest an update with a closure', function () { + $pulse = App::make(Pulse::class); + $ingest = App::make(Redis::class); + $storage = new StorageFake; + $update = new Update('pulse_jobs', [ + 'job_uuid' => 'unique-job-id', + ], function () { + return [ + 'slowest' => 66, + ]; + }); + + $pulse->record($update); + $pulse->store($ingest); + $ingest->store($storage); + + expect($storage->stored)->toHaveCount(1); + expect($storage->stored[0])->toBeInstanceOf(Update::class); + expect($storage->stored[0])->not->toBe($update); + expect($storage->stored[0]->conditions)->toBe([ + 'job_uuid' => 'unique-job-id', + ]); + expect(($storage->stored[0]->attributes)())->toBe([ + 'slowest' => 66, + ]); +}); + +it('can ingest an update with a closure using external scope', function () { $pulse = App::make(Pulse::class); $ingest = App::make(Redis::class); $storage = new StorageFake; @@ -29,4 +56,84 @@ expect($storage->stored[0]->conditions)->toBe([ 'job_uuid' => 'unique-job-id', ]); + expect(($storage->stored[0]->attributes)())->toBe([ + 'slowest' => 66, + ]); +}); + +it('can ingest an update with a short closure', function () { + $pulse = App::make(Pulse::class); + $ingest = App::make(Redis::class); + $storage = new StorageFake; + $update = new Update('pulse_jobs', [ + 'job_uuid' => 'unique-job-id', + ], fn () => [ + 'slowest' => 66, + ]); + + $pulse->record($update); + $pulse->store($ingest); + $ingest->store($storage); + + expect($storage->stored)->toHaveCount(1); + expect($storage->stored[0])->toBeInstanceOf(Update::class); + expect($storage->stored[0])->not->toBe($update); + expect($storage->stored[0]->conditions)->toBe([ + 'job_uuid' => 'unique-job-id', + ]); + expect(($storage->stored[0]->attributes)())->toBe([ + 'slowest' => 66, + ]); +}); + +it('can ingest an update with a short closure using external scope', function () { + $pulse = App::make(Pulse::class); + $ingest = App::make(Redis::class); + $storage = new StorageFake; + $duration = 66; + $update = new Update('pulse_jobs', [ + 'job_uuid' => 'unique-job-id', + ], fn () => [ + 'slowest' => $duration, + ]); + + $pulse->record($update); + $pulse->store($ingest); + $ingest->store($storage); + + expect($storage->stored)->toHaveCount(1); + expect($storage->stored[0])->toBeInstanceOf(Update::class); + expect($storage->stored[0])->not->toBe($update); + expect($storage->stored[0]->conditions)->toBe([ + 'job_uuid' => 'unique-job-id', + ]); + expect(($storage->stored[0]->attributes)())->toBe([ + 'slowest' => 66, + ]); +}); + +it('can ingest an update array based attributes', function () { + $pulse = App::make(Pulse::class); + $ingest = App::make(Redis::class); + $storage = new StorageFake; + $duration = 66; + $update = new Update('pulse_jobs', [ + 'job_uuid' => 'unique-job-id', + ], [ + 'slowest' => $duration, + ]); + + $pulse->record($update); + $pulse->store($ingest); + $ingest->store($storage); + + expect($storage->stored)->toHaveCount(1); + expect($storage->stored[0])->toBeInstanceOf(Update::class); + expect($storage->stored[0])->not->toBe($update); + expect($storage->stored[0]->conditions)->toBe([ + 'job_uuid' => 'unique-job-id', + ]); + expect($storage->stored[0]->attributes)->toBe([ + 'slowest' => 66, + ]); });