Class: Woods::Cache::CachedRetriever

Inherits:
Object
  • Object
show all
Defined in:
lib/woods/cache/cache_middleware.rb

Overview

Decorator that wraps a Retriever with result caching.

Caches the full formatted context output (the most token-expensive artifact) keyed by query + budget. Also caches the structural context overview separately with a longer TTL.

Examples:

retriever = Woods::Retriever.new(...)
cached = CachedRetriever.new(retriever: retriever, cache_store: store)
cached.retrieve("How does User work?")  # full pipeline + cache
cached.retrieve("How does User work?")  # instant cache hit

Instance Method Summary collapse

Constructor Details

#initialize(retriever:, cache_store:, context_ttl: ) ⇒ CachedRetriever

Returns a new instance of CachedRetriever.

Parameters:

  • retriever (Retriever)

    The real retriever instance

  • cache_store (CacheStore)

    Cache backend instance

  • context_ttl (Integer) (defaults to: )

    TTL for formatted context results



385
386
387
388
389
# File 'lib/woods/cache/cache_middleware.rb', line 385

def initialize(retriever:, cache_store:, context_ttl: DEFAULT_TTLS[:context])
  @retriever = retriever
  @cache_store = cache_store
  @context_ttl = context_ttl
end

Instance Method Details

#graph_storeObject



398
# File 'lib/woods/cache/cache_middleware.rb', line 398

def graph_store    = @retriever.graph_store

#invalidate_context_cache!void

This method returns an undefined value.

Invalidate every cached context result. Called from the MCP reload tool after the retriever’s stores have been re-hydrated from a fresh embed — otherwise cached results from the old embedding run would linger until their TTL expires and contradict the new stores.

Embedding caches (query → vector) are NOT cleared: the query-vector mapping is deterministic for a given provider+model and survives any index reload. Only context results (query → ranked units) go stale.



410
411
412
413
414
# File 'lib/woods/cache/cache_middleware.rb', line 410

def invalidate_context_cache!
  @cache_store.clear(namespace: :context)
rescue StandardError => e
  warn("[Woods] CachedRetriever context-cache invalidation failed: #{e.message}")
end

#metadata_storeObject



397
# File 'lib/woods/cache/cache_middleware.rb', line 397

def  = @retriever.

#retrieve(query, budget: 8000, types: nil, exclude_types: nil) ⇒ Retriever::RetrievalResult

Execute the retrieval pipeline with context-level caching.

On cache hit, returns a RetrievalResult reconstructed from cached data without running any pipeline stages. On miss, delegates to the real retriever and caches the serializable parts of the result.

Cache key includes types: / exclude_types: so a run with a narrower type filter doesn’t return a broader-filter cached result.

Parameters:

  • query (String)

    Natural language query

  • budget (Integer) (defaults to: 8000)

    Token budget

  • types (Array<String, Symbol>, nil) (defaults to: nil)

    Include-only filter

  • exclude_types (Array<String, Symbol>, nil) (defaults to: nil)

    Additional exclusions

Returns:



430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/woods/cache/cache_middleware.rb', line 430

def retrieve(query, budget: 8000, types: nil, exclude_types: nil)
  key = context_key(query, budget, types: types, exclude_types: exclude_types)
  cached = @cache_store.read(key)
  return rehydrate_cached(cached, budget) if cached

  result = @retriever.retrieve(query, budget: budget, types: types, exclude_types: exclude_types)

  begin
    @cache_store.write(key, serialize_result(result), ttl: @context_ttl)
  rescue StandardError => e
    warn("[Woods] CachedRetriever cache write failed: #{e.message}")
  end

  result
end

#vector_storeObject

Expose the wrapped stores so the MCP reload tool and MCP::Bootstrapper.reload_stores! can re-hydrate caches in place regardless of whether caching is enabled. Without these delegations, reload is a silent no-op when cache_enabled is true —the bootstrapper would see nil stores on the wrapper and skip.



396
# File 'lib/woods/cache/cache_middleware.rb', line 396

def vector_store   = @retriever.vector_store