From c5fa92c4ecbb791bc9a9ca54e7a4652653b7640b Mon Sep 17 00:00:00 2001 From: Jonas Linter Date: Mon, 10 Nov 2025 13:07:08 +0100 Subject: [PATCH] Fixed stuff --- CLAUDE.md | 2 ++ src/meta_api_grabber/database.py | 32 +++++++++------------ src/meta_api_grabber/scheduled_grabber.py | 35 ++++++++++++++--------- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 104b65e..8d33056 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,2 +1,4 @@ Uv managed python project that grabs data from the meta api and saves it in a timescaledb database. +Always use uv run to execute python related stuff + diff --git a/src/meta_api_grabber/database.py b/src/meta_api_grabber/database.py index 6ea5eda..512cb4f 100644 --- a/src/meta_api_grabber/database.py +++ b/src/meta_api_grabber/database.py @@ -310,7 +310,6 @@ class TimescaleDBClient: account_id: str, data: Dict[str, Any], date_preset: str = "today", - cache_metadata: bool = True, ): """ Insert campaign-level insights data. @@ -321,10 +320,9 @@ class TimescaleDBClient: account_id: Ad account ID data: Insights data dictionary from Meta API date_preset: Date preset used - cache_metadata: If True, automatically cache campaign metadata from insights data """ - # Cache campaign metadata if requested and available in the insights data - if cache_metadata and data.get("campaign_name"): + # Auto-cache campaign metadata if available in the insights data + if data.get("campaign_name"): await self.upsert_campaign( campaign_id=campaign_id, account_id=account_id, @@ -389,7 +387,6 @@ class TimescaleDBClient: account_id: str, data: Dict[str, Any], date_preset: str = "today", - cache_metadata: bool = True, ): """ Insert ad set level insights data. @@ -401,21 +398,18 @@ class TimescaleDBClient: account_id: Ad account ID data: Insights data dictionary from Meta API date_preset: Date preset used - cache_metadata: If True, automatically cache adset/campaign metadata from insights data """ - # Cache metadata if requested and available in the insights data - if cache_metadata: - # Cache adset metadata if available - # Note: Campaign should already exist from cache_campaigns_metadata or grab_campaign_insights - # If it doesn't exist, the foreign key constraint will fail with a clear error - # This is intentional - we should never silently create campaigns with 'Unknown' names - if data.get("adset_name"): - await self.upsert_adset( - adset_id=adset_id, - campaign_id=campaign_id, - adset_name=data["adset_name"], - status=None, # Not available in insights response - ) + # Auto-cache adset metadata if available in the insights data + # Note: Campaign should already exist from cache_campaigns_metadata or grab_campaign_insights + # If it doesn't exist, the foreign key constraint will fail with a clear error + # This is intentional - we should never silently create campaigns with 'Unknown' names + if data.get("adset_name"): + await self.upsert_adset( + adset_id=adset_id, + campaign_id=campaign_id, + adset_name=data["adset_name"], + status=None, # Not available in insights response + ) query = """ INSERT INTO adset_insights ( diff --git a/src/meta_api_grabber/scheduled_grabber.py b/src/meta_api_grabber/scheduled_grabber.py index de4fcf6..248bdda 100644 --- a/src/meta_api_grabber/scheduled_grabber.py +++ b/src/meta_api_grabber/scheduled_grabber.py @@ -438,7 +438,6 @@ class ScheduledInsightsGrabber: end_date: Optional[date] = None, breakdowns: Optional[list] = None, limit: Optional[int] = None, - cache_metadata: bool = False, required_fields: Optional[dict] = None, extra_data_processor=None, ) -> tuple[int, Optional[date]]: @@ -455,7 +454,6 @@ class ScheduledInsightsGrabber: end_date: End date for custom date range (optional) breakdowns: List of breakdown fields (optional) limit: Maximum number of results (optional) - cache_metadata: Whether to cache metadata (for campaign/adset levels) required_fields: Dict of field_name -> label for validation before insert extra_data_processor: Optional callable to process/add extra data to insight_dict @@ -529,14 +527,27 @@ class ScheduledInsightsGrabber: # Compute appropriate timestamp based on date_start and account timezone timestamp = self._compute_timestamp(date_start_str, account_timezone) - # Call the appropriate database insert function - await db_insert_func( - time=timestamp, - account_id=account_id, - data=insight_dict, - date_preset=date_preset_for_db, - cache_metadata=cache_metadata, - ) + # Build kwargs for insert function based on level + kwargs = { + "time": timestamp, + "account_id": account_id, + "data": insight_dict, + "date_preset": date_preset_for_db, + } + + # Add level-specific parameters + if level == "campaign": + kwargs["campaign_id"] = insight_dict.get("campaign_id") + elif level == "adset": + kwargs["adset_id"] = insight_dict.get("adset_id") + kwargs["campaign_id"] = insight_dict.get("campaign_id") + + # Add country for breakdown queries + if "country" in insight_dict: + kwargs["country"] = insight_dict.get("country") + + # Call the appropriate database insert function with level-specific parameters + await db_insert_func(**kwargs) count += 1 return count, date_start_value @@ -602,7 +613,6 @@ class ScheduledInsightsGrabber: db_insert_func=self.db.insert_campaign_insights, date_preset=date_preset, limit=limit, - cache_metadata=True, required_fields={"campaign_id": "campaign_id"}, ) @@ -640,7 +650,6 @@ class ScheduledInsightsGrabber: db_insert_func=self.db.insert_adset_insights, date_preset=date_preset, limit=limit, - cache_metadata=True, required_fields={"adset_id": "adset_id", "campaign_id": "campaign_id"}, ) @@ -759,7 +768,6 @@ class ScheduledInsightsGrabber: start_date=start_date, end_date=end_date, limit=limit, - cache_metadata=True, required_fields={"campaign_id": "campaign_id"}, ) @@ -808,7 +816,6 @@ class ScheduledInsightsGrabber: start_date=start_date, end_date=end_date, limit=limit, - cache_metadata=True, required_fields={"adset_id": "adset_id", "campaign_id": "campaign_id"}, )