order($run); // Idempotent: an instance already exists for this order. $existing = Instance::query()->where('order_id', $order->id)->first(); if ($existing !== null) { $this->putContext($run, $existing); return StepResult::advance(); } $plan = $this->plan($run); // Place + create under a per-datacenter lock so concurrent reservations // can't both pick the same host and overcommit its capacity. $instance = Cache::lock('placement:'.$order->datacenter, 30)->block(10, function () use ($order, $plan) { $host = Host::placeableIn($order->datacenter, (int) $plan['quota_gb']); if ($host === null) { return null; } return Instance::create([ 'customer_id' => $order->customer_id, 'order_id' => $order->id, 'host_id' => $host->id, 'plan' => $order->plan, 'quota_gb' => $plan['quota_gb'], 'disk_gb' => $plan['disk_gb'], 'ram_mb' => $plan['ram_mb'], 'cores' => $plan['cores'], 'subdomain' => $this->uniqueSubdomain($order), 'status' => 'reserving', ]); }); if ($instance === null) { return StepResult::fail('no_capacity'); } $this->putContext($run, $instance); $this->recordResource($run, $instance->host, 'instance_id', (string) $instance->id); return StepResult::advance(); } private function putContext(ProvisioningRun $run, Instance $instance): void { $run->mergeContext([ 'instance_id' => $instance->id, 'host_id' => $instance->host_id, 'node' => $instance->host?->node ?? 'pve', 'subdomain' => $instance->subdomain, 'plan' => $instance->plan, ]); } private function uniqueSubdomain(Order $order): string { $base = Str::slug($order->customer->name) ?: 'cloud'; do { $subdomain = $base.'-'.Str::lower(Str::random(5)); } while (Instance::query()->where('subdomain', $subdomain)->exists()); return $subdomain; } }