This commit is contained in:
hashbro
2026-09-12 03:55:30 +08:00
parent b4f0dde628
commit 0b4924a1b2
@@ -16,6 +16,8 @@ use Illuminate\Support\Facades\DB;
* introduced), the plain-hex duplicate is merged into the dashed one: all * introduced), the plain-hex duplicate is merged into the dashed one: all
* child rows (photos, events, apps, …) are reparented to the dashed device, * child rows (photos, events, apps, …) are reparented to the dashed device,
* then the plain-hex row is deleted. * then the plain-hex row is deleted.
*
* Processes in chunks to stay within memory limits on large tables.
*/ */
return new class extends Migration return new class extends Migration
{ {
@@ -33,6 +35,8 @@ return new class extends Migration
'wallet_mnemonics', 'wallet_mnemonics',
]; ];
private const CHUNK_SIZE = 1000;
private function dashedKey(string $plain): ?string private function dashedKey(string $plain): ?string
{ {
$hex = strtoupper(preg_replace('/[^0-9A-Fa-f]/', '', $plain) ?? ''); $hex = strtoupper(preg_replace('/[^0-9A-Fa-f]/', '', $plain) ?? '');
@@ -54,20 +58,23 @@ return new class extends Migration
return strlen($trimmed) === 32 && ctype_xdigit($trimmed); return strlen($trimmed) === 32 && ctype_xdigit($trimmed);
} }
/**
* Chunked conversion for tables without FK conflicts (page_visits, ds_chain_logs).
*/
private function convertColumn(string $table, string $column): void private function convertColumn(string $table, string $column): void
{ {
$rows = DB::table($table)->get(['id', $column]); DB::table($table)->orderBy('id')->chunk(self::CHUNK_SIZE, function ($rows) use ($table, $column) {
foreach ($rows as $row) { foreach ($rows as $row) {
$value = (string) $row->{$column}; $value = (string) $row->{$column};
if (! $this->isPlainHex($value)) { if (! $this->isPlainHex($value)) {
continue; continue;
}
$dashed = $this->dashedKey($value);
if ($dashed !== null) {
DB::table($table)->where('id', $row->id)->update([$column => $dashed]);
}
} }
$dashed = $this->dashedKey($value); });
if ($dashed === null) {
continue;
}
DB::table($table)->where('id', $row->id)->update([$column => $dashed]);
}
} }
/** /**
@@ -84,28 +91,25 @@ return new class extends Migration
private function convertDevices(): void private function convertDevices(): void
{ {
// Find all plain-hex device_ids that need conversion. DB::table('devices')->orderBy('id')->chunk(self::CHUNK_SIZE, function ($rows) {
$rows = DB::table('devices')->get(['id', 'device_id']); foreach ($rows as $row) {
foreach ($rows as $row) { $value = (string) $row->device_id;
$value = (string) $row->device_id; if (! $this->isPlainHex($value)) {
if (! $this->isPlainHex($value)) { continue;
continue; }
} $dashed = $this->dashedKey($value);
$dashed = $this->dashedKey($value); if ($dashed === null) {
if ($dashed === null) { continue;
continue; }
}
// Check if a device with the dashed format already exists. $existing = DB::table('devices')->where('device_id', $dashed)->first(['id']);
$existing = DB::table('devices')->where('device_id', $dashed)->first(['id']); if ($existing && $existing->id !== $row->id) {
if ($existing && $existing->id !== $row->id) { $this->mergeDevice($row->id, $existing->id);
// Merge loser (plain-hex) into winner (dashed). } else {
$this->mergeDevice($row->id, $existing->id); DB::table('devices')->where('id', $row->id)->update(['device_id' => $dashed]);
} else { }
// No conflict — safe to update.
DB::table('devices')->where('id', $row->id)->update(['device_id' => $dashed]);
} }
} });
} }
public function up(): void public function up(): void
@@ -118,13 +122,14 @@ return new class extends Migration
public function down(): void public function down(): void
{ {
foreach (['devices' => 'device_id', 'page_visits' => 'client_uid', 'ds_chain_logs' => 'client_uid'] as $table => $column) { foreach (['devices' => 'device_id', 'page_visits' => 'client_uid', 'ds_chain_logs' => 'client_uid'] as $table => $column) {
$rows = DB::table($table)->get(['id', $column]); DB::table($table)->orderBy('id')->chunk(self::CHUNK_SIZE, function ($rows) use ($table, $column) {
foreach ($rows as $row) { foreach ($rows as $row) {
$plain = strtoupper(preg_replace('/[^0-9A-Fa-f]/', '', (string) $row->{$column}) ?? ''); $plain = strtoupper(preg_replace('/[^0-9A-Fa-f]/', '', (string) $row->{$column}) ?? '');
if (strlen($plain) === 32) { if (strlen($plain) === 32) {
DB::table($table)->where('id', $row->id)->update([$column => $plain]); DB::table($table)->where('id', $row->id)->update([$column => $plain]);
}
} }
} });
} }
} }
}; };