fix(vision-manager): retain analysis-enabled gate alongside memory-yield
The analysis-disabled gate (stop/inhibit vision when Admin→Settings analysis is OFF, so stale queued jobs don't pin ~4.4GiB) was applied directly on the host and never committed, so it was absent from main and from this branch — merging as-is would have regressed it. Re-introduce it here so the merged manager has BOTH gates: vision is held down if analysis is disabled OR host memory is tight. Also grant the read-only role SELECT on app_settings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,20 @@ crawl_running() {
|
|||||||
AND state = 'running';" 2>/dev/null || echo "ERR"
|
AND state = 'running';" 2>/dev/null || echo "ERR"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Is the analysis subsystem enabled in Admin → Settings? The runtime source of
|
||||||
|
# truth is the `app_settings` row (key='analysis'), NOT the .env seed. When
|
||||||
|
# analysis is OFF the worker drains nothing, so leftover pending jobs would
|
||||||
|
# otherwise keep vision pinned forever — we must gate on this too, not just the
|
||||||
|
# queue depth. Returns the literal 'true'/'false'; 'ERR' (or anything else) on
|
||||||
|
# query failure is treated as enabled by the caller (fail-open: never yank
|
||||||
|
# vision out from under a live analysis on a transient DB hiccup).
|
||||||
|
analysis_enabled() {
|
||||||
|
"${PSQL[@]}" -c \
|
||||||
|
"SELECT CASE WHEN COALESCE((value->>'enabled')::boolean, false)
|
||||||
|
THEN 'true' ELSE 'false' END
|
||||||
|
FROM app_settings WHERE key = 'analysis';" 2>/dev/null || echo "ERR"
|
||||||
|
}
|
||||||
|
|
||||||
# ---- Memory pressure -------------------------------------------------------
|
# ---- Memory pressure -------------------------------------------------------
|
||||||
# Host-wide used% from MemAvailable (NOT MemFree, which sits near "full" thanks
|
# Host-wide used% from MemAvailable (NOT MemFree, which sits near "full" thanks
|
||||||
# to page cache and would false-trigger constantly). /proc/meminfo in this
|
# to page cache and would false-trigger constantly). /proc/meminfo in this
|
||||||
@@ -151,6 +165,7 @@ log "started: container=$VISION_CONTAINER health=$VISION_HEALTH_URL poll=${POLL_
|
|||||||
idle_for=0 # seconds the queue has been empty while vision is running
|
idle_for=0 # seconds the queue has been empty while vision is running
|
||||||
up_for=0 # seconds vision has been running (for MAX_UPTIME backstop)
|
up_for=0 # seconds vision has been running (for MAX_UPTIME backstop)
|
||||||
crawl_deferred=0 # 1 while a start is held off by the crawl mutex (log on flip only)
|
crawl_deferred=0 # 1 while a start is held off by the crawl mutex (log on flip only)
|
||||||
|
analysis_off=0 # 1 while analysis is disabled in settings (log on flip only)
|
||||||
mem_yield_until=0 # epoch deadline of the active memory-yield cooldown (0 = none)
|
mem_yield_until=0 # epoch deadline of the active memory-yield cooldown (0 = none)
|
||||||
mem_inhibited=0 # 1 while starts are inhibited by memory pressure (log on flip only)
|
mem_inhibited=0 # 1 while starts are inhibited by memory pressure (log on flip only)
|
||||||
|
|
||||||
@@ -169,6 +184,22 @@ while true; do
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# Gate on the runtime enable flag. If analysis is OFF, force the backlog to 0
|
||||||
|
# so the normal idle path runs the STOP_DEBOUNCE timer and shuts vision down.
|
||||||
|
# We deliberately reuse the idle debounce (rather than stopping instantly) so
|
||||||
|
# a quick toggle off→on inside the debounce window keeps vision warm — no
|
||||||
|
# cold reload for a momentary flip. Fail-open: only a literal 'false' counts
|
||||||
|
# as disabled; 'ERR'/empty leaves the real queue depth in effect.
|
||||||
|
if [ "$(analysis_enabled)" = "false" ]; then
|
||||||
|
if [ "$analysis_off" != "1" ]; then
|
||||||
|
log "analysis disabled in settings — ignoring ${pending} queued job(s); idle timer will stop vision"
|
||||||
|
analysis_off=1
|
||||||
|
fi
|
||||||
|
pending=0
|
||||||
|
else
|
||||||
|
analysis_off=0
|
||||||
|
fi
|
||||||
|
|
||||||
# Memory-yield gates (before the backlog logic). The active stop handles a
|
# Memory-yield gates (before the backlog logic). The active stop handles a
|
||||||
# running vision the idle path can't; the inhibit forces pending=0 so the
|
# running vision the idle path can't; the inhibit forces pending=0 so the
|
||||||
# existing idle-debounce path keeps it down (same shape as the crawl mutex).
|
# existing idle-debounce path keeps it down (same shape as the crawl mutex).
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ SELECT 'CREATE ROLE vision_manager LOGIN'
|
|||||||
-- (Re)set the password every run so rotating it is just a re-apply.
|
-- (Re)set the password every run so rotating it is just a re-apply.
|
||||||
ALTER ROLE vision_manager LOGIN PASSWORD :'pw';
|
ALTER ROLE vision_manager LOGIN PASSWORD :'pw';
|
||||||
|
|
||||||
-- CONNECT to the current database, and read-only on the one table we poll.
|
-- CONNECT to the current database, and read-only on the two tables we poll:
|
||||||
|
-- crawler_jobs (backlog depth + crawl-in-flight) and app_settings (the runtime
|
||||||
|
-- analysis-enabled flag — without this the manager can't tell that analysis was
|
||||||
|
-- turned off and would keep vision pinned on stale queued jobs).
|
||||||
GRANT CONNECT ON DATABASE :"DBNAME" TO vision_manager;
|
GRANT CONNECT ON DATABASE :"DBNAME" TO vision_manager;
|
||||||
GRANT USAGE ON SCHEMA public TO vision_manager;
|
GRANT USAGE ON SCHEMA public TO vision_manager;
|
||||||
GRANT SELECT ON crawler_jobs TO vision_manager;
|
GRANT SELECT ON crawler_jobs TO vision_manager;
|
||||||
|
GRANT SELECT ON app_settings TO vision_manager;
|
||||||
|
|||||||
Reference in New Issue
Block a user