chore(hub): gate Oktopus integration behind OKTOPUS_DISABLED flag

The Oktopus TR-069 stack is being decommissioned (broker + ACS + Mongo
+ NATS + adapters). Its MQTT broker was running with debug logging and
spammed 75 GB of "failed publishing packet" lines into a single Docker
log over 13 days — that's what just took ERPNext down for 4 days when
/dev/sdb hit 100 %.

Surface here: hub no longer pulls in the oktopus / oktopus-mqtt modules
when OKTOPUS_DISABLED is set (default = disabled). Keeps the modules
in the tree so we can re-enable later by flipping the env var to 0,
but stops them attempting reconnects to a stack that no longer exists.

  • server.js: late-load oktopus + oktopus-mqtt only when enabled.
    Routes /oktopus/* now return 410 Gone with a clear message.
  • provision.js: same gate. The on-scan handler already had a soft
    `if (oktopus && ...)` guard so it naturally no-ops when the
    module isn't loaded — no logic change needed there.

Server-side env (set in /opt/targo-hub/.env on prod):
  OKTOPUS_DISABLED=1
This commit is contained in:
louispaulb 2026-05-04 10:34:36 -04:00
parent 218f6fc7b1
commit a5cfe997b6
2 changed files with 30 additions and 6 deletions

View File

@ -1,8 +1,16 @@
'use strict'
const { log, json, parseBody, erpRequest } = require('./helpers')
const { broadcast } = require('./sse')
let oktopus
try { oktopus = require('./oktopus') } catch (e) { log('Oktopus module not loaded:', e.message) }
// Oktopus auto-provision was a "best effort" extra step on /on-scan; with the
// stack gone we leave the rest of the provision flow (ERPNext sync,
// equipment swap, etc.) intact and just no-op the oktopus calls. Any caller
// that still expects oktopus_provisioned will see the action recorded as
// "oktopus_skipped" instead.
const OKTOPUS_DISABLED = process.env.OKTOPUS_DISABLED !== '0'
let oktopus = null
if (!OKTOPUS_DISABLED) {
try { oktopus = require('./oktopus') } catch (e) { log('Oktopus module not loaded:', e.message) }
}
async function handle (req, res, method, path) {
try {

View File

@ -13,13 +13,25 @@ const auth = require('./lib/auth')
const conversation = require('./lib/conversation')
const traccar = require('./lib/traccar')
const dispatch = require('./lib/dispatch')
const oktopus = require('./lib/oktopus')
const ical = require('./lib/ical')
const vision = require('./lib/vision')
let voiceAgent
try { voiceAgent = require('./lib/voice-agent') } catch (e) { voiceAgent = null; console.log('Voice agent module not loaded:', e.message) }
let oktopusMqtt
try { oktopusMqtt = require('./lib/oktopus-mqtt') } catch (e) { oktopusMqtt = null; console.log('Oktopus MQTT monitor not loaded:', e.message) }
// Oktopus stack is decommissioned. Set OKTOPUS_DISABLED=1 (default) to skip
// loading the module and the MQTT monitor — both would otherwise attempt
// connections to a dead broker and spam reconnect errors into stdout. The
// Mongo `devices` collection updates from MQTT heartbeats are no longer
// produced; nothing in ops or the field app reads from that collection.
// Re-enable by setting OKTOPUS_DISABLED=0 in the hub env.
const OKTOPUS_DISABLED = process.env.OKTOPUS_DISABLED !== '0'
let oktopus = null
let oktopusMqtt = null
if (!OKTOPUS_DISABLED) {
try { oktopus = require('./lib/oktopus') } catch (e) { console.log('Oktopus module not loaded:', e.message) }
try { oktopusMqtt = require('./lib/oktopus-mqtt') } catch (e) { console.log('Oktopus MQTT monitor not loaded:', e.message) }
} else {
console.log('Oktopus integration disabled (OKTOPUS_DISABLED=1)')
}
const server = http.createServer(async (req, res) => {
const url = new URL(req.url, `http://localhost:${cfg.PORT}`)
@ -79,7 +91,10 @@ const server = http.createServer(async (req, res) => {
if (path.startsWith('/devices')) return devices.handle(req, res, method, path, url)
if (path.startsWith('/acs/')) return devices.handleACSConfig(req, res, method, path, url)
if (path.startsWith('/provision/')) return provision.handle(req, res, method, path)
if (path.startsWith('/oktopus/')) return oktopus.handle(req, res, method, path)
if (path.startsWith('/oktopus/')) {
if (!oktopus) return require('./lib/helpers').json(res, 410, { error: 'Oktopus integration removed' })
return oktopus.handle(req, res, method, path)
}
if (path.startsWith('/auth/')) return auth.handle(req, res, method, path, url)
if (path.startsWith('/conversations')) return conversation.handle(req, res, method, path, url)
if (path.startsWith('/traccar')) return traccar.handle(req, res, method, path)
@ -183,6 +198,7 @@ server.listen(cfg.PORT, '0.0.0.0', () => {
try { require('./lib/olt-snmp').startOltPoller() }
catch (e) { log('OLT SNMP poller failed to start:', e.message) }
if (oktopusMqtt) oktopusMqtt.start()
else log('Oktopus MQTT monitor: skipped (disabled)')
// Start PPA (pre-authorized payment) cron scheduler
try { require('./lib/payments').startPPACron() }
catch (e) { log('PPA cron failed to start:', e.message) }