diff --git a/app/domain/device/device.ts b/app/domain/device/device.ts index a7b32c3..3768830 100644 --- a/app/domain/device/device.ts +++ b/app/domain/device/device.ts @@ -128,17 +128,20 @@ export class Device { /** * Returns true if GPN is allowed based on circuit breaker state. - * Closed = always allowed. Half-open = allowed if cooldown expired. Open = not allowed. + * Closed = always allowed. Half-open = allowed (cooldown expired probe). + * Open → transitions to half-open when cooldown expires (clears cooldownUntil). + * + * NOTE: the open→half-open transition mutates state but does NOT persist to DB. + * The caller (IdleState) is responsible for persisting if needed. */ public isGpnAllowed(): boolean { - const { state, cooldownUntil } = this._gpnCircuitBreaker - if (state === 'closed') return true - if (state === 'half-open') { - return cooldownUntil === null || new Date() >= cooldownUntil - } + const cb = this._gpnCircuitBreaker + if (cb.state === 'closed') return true + if (cb.state === 'half-open') return true // state === 'open': check if cooldown expired → transition to half-open - if (cooldownUntil && new Date() >= cooldownUntil) { - this._gpnCircuitBreaker.state = 'half-open' + if (cb.cooldownUntil && new Date() >= cb.cooldownUntil) { + cb.state = 'half-open' + cb.cooldownUntil = null // clear stale cooldown so snapshot is clean return true } return false diff --git a/start/routes.ts b/start/routes.ts index 2cf6c15..8e04f8c 100644 --- a/start/routes.ts +++ b/start/routes.ts @@ -97,6 +97,13 @@ router router.post('/devices/:identifier/command', [DevicesController, 'executeCommand']) router.post('/devices/:identifier/refresh', [DevicesController, 'refresh']) + // References + const ReferencesController = () => import('#controllers/references_controller') + router.get('/devices/:identifier/references', [ReferencesController, 'index']) + router.get('/devices/:identifier/references/:provider', [ReferencesController, 'show']) + router.post('/devices/:identifier/references/resolve', [ReferencesController, 'resolveAll']) + router.post('/devices/:identifier/references/resolve/:provider', [ReferencesController, 'resolveOne']) + // Commands router.get('/commands', [CommandsController, 'index']) router.get('/commands/:id', [CommandsController, 'show'])