Skip to content

feat(buyer-agent-registry): with_full_stack() — compose caching + rate-limiting + auditing in one factory #697

@bokelley

Description

@bokelley

Follow-up to #380 / #692.

Context

PgBuyerAgentRegistry.with_caching(**kwargs) shipped in #692 collapses cache wiring into one call. But the canonical production stack documented in registry_cache.py is three layers:

Caching(RateLimited(Auditing(inner)))

Adopters who want the full stack still hand-compose:

pg = PgBuyerAgentRegistry(pool=pool)
audited = AuditingBuyerAgentRegistry(pg, audit_sink=sink)
limited = RateLimitedBuyerAgentRegistry(audited, rps_per_tenant=100, audit_sink=sink)
cache = CachingBuyerAgentRegistry(limited, ttl_seconds=60, audit_sink=sink)
pg.add_mutation_observer(lambda _op, _url: cache.clear_sync())
serve(buyer_agent_registry=cache, ...)

The mutation-observer wiring at the end is the part most adopters will forget.

Proposed

registry = PgBuyerAgentRegistry(pool=pool).with_full_stack(
    ttl_seconds=60,
    max_entries=10_000,
    rps_per_tenant=100,
    audit_sink=sink,
)
serve(buyer_agent_registry=registry, ...)

Returns the outermost CachingBuyerAgentRegistry, pre-wired with the mutation observer, with audit_sink threaded through every layer that accepts one.

Tradeoffs

  • More opinionated than with_caching — fixes a layer order (`Cache -> RateLimit -> Audit -> inner`). Adopters who need a different order still go manual.
  • Worth doing because the current manual path is the most-foot-shootable section of the registry composition story.

Alternative considered

Stacking method-chained factories (pg.with_caching(...).with_rate_limiting(...).with_auditing(...)) reads nicely but inverts the layer order — Auditing would end up outermost, which is wrong for this use case. The single-call factory dodges that confusion.

Acceptance

  • with_full_stack(**kwargs) on PgBuyerAgentRegistry
  • audit_sink parameter threaded to all three wrapper layers (so cache/rate-limit/resolve events all emit)
  • Conformance test: mutation through pg invalidates cache; rate-limit fires on burst; audit events emitted at each layer
  • Docstring documents layer order and points to manual composition for non-default orderings

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions