Initial Ladill Hosting app with Gitea deploy pipeline.
Deploy Ladill Hosting / deploy (push) Failing after 17s
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>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user