payfrit-api/api/beacon-sharding/allocate_business_namespace.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.
2026-03-14 14:26:59 -07:00

74 lines
2.5 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
global $businessId;
$data = readJsonBody();
$bizId = $businessId;
if ($bizId <= 0) $bizId = (int) ($data['BusinessID'] ?? 0);
if ($bizId <= 0) {
apiAbort(['OK' => false, 'ERROR' => 'missing_business_id', 'MESSAGE' => 'BusinessID is required']);
}
try {
$qBiz = queryOne("SELECT ID, BeaconShardID, BeaconMajor FROM Businesses WHERE ID = ? LIMIT 1", [$bizId]);
if (!$qBiz) {
apiAbort(['OK' => false, 'ERROR' => 'invalid_business', 'MESSAGE' => 'Business not found']);
}
// Already allocated
if ((int) ($qBiz['BeaconShardID'] ?? 0) > 0 && $qBiz['BeaconMajor'] !== null) {
$qShard = queryOne("SELECT UUID FROM BeaconShards WHERE ID = ?", [(int) $qBiz['BeaconShardID']]);
jsonResponse([
'OK' => true,
'BusinessID' => $bizId,
'BeaconShardUUID' => $qShard['UUID'],
'BeaconMajor' => (int) $qBiz['BeaconMajor'],
'ShardID' => (int) $qBiz['BeaconShardID'],
'AlreadyAllocated' => true,
]);
}
// Find shard with lowest utilization
$qShard = queryOne("
SELECT ID, UUID, BusinessCount FROM BeaconShards
WHERE IsActive = 1 AND BusinessCount < MaxBusinesses
ORDER BY BusinessCount ASC LIMIT 1
", []);
if (!$qShard) {
apiAbort(['OK' => false, 'ERROR' => 'no_available_shards', 'MESSAGE' => 'All beacon shards are at capacity']);
}
$shardId = (int) $qShard['ID'];
$shardUUID = $qShard['UUID'];
$qMaxMajor = queryOne("
SELECT COALESCE(MAX(BeaconMajor), -1) AS MaxMajor FROM Businesses WHERE BeaconShardID = ?
", [$shardId]);
$nextMajor = (int) $qMaxMajor['MaxMajor'] + 1;
if ($nextMajor > 65535) {
apiAbort(['OK' => false, 'ERROR' => 'shard_full', 'MESSAGE' => 'Shard has reached maximum major value']);
}
queryTimed("
UPDATE Businesses SET BeaconShardID = ?, BeaconMajor = ?
WHERE ID = ? AND (BeaconShardID IS NULL OR BeaconMajor IS NULL)
", [$shardId, $nextMajor, $bizId]);
queryTimed("UPDATE BeaconShards SET BusinessCount = BusinessCount + 1 WHERE ID = ?", [$shardId]);
jsonResponse([
'OK' => true,
'BusinessID' => $bizId,
'BeaconShardUUID' => $shardUUID,
'BeaconMajor' => $nextMajor,
'ShardID' => $shardId,
'AlreadyAllocated' => false,
]);
} catch (Exception $e) {
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]);
}