fix(worker-ai-health): address feedback on health status and cache handling

- Add checks for 'not_configured' and 'unavailable' states in Snapshot#status
- Include PDF probe failure codes in failure_codes detection
- Fix cache lifetime extension by removing expires_in and filtering expired entries in recent()

Ensures unconfigured workers and missing PDF pipelines are marked as failing,
and stale cache entries don't get indefinite TTL refreshes.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9494Pxh4LZKnNLTGfFXPw
This commit is contained in:
Jonathan Kaiser
2026-09-02 07:15:54 +02:00
committed by Juan José Mata
co-authored by Claude Haiku 4.5
parent 9906dd7b09
commit 1a7b664d05
2 changed files with 10 additions and 4 deletions
+2
View File
@@ -52,6 +52,8 @@ class WorkerAiHealthCheckJob < ApplicationJob
[
ai_health.llm_probe.failure_code,
ai_health.function_calling_probe.failure_code,
ai_health.pdf_text_extraction_probe.failure_code,
ai_health.pdf_vision_processing_probe.failure_code,
ai_health.vector_store_probe.failure_code,
ai_health.embedding_probe.failure_code
].compact.uniq
+8 -4
View File
@@ -58,8 +58,8 @@ class WorkerAiHealth
def status
return :stale if stale?
return :failing if failure_codes.present?
return :failing if llm_status == :failing || vector_store_status == :failing
return :failing if function_calling_status.in?(%i[unsupported failing])
return :failing if llm_status.in?(%i[not_configured failing]) || vector_store_status.in?(%i[not_configured failing])
return :failing if function_calling_status.in?(%i[unavailable unsupported failing])
:passing
end
@@ -100,7 +100,8 @@ class WorkerAiHealth
def record!(snapshot, cache: Rails.cache)
results = recent(cache: cache).reject { |r| r.process_identity == snapshot.process_identity }
results = [ snapshot, *results ].first(MAX_RESULTS)
cache.write(CACHE_KEY, results, expires_in: RETENTION)
# Don't set expires_in here; let individual entries expire via checked_at time
cache.write(CACHE_KEY, results)
snapshot
end
@@ -109,7 +110,10 @@ class WorkerAiHealth
# STALE_AFTER are still returned (status: :stale) so an operator can see
# a worker went quiet rather than the section going empty.
def recent(cache: Rails.cache)
Array(cache.read(CACHE_KEY)).sort_by { |r| r.checked_at || Time.at(0) }.reverse
results = Array(cache.read(CACHE_KEY))
# Filter out entries older than RETENTION
results = results.select { |r| r.checked_at && r.checked_at > RETENTION.ago }
results.sort_by { |r| r.checked_at || Time.at(0) }.reverse
end
# Stable identity for "this OS process" -- hostname:pid. Good enough to