Skip to content

Commit 639179b

Browse files
committed
Fix improper handling of database cache prefixes
1 parent 09d59c4 commit 639179b

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

src/Database/DatabaseEvictStrategy.php

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class DatabaseEvictStrategy extends AbstractEvictStrategy
2525

2626
protected float $elapsedTime = 0;
2727

28+
protected string $cachePrefix = "";
29+
2830
public function __construct(string $storeName)
2931
{
3032
parent::__construct($storeName);
@@ -34,6 +36,10 @@ public function __construct(string $storeName)
3436
$this->dbConn = DB::connection($storeConn);
3537
$this->dbTable = config("cache.stores.{$storeName}.table");
3638
$this->cacheStore = Cache::store($this->storeName)->getStore();
39+
40+
// write down the cache prefix; cache might have that
41+
// currently Laravel's cache prefix is only applied very easily by "{prefix}{key}"
42+
$this->cachePrefix = $this->cacheStore->getPrefix();
3743
}
3844

3945
public function execute(): void
@@ -49,10 +55,9 @@ public function execute(): void
4955
// the key field is indexed, so it is not too bad
5056
Partyline::info("Finding relevant cache records...");
5157
// cache might have prefix!
52-
$cachePrefix = $this->cacheStore->getPrefix();
5358
$itemCount = $this->dbConn
5459
->table($this->dbTable)
55-
->where('key', 'LIKE', "$cachePrefix%")
60+
->where('key', 'LIKE', "{$this->cachePrefix}%")
5661
->count();
5762
Partyline::info("Found $itemCount records; processing...");
5863

@@ -62,9 +67,8 @@ public function execute(): void
6267
$progressBar->setMaxSteps($itemCount);
6368
foreach ($this->yieldCacheTableItems() as $cacheItem) {
6469
// read record details
65-
$currentUserKey = $cacheItem->key;
70+
$currentActualKey = $cacheItem->key;
6671
$currentExpiration = $cacheItem->expiration;
67-
$currentActualKey = "{$cachePrefix}{$currentUserKey}";
6872
// currently timestamps are 32-bit, so are 4 bytes
6973
$estimatedBytes = (int) ($cacheItem->key_bytes + $cacheItem->value_bytes + 4);
7074
$progressBar->advance();
@@ -81,7 +85,7 @@ public function execute(): void
8185
->where('expiration', '=', $currentExpiration)
8286
->delete();
8387
if ($rowsAffected) {
84-
// item really expired with no new values
88+
// item really expired with no new updates
8589
$this->deletedRecords += 1;
8690
$this->deletedRecordSizes += $estimatedBytes;
8791
}
@@ -101,19 +105,25 @@ public function execute(): void
101105
Partyline::info("Note: no free space reclaimed; reclaiming free space should be done manually!");
102106
}
103107

108+
/**
109+
* Yields the next item from the cache table that belongs to this cache.
110+
*
111+
* This method will return the actual key (with the cache prefix if exists) of the entry.
112+
* @return \Generator<mixed, object, mixed, void>
113+
*/
104114
protected function yieldCacheTableItems(): \Generator
105115
{
106116
// there might be a prefix for the cache store!
107-
$cachePrefix = $this->cacheStore->getPrefix();
108-
$currentUserKey = "";
117+
$cachePrefix = $this->cachePrefix;
118+
// initialize the key to be just the cache prefix as the "zero string".
119+
$currentActualKey = $cachePrefix;
109120
// loop until no more items
110121
while (true) {
111122
// find the next key
112-
$actualKey = "{$cachePrefix}{$currentUserKey}";
113123
$record = $this->dbConn
114124
->table($this->dbTable)
115125
->select(['key', 'expiration', DB::raw('LENGTH(key) AS key_bytes'), DB::raw('LENGTH(value) AS value_bytes')])
116-
->where('key', '>', $actualKey)
126+
->where('key', '>', $currentActualKey)
117127
->where('key', 'LIKE', "$cachePrefix%")
118128
->limit(1)
119129
->first();
@@ -123,7 +133,7 @@ protected function yieldCacheTableItems(): \Generator
123133
}
124134

125135
yield $record;
126-
$currentUserKey = $record->key;
136+
$currentActualKey = $record->key;
127137
}
128138
// loop exit handled inside while loop
129139
}

0 commit comments

Comments
 (0)