Passed
Push — main ( 7a6063...0cf387 )
by Lorenzo
10:35
created

insertInvalidationEvent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 20
c 1
b 0
f 0
nc 3
nop 6
dl 0
loc 36
rs 9.6
1
<?php
2
3
namespace Padosoft\SuperCacheInvalidate\Helpers;
4
5
use Illuminate\Support\Facades\Cache;
6
use Illuminate\Support\Facades\DB;
7
use Illuminate\Support\Facades\Redis;
8
9
class SuperCacheInvalidationHelper
10
{
11
    /**
12
     * Insert a cache invalidation event into the database.
13
     *
14
     * @param string      $type                  'key' or 'tag'
15
     * @param string      $identifier            The cache key or tag to invalidate
16
     * @param string|null $reason                Reason for invalidation (optional)
17
     * @param int         $priority              Priority of the event
18
     * @param array       $associatedIdentifiers Optional array of associated tags or keys
19
     * @param int|null    $totalShards           Total number of shards (from config if null)
20
     */
21
    public function insertInvalidationEvent(
22
        string $type,
23
        string $identifier,
24
        ?string $reason = null,
25
        int $priority = 0,
26
        array $associatedIdentifiers = [],
27
        ?int $totalShards = null
28
    ): void {
29
        $totalShards = $totalShards ?? config('super_cache_invalidate.total_shards', 10);
30
        $shard = crc32($identifier) % $totalShards;
31
32
        $data = [
33
            'type' => $type,
34
            'identifier' => $identifier,
35
            'reason' => $reason,
36
            'priority' => $priority,
37
            'event_time' => now(),
38
            'processed' => 0,
39
            'shard' => $shard,
40
        ];
41
42
        // Insert the event and get its ID
43
        $eventId = DB::table('cache_invalidation_events')->insertGetId($data);
44
45
        // Insert associated identifiers
46
        if (!empty($associatedIdentifiers)) {
47
            $associations = [];
48
            foreach ($associatedIdentifiers as $associated) {
49
                $associations[] = [
50
                    'event_id' => $eventId,
51
                    'associated_type' => $associated['type'], // 'key' or 'tag'
52
                    'associated_identifier' => $associated['identifier'],
53
                    'created_at' => now(),
54
                ];
55
            }
56
            DB::table('cache_invalidation_event_associations')->insert($associations);
57
        }
58
    }
59
60
    /**
61
     * Acquire a lock for processing a shard.
62
     *
63
     * @param  int          $shardId     The shard number
64
     * @param  int          $lockTimeout Lock timeout in seconds
65
     * @return string|false The lock value if acquired, false otherwise
66
     */
67
    public function acquireShardLock(int $shardId, int $lockTimeout): bool|string
68
    {
69
        $lockKey = "shard_lock:$shardId";
70
        $lockValue = uniqid('', true);
71
        $isLocked = Redis::set($lockKey, $lockValue, 'NX', 'EX', $lockTimeout);
72
73
        return $isLocked ? $lockValue : false;
74
    }
75
76
    /**
77
     * Release the lock for a shard.
78
     *
79
     * @param int    $shardId   The shard number
80
     * @param string $lockValue The lock value to validate ownership
81
     */
82
    public function releaseShardLock(int $shardId, string $lockValue): void
83
    {
84
        $lockKey = "shard_lock:$shardId";
85
        $currentValue = Redis::get($lockKey);
86
        if ($currentValue === $lockValue) {
87
            Redis::del($lockKey);
88
        }
89
    }
90
}
91