diff --git a/app/platforms/ebay/adapter.py b/app/platforms/ebay/adapter.py index 2ecb07d..c3ddd18 100644 --- a/app/platforms/ebay/adapter.py +++ b/app/platforms/ebay/adapter.py @@ -22,7 +22,7 @@ _SHOPPING_API_INTER_REQUEST_DELAY = 0.5 # seconds between successive calls _SELLER_ENRICH_TTL_HOURS = 24 # skip re-enrichment within this window from app.db.models import Listing, MarketComp, Seller -from app.db.store import Store +from app.db.protocol import SharedTableProtocol from app.platforms import PlatformAdapter, SearchFilters from app.platforms.ebay.auth import EbayTokenManager from app.platforms.ebay.normaliser import normalise_listing, normalise_seller @@ -67,7 +67,7 @@ BROWSE_BASE = { class EbayAdapter(PlatformAdapter): - def __init__(self, token_manager: EbayTokenManager, shared_store: Store, env: str = "production"): + def __init__(self, token_manager: EbayTokenManager, shared_store: SharedTableProtocol, env: str = "production"): self._tokens = token_manager self._store = shared_store self._env = env diff --git a/app/platforms/ebay/scraper.py b/app/platforms/ebay/scraper.py index ca136c2..92393c0 100644 --- a/app/platforms/ebay/scraper.py +++ b/app/platforms/ebay/scraper.py @@ -25,7 +25,7 @@ log = logging.getLogger(__name__) from bs4 import BeautifulSoup from app.db.models import Listing, MarketComp, Seller -from app.db.store import Store +from app.db.protocol import SharedTableProtocol from app.platforms import PlatformAdapter, SearchFilters EBAY_SEARCH_URL = "https://www.ebay.com/sch/i.html" @@ -286,7 +286,7 @@ class ScrapedEbayAdapter(PlatformAdapter): category_history) cause TrustScorer to set score_is_partial=True. """ - def __init__(self, shared_store: Store, delay: float = 1.0): + def __init__(self, shared_store: SharedTableProtocol, delay: float = 1.0): self._store = shared_store self._delay = delay @@ -374,8 +374,6 @@ class ScrapedEbayAdapter(PlatformAdapter): Does not raise — failures per-seller are silently skipped so the main search response is never blocked. """ - db_path = self._store._db_path # capture for thread-local Store creation - def _enrich_one(item: tuple[str, str]) -> None: seller_id, listing_id = item try: @@ -388,7 +386,7 @@ class ScrapedEbayAdapter(PlatformAdapter): ) if age_days is None and fb_count is None: return # nothing new to write - thread_store = Store(db_path) + thread_store = self._store.clone() seller = thread_store.get_seller("ebay", seller_id) if not seller: log.warning("BTF enrich: seller %s not found in DB", seller_id) diff --git a/tests/db/test_protocol.py b/tests/db/test_protocol.py index 97349fd..c369b84 100644 --- a/tests/db/test_protocol.py +++ b/tests/db/test_protocol.py @@ -14,3 +14,26 @@ def test_store_clone_returns_new_instance(tmp_path): assert isinstance(clone, Store) assert clone is not s assert clone._db_path == db + + +def test_ebay_adapter_accepts_protocol(): + from app.platforms.ebay.adapter import EbayAdapter + import tempfile + import pathlib + from unittest.mock import MagicMock + + with tempfile.TemporaryDirectory() as tmp: + s = Store(pathlib.Path(tmp) / "t.db") + adapter = EbayAdapter(token_manager=MagicMock(), shared_store=s) + assert adapter._store is s + + +def test_scraped_adapter_no_db_path_ref(): + from app.platforms.ebay.scraper import ScrapedEbayAdapter + import tempfile + import pathlib + + with tempfile.TemporaryDirectory() as tmp: + s = Store(pathlib.Path(tmp) / "t.db") + adapter = ScrapedEbayAdapter(shared_store=s) + assert not hasattr(adapter, '_db_path_ref')