On-demand category resolver added in Task 3 of the autotrade-foundation branch. Provides a cache-hit-or-fetch path for resolving an event’s category bucket at trade-decision time, complementing the batch run_category_sync refresh.

Two New Functions

read_event_categorypmv2/repo.rs

Cache-read function: given a pool and an event_slug, returns Option<String> by querying pmv2_event_category for the cached bucket label.

  • Uses sqlx::query_as runtime style (no compile-time macros), consistent with the rest of the autotrade config/repo layer where no live DB is required at build time.
  • Returns None on a cache miss — the caller decides whether to fetch from gamma.

resolve_categorypmv2/category.rs

Cache-hit-or-fetch resolver. Full decision tree:

  1. Call read_event_category(pool, event_slug) — on a hit, return Ok(Some(bucket)) immediately.
  2. On a miss, call gamma.event_tags(&[slug]) to fetch tags from the gamma /events endpoint.
  3. Pass the returned tags through the frozen category_bucket function to map to a bucket label.
  4. Call upsert_event_category to write the result back to cache.
  5. Return Ok(None) if gamma does not recognise the slug (no tags returned).

Key Patterns and Gotchas

#[allow(dead_code)] on Both Functions

Both functions carry #[allow(dead_code)] because they are wired up in T4 (category gate) and T8 (final plumbing). T8 removes both allows once the callers are compiled in.

Temporary Binding for event_tags Lifetime

GammaClient::event_tags takes &[String]. Passing a temporary constructed inline causes a “temporary does not live long enough” compiler error. The fix is to bind the slice first:

let slugs = [event_slug.to_string()];
gamma.event_tags(&slugs).await

Import for GammaClient

GammaClient lives in the polymarket_data crate — import it with:

use polymarket_data::GammaClient;

No Staleness Logic in the On-Demand Path

resolve_category has no staleness check or TTL. Cache refreshes are handled entirely by the batch run_category_sync scheduled step. The on-demand resolver is purely additive: read cache → if miss, populate cache.

Relationship to the Category System

For Agents

The category system has two entry points:

  • Batch refreshrun_category_sync fetches gamma tags for known event slugs on a schedule; populates pmv2_event_category.
  • On-demand resolver (this note) — resolve_category fetches only the one slug needed right now; used by the autotrade engine gate to categorise an incoming trade signal. Both write through upsert_event_category to the same cache table.

The frozen category_bucket function is shared between both paths and must not be changed without re-validating every consumer (the /topbets filters, the category consensus filter, and the autotrade category gate all depend on its output).