Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
33 changes: 33 additions & 0 deletions src/Concerns/SerializesClosures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Laravel\Pulse\Concerns;

use Closure;
use Laravel\SerializableClosure\SerializableClosure;

trait SerializesClosures
{
/**
* Prepare the instance values for serialization.
*
* @return array<string, mixed>
*/
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<string, mixed> $data
*/
public function __unserialize(array $data): void
{
foreach ($data as $key => $value) {
$this->{$key} = $value instanceof SerializableClosure ? $value->getClosure() : $value;
}
}
}
2 changes: 1 addition & 1 deletion src/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
5 changes: 4 additions & 1 deletion src/Update.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
namespace Laravel\Pulse;

use Closure;
use Laravel\Pulse\Concerns\SerializesClosures;

class Update
{
use SerializesClosures;

/**
* @param array<string, mixed> $conditions
* @param array<string, mixed>|(\Closure(array<string, mixed>): array<string, mixed>) $attributes
Expand All @@ -19,7 +22,7 @@ public function __construct(
}

/**
* Resolve the update for ingest and storage.
* Resolve the update for ingest.
*/
public function resolve(): self
{
Expand Down
139 changes: 139 additions & 0 deletions tests/Feature/RedisIngestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

use Illuminate\Support\Facades\App;
use Laravel\Pulse\Ingests\Redis;
use Laravel\Pulse\Pulse;
use Laravel\Pulse\Update;
use Tests\StorageFake;

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;
$duration = 66;
$update = new Update('pulse_jobs', [
'job_uuid' => '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',
]);
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,
]);
});
37 changes: 37 additions & 0 deletions tests/StorageFake.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Tests;

use Illuminate\Support\Collection;
use Laravel\Pulse\Contracts\Storage;

class StorageFake implements Storage
{
/**
* Create a new fake instance.
*/
public function __construct(public Collection $stored = new Collection)
{
//
}

/**
* Store the entries and updates.
*
* @param \Illuminate\Support\Collection<int, \Laravel\Pulse\Entry|\Laravel\Pulse\Update> $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<int, string> $tables
*/
public function trim(Collection $tables): void
{
//
}
}