Skip to content

Commit 940195b

Browse files
committed
chore: populate activity_log batch_uuids
1 parent cea128c commit 940195b

3 files changed

Lines changed: 166 additions & 0 deletions

File tree

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Console\Commands;
6+
7+
use App\Models\Activity;
8+
use Illuminate\Console\Command;
9+
use Illuminate\Support\Collection;
10+
use Illuminate\Support\Facades\DB;
11+
use Illuminate\Support\Str;
12+
use function Sentry\logger;
13+
14+
class BackfillActivityLogBatchUuidCommand extends Command
15+
{
16+
/**
17+
* The name and signature of the console command.
18+
*
19+
* @var string
20+
*/
21+
protected $signature = 'app:activity:batch-uuid
22+
{--chunk=10000 : Rows per processing chunk}
23+
{--dry-run : Do not perform updates}';
24+
25+
/**
26+
* The console command description.
27+
*
28+
* @var string
29+
*/
30+
protected $description = 'Backfill batch_uuid on activity_log based on created_at proximity.';
31+
32+
/**
33+
* [['id' => ..., 'batch_uuid' => ...], ...].
34+
*
35+
* @var array
36+
*/
37+
protected array $buffer = [];
38+
39+
/**
40+
* Execute the console command.
41+
*/
42+
public function handle(): int
43+
{
44+
$chunkSize = (int) $this->option('chunk');
45+
46+
$query = Activity::query()
47+
->whereNull('batch_uuid')
48+
->whereIn('log_name', ['catagraphy', 'vulnerabilities'])
49+
->orderBy('id')
50+
->without('causer', 'subject')
51+
->select(['id', 'log_name', 'subject_id', 'created_at']);
52+
53+
$currentCreatedAt = null;
54+
$currentSubjectId = null;
55+
$currentBatchUuid = null;
56+
57+
$total = 0;
58+
59+
$query->chunk($chunkSize, function (Collection $rows) use (
60+
&$currentCreatedAt,
61+
&$currentSubjectId,
62+
&$currentBatchUuid,
63+
$chunkSize,
64+
&$total
65+
): void {
66+
foreach ($rows as $row) {
67+
$currentSubjectId ??= $row->subject_id;
68+
$currentCreatedAt ??= $row->created_at;
69+
70+
if (
71+
$row->subject_id !== $currentSubjectId ||
72+
$row->created_at->notEqualTo($currentCreatedAt)
73+
) {
74+
$currentCreatedAt = $row->created_at;
75+
$currentSubjectId = $row->subject_id;
76+
$currentBatchUuid = Str::uuid7($currentCreatedAt)->toString();
77+
}
78+
79+
$this->buffer[] = [
80+
'id' => $row->id,
81+
'batch_uuid' => $currentBatchUuid,
82+
];
83+
84+
$total++;
85+
86+
if (\count($this->buffer) >= $chunkSize) {
87+
$this->flush();
88+
$this->info("Processed {$total} rows...");
89+
}
90+
}
91+
});
92+
93+
$this->flush();
94+
95+
$this->info("Done. Processed {$total} rows.");
96+
97+
return self::SUCCESS;
98+
}
99+
100+
protected function flush(): void
101+
{
102+
if (empty($this->buffer)) {
103+
return;
104+
}
105+
106+
$ids = array_column($this->buffer, 'id');
107+
108+
// Build CASE expression
109+
$cases = '';
110+
$bindings = [];
111+
112+
foreach ($this->buffer as $row) {
113+
$cases .= ' WHEN ? THEN ?';
114+
$bindings[] = $row['id'];
115+
$bindings[] = $row['batch_uuid'];
116+
}
117+
118+
// $bindings[] = end($ids);
119+
$sql = "UPDATE activity_log
120+
SET batch_uuid = CASE id {$cases} END
121+
WHERE id IN (" . implode(',', array_fill(0, \count($ids), '?')) . ')';
122+
123+
// Merge id bindings at the end
124+
$bindings = array_merge(
125+
$bindings,
126+
array_column($this->buffer, 'id'), // ids for CASE WHEN ? THEN ?
127+
);
128+
129+
if (! $this->option('dry-run')) {
130+
DB::update($sql, $bindings);
131+
} else {
132+
logger()->info('Dry run - would execute SQL:', ['sql' => $sql/* 'bindings' => $bindings */]);
133+
}
134+
135+
$this->buffer = [];
136+
}
137+
}

app/Filament/Resources/Beneficiaries/Resources/Catagraphies/Pages/EditCatagraphy.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use App\Models\Vulnerability\Vulnerability;
1313
use Filament\Resources\Pages\EditRecord;
1414
use Illuminate\Database\Eloquent\Model;
15+
use Illuminate\Support\Str;
16+
use Spatie\Activitylog\Facades\LogBatch;
1517

1618
class EditCatagraphy extends EditRecord
1719
{
@@ -75,4 +77,14 @@ protected function handleRecordUpdate(Model $record, array $data): Model
7577

7678
return $record;
7779
}
80+
81+
protected function beforeSave(): void
82+
{
83+
LogBatch::setBatch(Str::uuid7()->toString());
84+
}
85+
86+
protected function afterSave(): void
87+
{
88+
LogBatch::endBatch();
89+
}
7890
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Migrations\Migration;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
return new class extends Migration
10+
{
11+
public function up()
12+
{
13+
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
14+
$table->index('batch_uuid');
15+
});
16+
}
17+
};

0 commit comments

Comments
 (0)