This commit is contained in:
@@ -320,7 +320,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
|
||||
# ==========================================
|
||||
# 系統版本與路徑
|
||||
# ==========================================
|
||||
SYSTEM_VERSION = "V10.102"
|
||||
SYSTEM_VERSION = "V10.103"
|
||||
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
|
||||
public_url = PUBLIC_URL # 用於模板顯示
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ sys_log = SystemLogger("EDMRoutes").get_logger()
|
||||
# Blueprint 定義
|
||||
edm_bp = Blueprint('edm', __name__)
|
||||
|
||||
_PROMO_DASHBOARD_CACHE = {}
|
||||
_PROMO_DASHBOARD_CACHE_MAX = 32
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 輔助函數
|
||||
@@ -62,11 +65,51 @@ def load_scheduler_stats():
|
||||
return {}
|
||||
|
||||
|
||||
def _get_promo_dashboard_fingerprint(session, page_type):
|
||||
"""取得促銷資料指紋,用於判斷快取是否仍可復用。"""
|
||||
max_id, max_crawled_at, row_count = session.query(
|
||||
func.max(PromoProduct.id),
|
||||
func.max(PromoProduct.crawled_at),
|
||||
func.count(PromoProduct.id)
|
||||
).filter(PromoProduct.page_type == page_type).one()
|
||||
return (
|
||||
max_id or 0,
|
||||
max_crawled_at.isoformat() if max_crawled_at else '',
|
||||
row_count or 0
|
||||
)
|
||||
|
||||
|
||||
def _get_promo_dashboard_cache_key(session, page_type, sort_by, order, requested_slot):
|
||||
"""建立 dashboard data 快取鍵;日期/小時避免自動時段跨時段後仍命中舊首屏。"""
|
||||
now_taipei = datetime.now(TAIPEI_TZ)
|
||||
auto_slot_bucket = now_taipei.strftime('%Y-%m-%d-%H') if not requested_slot else ''
|
||||
return (
|
||||
page_type,
|
||||
sort_by,
|
||||
order,
|
||||
requested_slot or '',
|
||||
auto_slot_bucket,
|
||||
_get_promo_dashboard_fingerprint(session, page_type)
|
||||
)
|
||||
|
||||
|
||||
def _remember_promo_dashboard_data(cache_key, data):
|
||||
"""保留少量活動 dashboard data,避免常用時段每次重算。"""
|
||||
if len(_PROMO_DASHBOARD_CACHE) >= _PROMO_DASHBOARD_CACHE_MAX:
|
||||
_PROMO_DASHBOARD_CACHE.pop(next(iter(_PROMO_DASHBOARD_CACHE)))
|
||||
_PROMO_DASHBOARD_CACHE[cache_key] = data
|
||||
|
||||
|
||||
def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order, requested_slot=None):
|
||||
"""
|
||||
通用的促銷儀表板數據建構函數
|
||||
用於 edm 和 festival 兩種頁面類型
|
||||
"""
|
||||
cache_key = _get_promo_dashboard_cache_key(session, page_type, sort_by, order, requested_slot)
|
||||
cached_data = _PROMO_DASHBOARD_CACHE.get(cache_key)
|
||||
if cached_data is not None:
|
||||
return cached_data
|
||||
|
||||
# 1. 基礎統計
|
||||
last_update = session.query(PromoProduct.crawled_at).filter(
|
||||
PromoProduct.page_type == page_type
|
||||
@@ -288,7 +331,7 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order, r
|
||||
slot_stats[slot]['on_shelf'] = on_shelf_count
|
||||
slot_stats[slot]['delisted_total'] = delisted_total_count
|
||||
|
||||
return {
|
||||
data = {
|
||||
'sorted_grouped_items': sorted_grouped_items,
|
||||
'slot_stats': slot_stats,
|
||||
'items_in_batch': items_in_batch,
|
||||
@@ -297,6 +340,8 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order, r
|
||||
'active_tab': active_tab,
|
||||
'current_batch_id': current_batch_id
|
||||
}
|
||||
_remember_promo_dashboard_data(cache_key, data)
|
||||
return data
|
||||
|
||||
|
||||
# ==========================================
|
||||
|
||||
Reference in New Issue
Block a user