Files
ewoooc/services/market_intel/service.py
OoO 30a173cf69
All checks were successful
CD Pipeline / deploy (push) Successful in 58s
統一全站暖色視覺與市場情報骨架
2026-05-06 20:24:46 +08:00

83 lines
2.5 KiB
Python

"""市場情報 Phase 1 骨架服務。
本階段只回報 feature flag 與 rollout 狀態,不啟動爬蟲、不寫資料庫。
"""
from dataclasses import asdict, dataclass
from datetime import datetime, timedelta, timezone
from uuid import uuid4
from config import (
MARKET_INTEL_CRAWLER_ENABLED,
MARKET_INTEL_ENABLED,
MARKET_INTEL_WRITE_ENABLED,
)
TAIPEI_TZ = timezone(timedelta(hours=8))
MARKET_INTEL_TABLES = (
"market_platforms",
"market_campaigns",
"market_campaign_snapshots",
"market_campaign_products",
"market_product_price_history",
"market_product_matches",
"market_crawler_runs",
)
@dataclass(frozen=True)
class MarketIntelRuntimeStatus:
"""市場情報模組目前的啟用狀態。"""
phase: str
enabled: bool
crawler_enabled: bool
write_enabled: bool
dry_run_only: bool
scheduler_attached: bool
database_write_allowed: bool
def to_dict(self):
return asdict(self)
class MarketIntelService:
"""市場情報入口服務,先集中 feature gate 與安全狀態。"""
phase = "phase_2_schema_ready_disabled"
def get_runtime_status(self) -> MarketIntelRuntimeStatus:
return MarketIntelRuntimeStatus(
phase=self.phase,
enabled=MARKET_INTEL_ENABLED,
crawler_enabled=MARKET_INTEL_CRAWLER_ENABLED,
write_enabled=MARKET_INTEL_WRITE_ENABLED,
dry_run_only=not MARKET_INTEL_WRITE_ENABLED,
scheduler_attached=False,
database_write_allowed=(
MARKET_INTEL_ENABLED
and MARKET_INTEL_CRAWLER_ENABLED
and MARKET_INTEL_WRITE_ENABLED
),
)
def get_schema_tables(self):
"""回傳 ADR-035 定義的 market_* schema 名稱。"""
return list(MARKET_INTEL_TABLES)
def build_dry_run_plan(self, platform_code="all"):
"""建立 dry-run 計畫,不執行爬蟲、不寫 DB。"""
status = self.get_runtime_status()
return {
"batch_id": f"market-dry-run-{uuid4().hex[:12]}",
"platform_code": platform_code,
"created_at": datetime.now(TAIPEI_TZ).replace(tzinfo=None).isoformat(),
"phase": self.phase,
"would_discover_campaigns": bool(status.enabled and status.crawler_enabled),
"would_write_database": bool(status.database_write_allowed),
"scheduler_attached": status.scheduler_attached,
"schema_tables": self.get_schema_tables(),
"status": status.to_dict(),
}