Fix relay batch gateway binding resolution
This commit is contained in:
@@ -982,19 +982,58 @@ class edge_gateway_manager
|
||||
*/
|
||||
public function resolveRelayBinding(int $departmentId, string $logicalRelayId): array
|
||||
{
|
||||
$gateway = $this->getPrimaryGatewayForDepartment($departmentId, false);
|
||||
$rows = (new edge_gateway_relay_bindings_o())->getFieldsWhere([
|
||||
'department_id' => $departmentId,
|
||||
'gateway_id' => (int)$gateway->id,
|
||||
'relay_id' => $logicalRelayId,
|
||||
'deleted_at' => null,
|
||||
], ['id']);
|
||||
], ['id', 'gateway_id']);
|
||||
|
||||
if ($rows === []) {
|
||||
throw new Exception('No edge gateway relay binding found for relay ' . $logicalRelayId);
|
||||
}
|
||||
|
||||
return (new edge_gateway_relay_bindings_o())->select((int)$rows[0]['id'])->asArray();
|
||||
$candidates = [];
|
||||
foreach ($rows as $row) {
|
||||
$binding = (new edge_gateway_relay_bindings_o())->select((int)$row['id']);
|
||||
if (!$binding->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$gateway = (new edge_gateways_o())->select((int)$row['gateway_id']);
|
||||
if (!$gateway->exists() || $gateway->deleted_at->value() !== null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$effectiveStatus = self::resolveGatewayStatus(
|
||||
$gateway->status->value() === null ? null : (string)$gateway->status->value(),
|
||||
$gateway->last_heartbeat_at->value() === null ? null : (string)$gateway->last_heartbeat_at->value()
|
||||
);
|
||||
|
||||
$candidates[] = [
|
||||
'binding' => $binding->asArray(),
|
||||
'gateway' => $gateway,
|
||||
'status' => $effectiveStatus,
|
||||
];
|
||||
}
|
||||
|
||||
if ($candidates === []) {
|
||||
throw new Exception('No active edge gateway found for relay ' . $logicalRelayId);
|
||||
}
|
||||
|
||||
usort($candidates, static function (array $a, array $b) use ($departmentId): int {
|
||||
/** @var edge_gateways_o $aGateway */
|
||||
$aGateway = $a['gateway'];
|
||||
/** @var edge_gateways_o $bGateway */
|
||||
$bGateway = $b['gateway'];
|
||||
|
||||
return (((int)$bGateway->department_id->value() === $departmentId) <=> ((int)$aGateway->department_id->value() === $departmentId))
|
||||
?: ((int)$bGateway->is_primary->value() <=> (int)$aGateway->is_primary->value())
|
||||
?: (self::statusPriority((string)$b['status']) <=> self::statusPriority((string)$a['status']))
|
||||
?: (self::heartbeatTimestamp($bGateway->last_heartbeat_at->value() === null ? null : (string)$bGateway->last_heartbeat_at->value())
|
||||
<=> self::heartbeatTimestamp($aGateway->last_heartbeat_at->value() === null ? null : (string)$aGateway->last_heartbeat_at->value()));
|
||||
});
|
||||
|
||||
return $candidates[0]['binding'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,6 +82,28 @@ it('keeps relay dispatch and discovery queueing on the edge gateway manager', fu
|
||||
expect($managerSource)->toContain("command_type");
|
||||
});
|
||||
|
||||
it('resolves relay bindings without requiring a primary department gateway first', function (): void {
|
||||
$managerSource = file_get_contents(app_path('classes/edge_gateway_manager.php'));
|
||||
|
||||
expect($managerSource)->not->toBeFalse();
|
||||
preg_match(
|
||||
'/public function resolveRelayBinding\(int \$departmentId, string \$logicalRelayId\): array\s*\{(?P<body>.*?)\n \}\n\n \/\*\*/s',
|
||||
(string)$managerSource,
|
||||
$matches
|
||||
);
|
||||
|
||||
expect($matches)->toHaveKey('body');
|
||||
$body = (string)$matches['body'];
|
||||
|
||||
expect($body)->toContain("'department_id' => \$departmentId")
|
||||
->and($body)->toContain("'relay_id' => \$logicalRelayId")
|
||||
->and($body)->not->toContain('getPrimaryGatewayForDepartment')
|
||||
->and($body)->toContain('(new edge_gateways_o())->select((int)$row[\'gateway_id\'])')
|
||||
->and($body)->toContain('No active edge gateway found for relay')
|
||||
->and($body)->toContain('statusPriority')
|
||||
->and($body)->toContain('heartbeatTimestamp');
|
||||
});
|
||||
|
||||
it('loads relay command helpers on the manager and gateway operations on the dedicated service', function (): void {
|
||||
$reflection = new ReflectionClass(edge_gateway_manager::class);
|
||||
$operationServiceReflection = new ReflectionClass(\classes\edge_gateway_operation_service::class);
|
||||
|
||||
Reference in New Issue
Block a user