Handle relay command job timeouts for edge gateways

- Introduce `expireTimedOutRelayStatusCommandJobs` to clean up long-pending relay status command jobs.
- Add `TIMED_OUT` status for relay command jobs and incorporate it into job status evaluations.
- Refactor command job finalization to support timeout-specific error messaging.
- Improve handling of fast-path failures in edge broker commands.
This commit is contained in:
Jeppe Bundgaard
2026-04-27 16:47:09 +02:00
parent 86eec9a51e
commit feb9aac4f7
16 changed files with 636 additions and 108 deletions
@@ -259,6 +259,58 @@ it('assembles tasks, logs, statistics, operations, commands, and shell lifecycle
}
});
it('persists gateway cutover relay bindings used by self-serve Shelly dispatch', function (): void {
$context = edge_gateway_integration_context();
try {
$department = $context['fixtures']->createDepartment([
'name' => 'Edge Integration Self Serve Relay Department',
]);
$user = $context['fixtures']->createUser([
'display_name' => 'Edge Integration Relay User',
]);
$token = $context['manager']->createInstallToken((int)$department['id'], 'Integration Relay Token', (int)$user['id']);
$claimed = $context['manager']->claimGateway((string)$token['token'], 'edge-relay-host', 'php-agent-v1');
$gatewayId = (int)($claimed['gateway']['id'] ?? 0);
$mode = $context['manager']->setDepartmentTransportMode(
(int)$department['id'],
edge_gateway_manager::TRANSPORT_MODE_GATEWAY,
(int)$user['id']
);
$bindings = $context['manager']->setRelayBindings($gatewayId, [[
'relay_id' => 'relay-machine',
'device_id' => 'device-machine',
'local_ip' => '10.50.60.70',
'channel' => 0,
'metadata' => [
'fallback_mode' => edge_gateway_manager::RELAY_FALLBACK_PREFER_LOCAL,
],
]], (int)$user['id']);
$resolved = $context['manager']->resolveRelayBinding((int)$department['id'], 'relay-machine');
expect($mode)->toHaveKey('transport_mode', edge_gateway_manager::TRANSPORT_MODE_GATEWAY)
->and($bindings)->toHaveCount(1)
->and($resolved)->toMatchArray([
'gateway_id' => $gatewayId,
'department_id' => (int)$department['id'],
'relay_id' => 'relay-machine',
'device_id' => 'device-machine',
'local_ip' => '10.50.60.70',
'channel' => 0,
'fallback_mode' => edge_gateway_manager::RELAY_FALLBACK_PREFER_LOCAL,
'metadata' => [
'fallback_mode' => edge_gateway_manager::RELAY_FALLBACK_PREFER_LOCAL,
],
])
->and($context['manager']->getDepartmentTransportMode((int)$department['id']))
->toBe(edge_gateway_manager::TRANSPORT_MODE_GATEWAY);
} finally {
$context['cleanup']->run();
}
});
/**
* @return array{cleanup:ApiCleanup,fixtures:ApiFixtures,manager:edge_gateway_manager,operations:edge_gateway_operation_service,mysqli:mysqli,redis:?PredisClient}
*/