Passed
Push — main ( 5995aa...2135e0 )
by Lorenzo
03:01
created

PruneCacheInvalidationDataCommand   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 25
c 1
b 0
f 0
dl 0
loc 82
rs 10
wmc 5

3 Methods

Rating   Name   Duplication   Size   Complexity  
A pruneTable() 0 18 2
A handle() 0 18 2
A getPartitionsFromDb() 0 11 1
1
<?php
2
3
namespace Padosoft\SuperCacheInvalidate\Console;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Facades\DB;
7
8
class PruneCacheInvalidationDataCommand extends Command
9
{
10
    /**
11
     * The name and signature of the console command.
12
     *
13
     * @var string
14
     */
15
    protected $signature = 'supercache:prune-invalidation-data
16
                            {--months=1 : The number of months to retain data}';
17
18
    /**
19
     * The console command description.
20
     *
21
     * @var string
22
     */
23
    protected $description = 'Prune old cache invalidation data by dropping partitions';
24
25
    /**
26
     * Prune partitions in a table older than the retention partition key.
27
     *
28
     * @param string $tableName             The name of the table
29
     * @param int    $retentionPartitionKey The partition key cutoff
30
     */
31
    protected function pruneTable(string $tableName, int $retentionPartitionKey): void
32
    {
33
        // Fetch partition names
34
        $partitions = $this->getPartitionsFromDb($tableName, $retentionPartitionKey);
35
36
        if (empty($partitions)) {
37
            $this->info("No partitions to prune for table {$tableName}.");
38
39
            return;
40
        }
41
42
        // Build DROP PARTITION statement
43
        $partitionNames = implode(', ', array_map(function ($partition) {
44
            return $partition->PARTITION_NAME;
45
        }, $partitions));
46
47
        DB::statement("ALTER TABLE `{$tableName}` DROP PARTITION {$partitionNames}");
48
        $this->info("Pruned partitions: {$partitionNames} from table {$tableName}.");
49
    }
50
51
    /**
52
     * Execute the console command.
53
     */
54
    public function handle(): void
55
    {
56
        $months = (int) $this->option('months');
57
        $retentionDate = now()->subMonths($months);
58
        $retentionPartitionKey = $retentionDate->year * 100 + $retentionDate->week();
59
60
        // Prune tables
61
        $tables = [
62
            'cache_invalidation_events',
63
            'cache_invalidation_timestamps',
64
            'cache_invalidation_event_associations',
65
        ];
66
67
        foreach ($tables as $tableName) {
68
            $this->pruneTable($tableName, $retentionPartitionKey);
69
        }
70
71
        $this->info('Old cache invalidation data has been pruned.');
72
    }
73
74
    /**
75
     * @param string $tableName
76
     * @param int $retentionPartitionKey
77
     * @return array
78
     */
79
    protected function getPartitionsFromDb(string $tableName, int $retentionPartitionKey): array
80
    {
81
        $partitions = DB::select('
82
            SELECT PARTITION_NAME, PARTITION_DESCRIPTION
83
            FROM INFORMATION_SCHEMA.PARTITIONS
84
            WHERE TABLE_SCHEMA = DATABASE()
85
            AND TABLE_NAME = ?
86
            AND PARTITION_NAME IS NOT NULL
87
            AND PARTITION_DESCRIPTION < ?
88
        ', [$tableName, $retentionPartitionKey]);
89
        return $partitions;
90
    }
91
}
92