[Workbench] Two legacy name-generation endpoints bypass generation_results and write to Redis instead #288
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the LLM trigger audit that produced #278 and #279.
The inconsistency
generation_serviceis the one genuinely well-factored part of the LLM layer: a data-drivenToolDefregistry (generation_service.py:1530-1663), one generic executor (run_tool,:301), one endpoint (campaigns.py:5235), and a persistence layer ingeneration_resultsthat the Workbench polls (added in #138).But two endpoints call
run_tooldirectly and never persist the result:campaigns.py:4302— name-cache miss path. Callsgeneration_service.run_tool(...), takesresult.output["options"], and writes it to Redis undername_cache:{campaign}:{category}with a TTL.sessions.py:290— the legacy session-scoped canonical-name endpoint. Same pattern.Both produce real LLM output that costs real tokens and then drops it outside the system of record.
Why it matters
generation_results. Name generations vanish when the Redis TTL expires.generation_results.token_usageis how spend is tracked. These two paths spend tokens invisibly.failedrow the UI can show.Counting them,
generation_servicehas six enqueue/execute paths hanging off it (sync inline, async Celery, cold-pool inline, and three prefetch refills) plus these two legacy bypasses. The registry is clean; the ways into it are not.Fix direction
Route both through the same persistence layer the rest of the Workbench uses, keeping the Redis cache as a cache in front of
generation_resultsrather than as the only place the output exists. The name-cache TTL behaviour can stay — it is a reasonable latency optimisation — but a cache miss should persist as well as cache.Worth checking whether the session-scoped endpoint at
sessions.py:290is still used by the frontend at all, or whether it was superseded by the campaign-scoped one and can simply be removed.Acceptance
generation_resultswith token usage recordedsessions.py:290either routed through persistence or removed if deadLabels: backend