diff --git a/.env.example b/.env.example index 31f1caf..e6ffdd6 100644 --- a/.env.example +++ b/.env.example @@ -21,3 +21,16 @@ INFLUXDB_TOKEN=mytoken123456789 INFLUXDB_ORG=mikrotik-manager INFLUXDB_BUCKET=metrics INFLUXDB_ADMIN_PASSWORD=admin_password_123 + +# ─── Poller tuning (see GET /api/system/poller) ────────────────────────────── +# Raise concurrency if `headroom` in the poller health endpoint drops near 1.0 — +# below that the queue grows every cycle and devices go stale. +# POLLER_CONCURRENCY=12 +# POLLER_JOB_TIMEOUT_MS=45000 +# POLLER_INTERVAL_MS=30000 +# POLLER_JOB_RETENTION_SEC=3600 +# POLLER_JOB_RETENTION_COUNT=5000 + +# Redis memory ceiling. Only TTL-bearing keys are evicted (volatile-lru), so +# queued jobs are never discarded; the cap exists to protect the host. +# REDIS_MAXMEMORY=512mb diff --git a/README.md b/README.md index f131f26..3da4552 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

- Version + Version License Docker TypeScript diff --git a/backend/package.json b/backend/package.json index fcb9841..d2636fa 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "mikrotik-manager-backend", - "version": "0.23.17-beta", + "version": "0.23.18-beta", "description": "Mikrotik Network Management Platform - Backend API", "main": "dist/index.js", "scripts": { diff --git a/backend/src/services/PollerService.ts b/backend/src/services/PollerService.ts index e36f86f..76ac9ba 100644 --- a/backend/src/services/PollerService.ts +++ b/backend/src/services/PollerService.ts @@ -159,12 +159,19 @@ export class PollerService { attempts: 3, backoff: { type: 'exponential', delay: 5000 }, }); + // Periodic polls are not retried in-job: the schedule is the retry. A device + // that just failed to answer is unlikely to answer a second later, and each + // extra attempt occupies a worker for up to the job timeout. On a fleet with + // several devices down that doubles the capacity they waste, which is exactly + // the capacity the rest of the fleet is short of (#114). Historically this + // also doubled the recorded failure count: 231k failed jobs on a four-device + // fleet turned out to be ~1,000 hours of genuine downtime, counted twice. } else if (type === 'fast') { - await this.fastQueue.add('device-fast-poll', jobData, { attempts: 2 }); + await this.fastQueue.add('device-fast-poll', jobData, { attempts: 1 }); } else if (type === 'slow') { - await this.slowQueue.add('device-slow-poll', jobData, { attempts: 2 }); + await this.slowQueue.add('device-slow-poll', jobData, { attempts: 1 }); } else if (type === 'logs') { - await this.logsQueue.add('device-logs-poll', jobData, { attempts: 2 }); + await this.logsQueue.add('device-logs-poll', jobData, { attempts: 1 }); } else if (type === 'macscan') { await this.fastQueue.add('device-macscan', jobData, { attempts: 1 }); } else if (type === 'spectral') { diff --git a/docker-compose.yml b/docker-compose.yml index 6fe9683..c48f867 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -85,7 +85,16 @@ services: redis: image: redis:7-alpine - command: redis-server --appendonly yes + # A memory ceiling so a runaway producer can never take the host down. The + # eviction policy is deliberately volatile-lru rather than allkeys-*: BullMQ + # job data carries no TTL and must never be evicted (that would silently + # destroy queued work), while the poller's caches and in-flight claims all + # set one and are safe to drop. If pressure ever exhausts the volatile keys + # Redis refuses writes instead of evicting queue state — loud, and survivable. + command: > + redis-server --appendonly yes + --maxmemory ${REDIS_MAXMEMORY:-512mb} + --maxmemory-policy volatile-lru volumes: - redis_data:/data restart: unless-stopped diff --git a/frontend/package.json b/frontend/package.json index 2d064da..822ff00 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mikrotik-manager-frontend", - "version": "0.23.17-beta", + "version": "0.23.18-beta", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 2252b75..a457959 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1 +1 @@ -export const APP_VERSION = 'v0.23.17 Beta'; +export const APP_VERSION = 'v0.23.18 Beta';