Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/ad_seller/services/catalog_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,15 @@ def build_static_product_catalog() -> dict[str, Any]:
"""Build a fresh catalog dict from ``DEFAULT_PRODUCT_CONFIGS`` (uncached).

Returns ``{"products": {product_id: ProductDefinition}, "inventory_types": [...]}``
with newly generated product IDs.
with deterministic product IDs derived from each config's name, so every
process (and every uvicorn worker) serves the same ids. Random per-process
ids meant a list-then-get across two workers, or across a restart, could
404 on an id the server itself had just returned (issue #34).
"""
products: dict[str, Any] = {}
for cfg in DEFAULT_PRODUCT_CONFIGS:
product_def = product_from_config(cfg, f"prod-{uuid.uuid4().hex[:8]}")
stable = uuid.uuid5(uuid.NAMESPACE_URL, f"ad-seller-product:{cfg['name']}")
product_def = product_from_config(cfg, f"prod-{stable.hex[:8]}")
products[product_def.product_id] = product_def

inventory_types = sorted({p.inventory_type for p in products.values()})
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/test_csv_catalog_coherence.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ def test_default_mode_ids_stay_uuid_shaped_and_stable(self, default_mode):
second = catalog_service.get_static_product_catalog()
assert list(first["products"].keys()) == list(second["products"].keys())

def test_default_mode_ids_survive_cache_reset(self, default_mode):
# Proxy for multi-worker and restart behavior (issue #34): each uvicorn
# worker builds its own catalog cache, so ids must be deterministic
# across independent builds, not merely stable within one cache.
first = catalog_service.get_static_product_catalog()
catalog_service.reset_catalog_cache()
second = catalog_service.get_static_product_catalog()
assert list(first["products"].keys()) == list(second["products"].keys())
assert len(set(first["products"])) == len(catalog_service.DEFAULT_PRODUCT_CONFIGS)


# =============================================================================
# API surface — CSV mode
Expand Down
Loading