Files
michaelschiemer/src/Framework/SlidingWindow/InMemorySlidingWindow.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

109 lines
2.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\SlidingWindow;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\SlidingWindow\Aggregator\SlidingWindowAggregator;
/**
* In-memory sliding window implementation
*/
final class InMemorySlidingWindow implements SlidingWindow
{
/**
* @var array<WindowEntry>
*/
private array $entries = [];
public function __construct(
private readonly Duration $windowSize,
private readonly string $identifier,
private readonly SlidingWindowAggregator $aggregator,
) {
}
public function record(mixed $value, Timestamp $timestamp): void
{
$this->entries[] = new WindowEntry($value, $timestamp);
$this->cleanup();
}
public function getValues(?Timestamp $now = null): array
{
$now ??= Timestamp::now();
$this->cleanup($now);
return array_map(
fn (WindowEntry $entry) => $entry->value,
$this->getValidEntries($now)
);
}
public function getStats(?Timestamp $now = null): SlidingWindowStats
{
$now ??= Timestamp::now();
$this->cleanup($now);
$validEntries = $this->getValidEntries($now);
$windowStart = $now->diff($this->windowSize) > Duration::zero()
? Timestamp::fromFloat($now->toFloat() - $this->windowSize->toSeconds())
: $now;
$aggregatedData = [];
if (! empty($validEntries)) {
$result = $this->aggregator->aggregate(...$validEntries);
$aggregatedData = method_exists($result, 'toArray') ? $result->toArray() : [$this->aggregator->getIdentifier() => $result];
}
return new SlidingWindowStats(
totalCount: count($validEntries),
windowSize: $this->windowSize,
windowStart: $windowStart,
windowEnd: $now,
aggregatedData: $aggregatedData
);
}
public function clear(): void
{
$this->entries = [];
}
public function getWindowSize(): Duration
{
return $this->windowSize;
}
public function getIdentifier(): string
{
return $this->identifier;
}
/**
* Get all valid entries within the window
*
* @return array<WindowEntry>
*/
private function getValidEntries(Timestamp $now): array
{
$cutoffTime = Timestamp::fromFloat($now->toFloat() - $this->windowSize->toSeconds());
return array_filter(
$this->entries,
fn (WindowEntry $entry) => $entry->isWithinWindow($cutoffTime)
);
}
/**
* Remove entries outside the window
*/
private function cleanup(?Timestamp $now = null): void
{
$now ??= Timestamp::now();
$this->entries = $this->getValidEntries($now);
}
}