Skip to content

Commit

Permalink
Frontend: keep buffered events lazy sorted by timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Feb 3, 2024
1 parent 8308c33 commit c2d6000
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/Info.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class Info
{
public const NAME = 'Buggregator Trap';
public const VERSION = '1.4.0';
public const VERSION = '1.4.1';
public const LOGO_CLI_COLOR = <<<CONSOLE
\e[44;97;1m \e[0m
\e[44;97;1m ▄█▀ ▀█▄ \e[0m
Expand Down
30 changes: 28 additions & 2 deletions src/Sender/Frontend/EventsStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,33 @@ final class EventsStorage implements IteratorAggregate, Countable

{
/**
* Events. Will be sorted by timestamp in descending order when requested via the {@see getIterator()} method.
* @var array<non-empty-string, Event>
*/
private array $events = [];
private bool $sorted = false;

public function __construct(
private readonly Config $config = new Config(2),
private readonly Config $config = new Config(),
) {
}

public function add(Event $event): void
{
$this->events[$event->uuid] = $event;
$this->sorted = false;

if (\count($this->events) > $this->config->maxSize) {
\array_shift($this->events);
// find most old event and remove it
$k = $event->uuid;
$t = $event->timestamp;
foreach ($this->events as $uuid => $e) {
if ($e->timestamp < $t) {
$k = $uuid;
$t = $e->timestamp;
}
}
unset($this->events[$k]);
}
}

Expand All @@ -43,6 +56,8 @@ public function clear(): void
*/
public function getIterator(): \Traversable
{
// Defers sorting of events until it is necessary.
$this->sort();
return new \ArrayIterator($this->events);
}

Expand All @@ -63,4 +78,15 @@ public function count(): int
{
return \count($this->events);
}

/**
* Sort events by timestamp in descending order.
*/
private function sort(): void
{
if (!$this->sorted) {
\uasort($this->events, static fn(Event $a, Event $b) => $b->timestamp <=> $a->timestamp);
$this->sorted = true;
}
}
}
2 changes: 1 addition & 1 deletion src/Sender/Frontend/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function eventsDelete(array $uuids = []): Success
public function eventsList(): EventCollection
{
$this->debug('List all events');
return new EventCollection(events: \array_reverse(\iterator_to_array($this->eventsStorage->getIterator(), false)));
return new EventCollection(events: \iterator_to_array($this->eventsStorage->getIterator(), false));
}

private function debug(string $pattern, string ...$args): void
Expand Down
2 changes: 0 additions & 2 deletions src/Support/ProtobufCaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ public static function castEnum(EnumValue $c, array $a, Stub $stub, bool $isNest
];
}

public mixed $value;

private static function castMessage(Message $message, PublicDescriptor|InternalDescriptor $descriptor): array
{
return [
Expand Down
20 changes: 20 additions & 0 deletions tests/Unit/Sender/Frontend/EventsStorageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ public function testMaxEventsLimit(): void
$this->assertNotNull($storage->get($e3->uuid));
}

public function testMaxEventsLimitWithSort(): void
{
$config = new Config(2);
$storage = new EventsStorage($config);

$storage->add($e1 = $this->createEvent());
$storage->add($e2 = $this->createEvent());
$storage->add($e3 = $this->createEvent(timestamp: \microtime(true) - 1));

$this->assertCount(2, $storage);
// new event should be added in order of timestamp, and then the first event should be removed
$this->assertNull($storage->get($e3->uuid));
$this->assertNotNull($storage->get($e1->uuid));
$this->assertNotNull($storage->get($e2->uuid));
// Check order of events
$events = \iterator_to_array($storage->getIterator(), false);
$this->assertSame($e2->uuid, $events[0]->uuid);
$this->assertSame($e1->uuid, $events[1]->uuid);
}

private function createEvent(
?string $uuid = null,
?string $type = null,
Expand Down

0 comments on commit c2d6000

Please sign in to comment.