Skip to content
6 changes: 4 additions & 2 deletions config/geoip.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@
| Cache Tags
|--------------------------------------------------------------------------
|
| Cache tags are not supported when using the file or database cache
| drivers in Laravel. This is done so that only locations can be cleared.
| Cache tags allow you to selectively clear only GeoIP cached locations
| without affecting other cached data. If the active cache driver does
| not support tagging (e.g. file, database), tags are automatically
| ignored at runtime. Set to null or an empty array to disable tagging.
|
*/

Expand Down
1 change: 0 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
<MixedArgument>
<code><![CDATA[$config]]></code>
<code><![CDATA[$this->config('cache_expires', 30)]]></code>
<code><![CDATA[$this->config('cache_tags')]]></code>
<code><![CDATA[$this->config('default_location', [])]]></code>
</MixedArgument>
<MixedArgumentTypeCoercion>
Expand Down
6 changes: 2 additions & 4 deletions src/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ final class Cache
/**
* Create a new cache instance.
*
* @param CacheManager $cache
* @param array $tags
* @param int $expires
* @param list<string> $tags
*/
public function __construct(CacheManager $cache, $tags, private readonly int $expires = 30)
public function __construct(CacheManager $cache, array $tags, private readonly int $expires = 30)
{
$this->cache = ($tags === [] || !$cache->supportsTags()) ? $cache : $cache->tags($tags);
}
Expand Down
9 changes: 6 additions & 3 deletions src/Console/Clear.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ class Clear extends Command
public function handle(): int
{
if ($this->isSupported() === false) {
$this->output->error('Default cache system does not support tags');
$this->output->error(
'Cannot selectively clear GeoIP cache: either cache tags are not configured'
.' or the active cache driver does not support tagging.'
);
return self::FAILURE;
}

Expand All @@ -40,8 +43,8 @@ public function handle(): int
*/
protected function isSupported(): bool
{
return (empty(app('geoip')->config('cache_tags')) === false)
&& (in_array(config('cache.default'), ['file', 'database'], true) === false);
return !empty(app('geoip')->config('cache_tags'))
&& app(\Illuminate\Cache\CacheManager::class)->supportsTags();
}

/**
Expand Down
7 changes: 6 additions & 1 deletion src/GeoIP.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@ public function __construct(
private readonly LoggerInterface $logger,
) {
// Create caching instance
/** @var list<string> $cacheTags */
$cacheTags = array_values((array) $this->config('cache_tags', []));
if ($cacheTags !== [] && !$cache->supportsTags()) {
$this->logger->warning('GeoIP: cache tags are configured but the active cache driver does not support tagging. Tags will be ignored.');
}
Comment on lines +69 to +71

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The warning message is logged every time the GeoIP service is instantiated if the cache driver does not support tags. This could lead to log flooding in production environments. Consider using a more rate-limited approach or logging this only once per request/process lifecycle.

$this->cache = new Cache(
$cache,
$this->config('cache_tags'),
$cacheTags,
$this->config('cache_expires', 30)
);
$this->cache->setPrefix((string) $this->config('cache_prefix'));
Expand Down
26 changes: 26 additions & 0 deletions tests/CacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@ public function should_return_valid_location(): void
$this->assertFalse($uncachedLocation->default);
}

#[Test]
public function should_fall_back_to_untagged_cache_when_driver_does_not_support_tags(): void
{
// Switch to file driver which does not support tagging
config(['cache.default' => 'file']);
$cacheManager = app(CacheManager::class);

$this->assertFalse($cacheManager->supportsTags(), 'File cache driver should not support tags');

// Tags are configured, but driver doesn't support them — should not throw
$cache = new Cache($cacheManager, ['some-tag'], 30);

$location = new Location([
'ip' => '81.2.69.142',
'iso_code' => 'US',
'lat' => 41.31,
'lon' => -72.92,
]);

$cache->set($location['ip'], $location);
$cachedLocation = $cache->get($location['ip']);

$this->assertInstanceOf(Location::class, $cachedLocation);
$this->assertSame('81.2.69.142', $cachedLocation->ip);
}

#[Test]
public function it_flushes_empty_cache(): void
{
Expand Down
Loading