From c3bc2902f0f62485567491373331ea1a6ac3d7d1 Mon Sep 17 00:00:00 2001 From: Kevin L'Hereec Date: Fri, 17 Jul 2026 16:36:43 +0200 Subject: [PATCH] fix: add missing /internal/references routes and clean isGpnAllowed() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - start/routes.ts: mirror references routes into /internal group so the DeviceDetail.vue resolve buttons work (were returning 404) - device.ts: isGpnAllowed() now clears cooldownUntil when transitioning open→half-open, avoiding stale date in persisted snapshots --- app/domain/device/device.ts | 19 +++++++++++-------- start/routes.ts | 7 +++++++ 2 files changed, 18 insertions(+), 8 deletions(-) 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'])