Files
ladill-servers/app/Jobs/MigrateHostingAccountJob.php
isaaccladandCursor b6c8ac343f Extract Ladill Servers as standalone app at servers.ladill.com.
VPS and dedicated server ordering, managed panels, SSO, billing, and launcher integration — forked from hosting infrastructure with server-focused routes and dashboard.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 19:18:30 +00:00

110 lines
3.7 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\HostingAccount;
use App\Models\HostingNode;
use App\Services\Hosting\Providers\SharedNodeProvider;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
class MigrateHostingAccountJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $timeout = 3600; // 1 hour timeout for large migrations
public int $tries = 1; // Don't retry migrations automatically
public function __construct(
public int $accountId,
public int $destinationNodeId,
public ?int $initiatedBy = null
) {}
public function handle(SharedNodeProvider $provider): void
{
$account = HostingAccount::with(['node', 'sites', 'databases'])->find($this->accountId);
$destinationNode = HostingNode::find($this->destinationNodeId);
if (!$account) {
Log::error("Migration job failed: Account {$this->accountId} not found");
return;
}
if (!$destinationNode) {
Log::error("Migration job failed: Destination node {$this->destinationNodeId} not found");
return;
}
$sourceNode = $account->node;
$sourceNodeId = $sourceNode?->id;
Log::info("Starting migration job for account {$account->username}", [
'account_id' => $account->id,
'source_node' => $sourceNode?->name,
'destination_node' => $destinationNode->name,
'initiated_by' => $this->initiatedBy,
]);
try {
// Update account status to migrating
$account->update(['status' => 'migrating']);
// Perform the migration
$result = $provider->migrateAccount($account, $destinationNode, function ($message) use ($account) {
Log::info("Migration progress [{$account->username}]: {$message}");
});
// Update account with new node
DB::transaction(function () use ($account, $destinationNode, $sourceNodeId) {
$account->update([
'hosting_node_id' => $destinationNode->id,
'status' => 'active',
]);
// Update node account counts
$destinationNode->incrementAccountCount();
if ($sourceNodeId) {
HostingNode::where('id', $sourceNodeId)->decrement('current_accounts');
}
});
Log::info("Migration completed successfully for account {$account->username}", [
'account_id' => $account->id,
'new_node' => $destinationNode->name,
]);
} catch (\Throwable $e) {
Log::error("Migration failed for account {$account->username}: " . $e->getMessage(), [
'account_id' => $account->id,
'exception' => $e,
]);
// Revert status
$account->update(['status' => 'active']);
throw $e;
}
}
public function failed(\Throwable $exception): void
{
Log::error("Migration job failed permanently for account {$this->accountId}", [
'destination_node' => $this->destinationNodeId,
'error' => $exception->getMessage(),
]);
// Try to revert account status
$account = HostingAccount::find($this->accountId);
if ($account && $account->status === 'migrating') {
$account->update(['status' => 'active']);
}
}
}