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
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,241 @@
<?php
declare(strict_types=1);
use App\Framework\Ksuid\Ksuid;
use App\Framework\Ksuid\KsuidGenerator;
use App\Framework\Random\SecureRandomGenerator;
it('generates KSUID with current timestamp', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$ksuid = $generator->generate();
expect($ksuid)->toBeInstanceOf(Ksuid::class);
expect($ksuid->getTimestamp())->toBeGreaterThanOrEqual(time() - 1);
expect($ksuid->getTimestamp())->toBeLessThanOrEqual(time() + 1);
});
it('generates KSUID at specific timestamp', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$timestamp = time() - 3600; // 1 hour ago
$ksuid = $generator->generateAt($timestamp);
expect($ksuid->getTimestamp())->toBe($timestamp);
});
it('generates KSUID at specific DateTime', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$dateTime = new DateTimeImmutable('2021-01-01 12:00:00 UTC');
$ksuid = $generator->generateAtDateTime($dateTime);
expect($ksuid->getTimestamp())->toBe($dateTime->getTimestamp());
});
it('generates KSUID in the past', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$secondsAgo = 3600; // 1 hour ago
$ksuid = $generator->generateInPast($secondsAgo);
$expectedTimestamp = time() - $secondsAgo;
expect($ksuid->getTimestamp())->toBeGreaterThanOrEqual($expectedTimestamp - 1);
expect($ksuid->getTimestamp())->toBeLessThanOrEqual($expectedTimestamp + 1);
});
it('generates batch of KSUIDs', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$count = 10;
$ksuids = $generator->generateBatch($count);
expect($ksuids)->toHaveCount($count);
expect($ksuids[0])->toBeInstanceOf(Ksuid::class);
// All should have the same timestamp
$firstTimestamp = $ksuids[0]->getTimestamp();
foreach ($ksuids as $ksuid) {
expect($ksuid->getTimestamp())->toBe($firstTimestamp);
}
// All should be unique
$values = array_map(fn ($ksuid) => $ksuid->toString(), $ksuids);
$uniqueValues = array_unique($values);
expect($uniqueValues)->toHaveCount($count);
});
it('generates batch with custom timestamp', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$timestamp = time() - 7200; // 2 hours ago
$count = 5;
$ksuids = $generator->generateBatch($count, $timestamp);
expect($ksuids)->toHaveCount($count);
foreach ($ksuids as $ksuid) {
expect($ksuid->getTimestamp())->toBe($timestamp);
}
});
it('generates sequence of KSUIDs', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$count = 5;
$interval = 10; // 10 seconds apart
$ksuids = $generator->generateSequence($count, $interval);
expect($ksuids)->toHaveCount($count);
// Check timestamps are incrementing
for ($i = 1; $i < $count; $i++) {
$timeDiff = $ksuids[$i]->getTimestamp() - $ksuids[$i - 1]->getTimestamp();
expect($timeDiff)->toBe($interval);
}
});
it('generates KSUID with prefix', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$prefix = 'test';
$ksuid = $generator->generateWithPrefix($prefix);
$payload = $ksuid->getPayload();
expect(substr($payload, 0, strlen($prefix)))->toBe($prefix);
expect(strlen($payload))->toBe(Ksuid::PAYLOAD_BYTES);
});
it('validates KSUID strings', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$validKsuid = $generator->generate();
expect($generator->isValid($validKsuid->toString()))->toBeTrue();
expect($generator->isValid('invalid'))->toBeFalse();
expect($generator->isValid(''))->toBeFalse();
expect($generator->isValid(str_repeat('!', Ksuid::ENCODED_LENGTH)))->toBeFalse();
});
it('parses KSUID strings', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$original = $generator->generate();
$parsed = $generator->parse($original->toString());
expect($parsed->equals($original))->toBeTrue();
});
it('gets min/max KSUIDs for timestamp', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$timestamp = time();
$min = $generator->getMinForTimestamp($timestamp);
$max = $generator->getMaxForTimestamp($timestamp);
expect($min->getTimestamp())->toBe($timestamp);
expect($max->getTimestamp())->toBe($timestamp);
expect($min->compare($max))->toBeLessThan(0);
// Min should have all zero payload
expect($min->getPayload())->toBe(str_repeat("\0", Ksuid::PAYLOAD_BYTES));
// Max should have all 0xFF payload
expect($max->getPayload())->toBe(str_repeat("\xFF", Ksuid::PAYLOAD_BYTES));
});
it('generates time range for queries', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$startTime = time() - 3600;
$endTime = time();
$range = $generator->generateTimeRange($startTime, $endTime);
expect($range)->toHaveKey('min');
expect($range)->toHaveKey('max');
expect($range['min']->getTimestamp())->toBe($startTime);
expect($range['max']->getTimestamp())->toBe($endTime);
});
it('throws exception for invalid batch count', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
expect(fn () => $generator->generateBatch(0))
->toThrow(InvalidArgumentException::class, 'Count must be positive');
expect(fn () => $generator->generateBatch(10001))
->toThrow(InvalidArgumentException::class, 'Batch size cannot exceed 10000');
});
it('throws exception for invalid sequence count', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
expect(fn () => $generator->generateSequence(0))
->toThrow(InvalidArgumentException::class, 'Count must be positive');
expect(fn () => $generator->generateSequence(1001))
->toThrow(InvalidArgumentException::class, 'Sequence size cannot exceed 1000');
});
it('throws exception for negative interval', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
expect(fn () => $generator->generateSequence(5, -1))
->toThrow(InvalidArgumentException::class, 'Interval must be non-negative');
});
it('throws exception for timestamp before epoch', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$beforeEpoch = Ksuid::EPOCH - 1;
expect(fn () => $generator->generateAt($beforeEpoch))
->toThrow(InvalidArgumentException::class, 'Timestamp cannot be before KSUID epoch');
});
it('throws exception for prefix too long', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$longPrefix = str_repeat('x', Ksuid::PAYLOAD_BYTES); // Full payload size
expect(fn () => $generator->generateWithPrefix($longPrefix))
->toThrow(InvalidArgumentException::class, 'Prefix cannot exceed 15 bytes');
});
it('throws exception for invalid time range', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$startTime = time();
$endTime = time() - 3600; // Before start time
expect(fn () => $generator->generateTimeRange($startTime, $endTime))
->toThrow(InvalidArgumentException::class, 'Start timestamp must be before end timestamp');
});
it('creates generator using factory method', function () {
$randomGen = new SecureRandomGenerator();
$generator = KsuidGenerator::create($randomGen);
expect($generator)->toBeInstanceOf(KsuidGenerator::class);
expect($generator->generate())->toBeInstanceOf(Ksuid::class);
});
it('generates sortable KSUIDs by timestamp', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$older = $generator->generateAt(time() - 3600);
$newer = $generator->generateAt(time());
// Lexicographic comparison should match timestamp order
expect($older->compare($newer))->toBeLessThan(0);
expect($older->toString() < $newer->toString())->toBeTrue();
});
it('generates unique KSUIDs across multiple calls', function () {
$generator = new KsuidGenerator(new SecureRandomGenerator());
$ksuids = [];
$count = 1000;
for ($i = 0; $i < $count; $i++) {
$ksuids[] = $generator->generate()->toString();
}
$uniqueKsuids = array_unique($ksuids);
expect($uniqueKsuids)->toHaveCount($count);
});