isExtension() && $node->primary ? $node->primary : $node; } /** * @return Collection */ 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(); } }