From 5426722c71a6c0bf059f3576414415671e94081b Mon Sep 17 00:00:00 2001 From: Ovidiu U Date: Wed, 22 Apr 2026 12:23:50 +0100 Subject: [PATCH] refactor: scope postcode cache to place names, DB is authoritative for postcodes --- app/Services/PostcodeService.php | 17 ++++++---- tests/Unit/Services/PostcodeServiceTest.php | 36 +++++++++++++++------ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/app/Services/PostcodeService.php b/app/Services/PostcodeService.php index 67b8ae3..8cc1c93 100644 --- a/app/Services/PostcodeService.php +++ b/app/Services/PostcodeService.php @@ -26,7 +26,16 @@ class PostcodeService public function resolve(string $query): ?LocationResult { $query = trim($query); - $cacheKey = 'postcode:'.strtolower(preg_replace('/\s+/', '', $query)); + + if ($this->isFullPostcode($query)) { + return $this->lookupLocalPostcode($query) ?? $this->lookupPostcode($query); + } + + if ($this->isOutcode($query)) { + return $this->lookupLocalOutcode($query) ?? $this->lookupOutcode($query); + } + + $cacheKey = 'place:'.strtolower(preg_replace('/\s+/', '', $query)); $cached = Cache::get($cacheKey); @@ -34,11 +43,7 @@ class PostcodeService return $cached; } - $result = match (true) { - $this->isFullPostcode($query) => $this->lookupLocalPostcode($query) ?? $this->lookupPostcode($query), - $this->isOutcode($query) => $this->lookupLocalOutcode($query) ?? $this->lookupOutcode($query), - default => $this->lookupPlace($query), - }; + $result = $this->lookupPlace($query); if ($result !== null) { Cache::put($cacheKey, $result, self::CACHE_TTL); diff --git a/tests/Unit/Services/PostcodeServiceTest.php b/tests/Unit/Services/PostcodeServiceTest.php index f3bc4ea..9e99cfc 100644 --- a/tests/Unit/Services/PostcodeServiceTest.php +++ b/tests/Unit/Services/PostcodeServiceTest.php @@ -134,23 +134,41 @@ it('returns null when place name yields no results', function (): void { // --- Caching --- -it('caches a successful resolution for 30 days', function (): void { +it('caches a successful place resolution for 30 days', function (): void { Http::fake([ - '*/outcodes/PE7' => Http::response([ + '*/places*' => Http::response([ + 'status' => 200, + 'result' => [[ + 'name_1' => 'Manchester', + 'latitude' => 53.480957, + 'longitude' => -2.237428, + ]], + ]), + ]); + + $this->service->resolve('Manchester'); + $this->service->resolve('Manchester'); + + Http::assertSentCount(1); + expect(Cache::get('place:manchester'))->toBeInstanceOf(LocationResult::class); +}); + +it('does not cache postcode resolutions in the Cache store (DB is the cache)', function (): void { + Http::fake([ + '*/postcodes/SW1A1AA' => Http::response([ 'status' => 200, 'result' => [ - 'outcode' => 'PE7', - 'latitude' => 52.536397, - 'longitude' => -0.210181, + 'postcode' => 'SW1A 1AA', + 'latitude' => 51.501009, + 'longitude' => -0.141588, ], ]), ]); - $this->service->resolve('PE7'); - $this->service->resolve('PE7'); + $this->service->resolve('SW1A 1AA'); - Http::assertSentCount(1); - expect(Cache::get('postcode:pe7'))->toBeInstanceOf(LocationResult::class); + expect(Cache::get('postcode:sw1a1aa'))->toBeNull() + ->and(Postcode::find('SW1A1AA'))->not->toBeNull(); }); it('does not cache failed lookups', function (): void {