feat: 18
This commit is contained in:
@@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user