optimizations

This commit is contained in:
2026-03-28 19:15:39 +01:00
parent 0b25d9570a
commit cab4fbd83e
509 changed files with 1016804 additions and 1605 deletions

View File

@@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
use App\Jobs\BackfillArtworkVectorIndexJob;
use App\Jobs\SyncArtworkVectorIndexJob;
use App\Models\Artwork;
use App\Models\ArtworkEmbedding;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use function Pest\Laravel\artisan;
uses(RefreshDatabase::class);
function jobProperty(object $job, string $property): mixed
{
$reflection = new ReflectionProperty($job, $property);
$reflection->setAccessible(true);
return $reflection->getValue($job);
}
it('queues a resumable vector repair run from the command', function (): void {
Queue::fake();
artisan('artworks:vectors-repair', [
'--after-id' => 25,
'--batch' => 50,
'--public-only' => true,
'--stale-hours' => 24,
])->assertSuccessful();
Queue::assertPushed(BackfillArtworkVectorIndexJob::class, function (BackfillArtworkVectorIndexJob $job): bool {
return jobProperty($job, 'afterId') === 25
&& jobProperty($job, 'batchSize') === 50
&& jobProperty($job, 'publicOnly') === true
&& jobProperty($job, 'staleHours') === 24;
});
});
it('fans out queued vector repair only for artworks with local embeddings', function (): void {
Queue::fake();
$embeddedArtwork = Artwork::factory()->create([
'hash' => '1122334455667788',
'is_public' => true,
'is_approved' => true,
'published_at' => now()->subDay(),
]);
ArtworkEmbedding::query()->create([
'artwork_id' => $embeddedArtwork->id,
'model' => 'clip',
'model_version' => 'v1',
'algo_version' => 'clip-cosine-v1',
'dim' => 2,
'embedding_json' => json_encode([0.6, 0.8], JSON_THROW_ON_ERROR),
'source_hash' => '1122334455667788',
'is_normalized' => true,
'generated_at' => now(),
'meta' => ['source' => 'clip'],
]);
Artwork::factory()->create([
'hash' => 'aabbccddeeff0011',
'is_public' => true,
'is_approved' => true,
'published_at' => now()->subDay(),
]);
(new BackfillArtworkVectorIndexJob(0, 100, true))->handle();
Queue::assertPushed(SyncArtworkVectorIndexJob::class, function (SyncArtworkVectorIndexJob $job) use ($embeddedArtwork): bool {
return jobProperty($job, 'artworkId') === $embeddedArtwork->id;
});
Queue::assertNotPushed(BackfillArtworkVectorIndexJob::class);
});
it('can target only stale or never-indexed artworks during queued repair', function (): void {
Queue::fake();
$staleArtwork = Artwork::factory()->create([
'hash' => '1111222233334444',
'is_public' => true,
'is_approved' => true,
'published_at' => now()->subDay(),
'last_vector_indexed_at' => now()->subHours(48),
]);
ArtworkEmbedding::query()->create([
'artwork_id' => $staleArtwork->id,
'model' => 'clip',
'model_version' => 'v1',
'algo_version' => 'clip-cosine-v1',
'dim' => 2,
'embedding_json' => json_encode([0.6, 0.8], JSON_THROW_ON_ERROR),
'source_hash' => '1111222233334444',
'is_normalized' => true,
'generated_at' => now(),
'meta' => ['source' => 'clip'],
]);
$missingArtwork = Artwork::factory()->create([
'hash' => '5555666677778888',
'is_public' => true,
'is_approved' => true,
'published_at' => now()->subDay(),
'last_vector_indexed_at' => null,
]);
ArtworkEmbedding::query()->create([
'artwork_id' => $missingArtwork->id,
'model' => 'clip',
'model_version' => 'v1',
'algo_version' => 'clip-cosine-v1',
'dim' => 2,
'embedding_json' => json_encode([0.6, 0.8], JSON_THROW_ON_ERROR),
'source_hash' => '5555666677778888',
'is_normalized' => true,
'generated_at' => now(),
'meta' => ['source' => 'clip'],
]);
$freshArtwork = Artwork::factory()->create([
'hash' => '9999aaaabbbbcccc',
'is_public' => true,
'is_approved' => true,
'published_at' => now()->subDay(),
'last_vector_indexed_at' => now()->subHours(2),
]);
ArtworkEmbedding::query()->create([
'artwork_id' => $freshArtwork->id,
'model' => 'clip',
'model_version' => 'v1',
'algo_version' => 'clip-cosine-v1',
'dim' => 2,
'embedding_json' => json_encode([0.6, 0.8], JSON_THROW_ON_ERROR),
'source_hash' => '9999aaaabbbbcccc',
'is_normalized' => true,
'generated_at' => now(),
'meta' => ['source' => 'clip'],
]);
(new BackfillArtworkVectorIndexJob(0, 100, true, 24))->handle();
Queue::assertPushed(SyncArtworkVectorIndexJob::class, function (SyncArtworkVectorIndexJob $job) use ($staleArtwork): bool {
return jobProperty($job, 'artworkId') === $staleArtwork->id;
});
Queue::assertPushed(SyncArtworkVectorIndexJob::class, function (SyncArtworkVectorIndexJob $job) use ($missingArtwork): bool {
return jobProperty($job, 'artworkId') === $missingArtwork->id;
});
Queue::assertNotPushed(SyncArtworkVectorIndexJob::class, function (SyncArtworkVectorIndexJob $job) use ($freshArtwork): bool {
return jobProperty($job, 'artworkId') === $freshArtwork->id;
});
Queue::assertNotPushed(BackfillArtworkVectorIndexJob::class);
});