Deploy Ladill Hosting / deploy (push) Failing after 17s
Shared web hosting extracted from the platform monolith, with CI deploy to /var/www/ladill-hosting matching Bird/Domains/Email. Co-authored-by: Cursor <cursoragent@cursor.com>
87 lines
2.5 KiB
PHP
87 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Hosting;
|
|
|
|
use App\Models\HostingAccount;
|
|
use App\Models\HostingNode;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class HostingNodePoolService
|
|
{
|
|
public function poolRoot(HostingNode $node): HostingNode
|
|
{
|
|
return $node->isExtension() && $node->primary
|
|
? $node->primary
|
|
: $node;
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, HostingNode>
|
|
*/
|
|
public function poolMembers(HostingNode $node): Collection
|
|
{
|
|
$root = $this->poolRoot($node);
|
|
|
|
return HostingNode::query()
|
|
->where(function ($query) use ($root) {
|
|
$query->where('id', $root->id)
|
|
->orWhere('primary_hosting_node_id', $root->id);
|
|
})
|
|
->where('type', HostingNode::TYPE_SHARED)
|
|
->whereNotIn('status', [HostingNode::STATUS_DECOMMISSIONED])
|
|
->orderBy('role')
|
|
->get();
|
|
}
|
|
|
|
public function poolDiskGb(HostingNode $node): int
|
|
{
|
|
return (int) $this->poolMembers($node)->sum('disk_gb');
|
|
}
|
|
|
|
public function poolLogicalCapacityGb(HostingNode $node): float
|
|
{
|
|
return round($this->poolMembers($node)->sum(fn (HostingNode $m) => $m->logicalCapacityGb()), 2);
|
|
}
|
|
|
|
public function poolAllocatedDiskGb(HostingNode $node): int
|
|
{
|
|
$memberIds = $this->poolMembers($node)->pluck('id');
|
|
|
|
return (int) HostingAccount::query()
|
|
->whereIn('hosting_node_id', $memberIds)
|
|
->where('type', HostingAccount::TYPE_SHARED)
|
|
->sum('allocated_disk_gb');
|
|
}
|
|
|
|
public function poolUsedDiskGb(HostingNode $node): int
|
|
{
|
|
$memberIds = $this->poolMembers($node)->pluck('id');
|
|
|
|
$bytes = (int) HostingAccount::query()
|
|
->whereIn('hosting_node_id', $memberIds)
|
|
->where('type', HostingAccount::TYPE_SHARED)
|
|
->sum('disk_used_bytes');
|
|
|
|
return (int) ceil($bytes / 1073741824);
|
|
}
|
|
|
|
/**
|
|
* Member node with the most room for a new shared account.
|
|
*/
|
|
public function findProvisioningMember(HostingNode $poolRoot, int $requestedDiskGb = 0, ?string $segment = null): ?HostingNode
|
|
{
|
|
$members = $this->poolMembers($poolRoot)
|
|
->filter(fn (HostingNode $n) => $n->canProvision($requestedDiskGb, $segment));
|
|
|
|
if ($members->isEmpty()) {
|
|
return null;
|
|
}
|
|
|
|
return $members->sortBy(fn (HostingNode $n) => sprintf(
|
|
'%012.2f-%012d',
|
|
(float) $n->current_load_percent,
|
|
$n->used_disk_gb,
|
|
))->first();
|
|
}
|
|
}
|