Skip to content

Commit 8605f04

Browse files
committed
Detect evicted current chunk and invalidate memoized chunk on metadata reload
1 parent 6f979a0 commit 8605f04

4 files changed

Lines changed: 46 additions & 1 deletion

File tree

src/Concerns/LogIndex/CanSplitIndexIntoChunks.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ public function getCurrentChunk(): LogIndexChunk
3535
$this->currentChunk = LogIndexChunk::fromDefinitionArray($this->currentChunkDefinition);
3636

3737
if ($this->currentChunk->size > 0) {
38-
$this->currentChunk->data = $this->getChunkDataFromCache($this->currentChunk->index, []);
38+
$data = $this->getChunkDataFromCache($this->currentChunk->index);
39+
$this->currentChunk->data = $data ?? [];
40+
41+
if (is_null($data)) {
42+
// The current chunk was evicted from cache while the metadata survived.
43+
$this->markForRebuild();
44+
}
3945
}
4046
}
4147

src/Concerns/LogIndex/HasMetadata.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,9 @@ protected function loadMetadata(): void
3636
$this->maxChunkSize = $data['max_chunk_size'] ?? self::DEFAULT_CHUNK_SIZE;
3737
$this->chunkDefinitions = $data['chunk_definitions'] ?? [];
3838
$this->currentChunkDefinition = $data['current_chunk_definition'] ?? [];
39+
40+
// The memoized chunk object is derived from the definition loaded above,
41+
// so it must not survive a metadata (re)load — e.g. after clearCache().
42+
unset($this->currentChunk);
3943
}
4044
}

src/Concerns/LogIndex/PreservesIndexingProgress.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ public function incomplete(): bool
4242

4343
public function markForRebuild(): void
4444
{
45+
if ($this->rebuildRequired ?? false) {
46+
return;
47+
}
48+
4549
$this->rebuildRequired = true;
4650

4751
// Persist immediately so the next request sees the flag even though

tests/Unit/LogReaderTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,37 @@
116116
->and(count($logReader->reset()->get()))->toBe(2);
117117
});
118118

119+
it('rebuilds the index when the current chunk is evicted but metadata survives', function () {
120+
File::append($this->file->path, PHP_EOL.makeLaravelLogEntry());
121+
122+
$path = $this->file->path;
123+
// Default chunk size, so both entries live in the single (current) chunk.
124+
$this->file->logs()->scan();
125+
126+
expect($this->file->logs()->total())->toBe(2);
127+
128+
LogViewerCache::forget(GenerateCacheKey::for($this->file->index(), 'chunk:0'));
129+
130+
// The request that discovers the eviction flags the index for a rebuild.
131+
IndexedLogReader::clearInstances();
132+
$logReader = (new LogFile($path))->logs();
133+
134+
expect(count($logReader->get()))->toBe(0)
135+
->and($logReader->requiresScan())->toBeTrue();
136+
137+
// The next request (e.g. a page reload) rebuilds the index from scratch.
138+
IndexedLogReader::clearInstances();
139+
$logReader = (new LogFile($path))->logs();
140+
141+
expect($logReader->requiresScan())->toBeTrue();
142+
143+
$logReader->scan();
144+
145+
expect($logReader->requiresScan())->toBeFalse()
146+
->and($logReader->total())->toBe(2)
147+
->and(count($logReader->reset()->get()))->toBe(2);
148+
});
149+
119150
it('does not flag a rebuild when reading a chunk the index does not know about', function () {
120151
$this->file->logs()->scan();
121152

0 commit comments

Comments
 (0)