Skip to content

Commit 68a3831

Browse files
authored
fix: 🐛 Self-heal cache when corrupted non-Collection value is detected. (#207)
1 parent ba101bd commit 68a3831

2 files changed

Lines changed: 34 additions & 6 deletions

File tree

src/ProviderAndDumperAggregator.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,18 @@ protected function getProvidersFromConfiguration(Collection $providers) : array
341341
}
342342

343343
protected function preventCacheKeyHashCollision(
344-
array $result,
344+
mixed $result,
345345
string $hashedCacheKey,
346346
string $cacheKey,
347347
array $queryElements,
348-
string $queryType
349-
) {
350-
if ($result["key"] === $cacheKey) {
348+
string $queryType,
349+
): Collection {
350+
$isValid = is_array($result)
351+
&& isset($result["key"], $result["value"])
352+
&& $result["key"] === $cacheKey
353+
&& $result["value"] instanceof Collection;
354+
355+
if ($isValid) {
351356
return $result["value"];
352357
}
353358

@@ -358,9 +363,13 @@ protected function preventCacheKeyHashCollision(
358363
return $this->cacheRequest($cacheKey, $queryElements, $queryType);
359364
}
360365

361-
protected function removeEmptyCacheEntry(Collection $result, string $cacheKey)
366+
protected function removeEmptyCacheEntry(mixed $result, string $cacheKey)
362367
{
363-
if ($result && $result->isEmpty()) {
368+
if (! $result instanceof Collection) {
369+
return;
370+
}
371+
372+
if ($result->isEmpty()) {
364373
app('cache')
365374
->store(config('geocoder.cache.store'))
366375
->forget($cacheKey);

tests/Feature/Providers/GeocoderServiceTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,3 +353,22 @@
353353
expect($store->get($positiveKey)['key'])->toBe('45.473282-73.834721');
354354
Http::assertSentCount(2);
355355
});
356+
357+
it('self-heals when a cached entry has a non-Collection value', function () {
358+
$address = '1600 Pennsylvania Ave NW, Washington, DC 20500, USA';
359+
$providerName = app('geocoder')->getProvider()->getName();
360+
$cacheKey = Str::slug(strtolower(urlencode($address)));
361+
$hashedCacheKey = sha1("{$providerName}-{$cacheKey}");
362+
$store = app('cache')->store(config('geocoder.cache.store'));
363+
364+
$store->put($hashedCacheKey, [
365+
'key' => $cacheKey,
366+
'value' => 'corrupted-not-a-collection',
367+
], 999999);
368+
369+
$results = app('geocoder')->geocode($address)->get();
370+
371+
expect($results)->toBeInstanceOf(Collection::class);
372+
expect($results->isNotEmpty())->toBeTrue();
373+
expect($store->get($hashedCacheKey)['value'])->toBeInstanceOf(Collection::class);
374+
});

0 commit comments

Comments
 (0)