From 0a519d5c7d47aa4d8ac583cf57f734955f4972da Mon Sep 17 00:00:00 2001 From: Lxy Date: Sat, 4 Jul 2026 12:40:42 +0800 Subject: [PATCH] fix(cache): fallback to SQLite when StorageManager timestamp write fails --- app/services/cache.py | 6 +++-- tests/test_cache_storage_integration.py | 34 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/app/services/cache.py b/app/services/cache.py index 8f6b11a..d6a68c1 100644 --- a/app/services/cache.py +++ b/app/services/cache.py @@ -314,8 +314,10 @@ def update_symbol_timestamp(db: Session, symbol: str, data_type: str, refresh_ti if storage.is_available(): try: - storage.save_symbol_timestamp(symbol, data_type, refresh_time) - return + if storage.save_symbol_timestamp(symbol, data_type, refresh_time): + return + else: + raise Exception("save_symbol_timestamp returned False") except Exception as e: logger.warning(f"StorageManager 时间戳写入失败,降级到 SQLite: {e}") diff --git a/tests/test_cache_storage_integration.py b/tests/test_cache_storage_integration.py index 37adeeb..b822c02 100644 --- a/tests/test_cache_storage_integration.py +++ b/tests/test_cache_storage_integration.py @@ -482,6 +482,40 @@ class TestSymbolTimestamp: assert sqlite_record.last_refresh_at == refresh_time assert sqlite_record.refresh_count == 1 + def test_update_symbol_timestamp_falls_back_to_sqlite_when_storage_returns_false(self, db, storage_manager_mock): + """StorageManager 可用但返回 False 时降级到 SQLite 写入合约时间戳。""" + storage_manager_mock.save_symbol_timestamp.return_value = False + refresh_time = datetime(2026, 7, 4, 10, 0, 0) + + with patch("app.services.cache.get_storage_manager", return_value=storage_manager_mock): + from app.services import cache + + cache.update_symbol_timestamp(db, "AG2606", "futures", refresh_time) + + storage_manager_mock.save_symbol_timestamp.assert_called_once_with("AG2606", "futures", refresh_time) + sqlite_record = db.query(SymbolTimestamp).filter_by(symbol="AG2606").first() + assert sqlite_record is not None + assert sqlite_record.last_refresh_at == refresh_time + assert sqlite_record.refresh_count == 1 + + def test_update_symbol_timestamp_falls_back_to_sqlite_when_storage_raises(self, db, storage_manager_mock, caplog): + """StorageManager 可用但写入异常时降级到 SQLite 写入合约时间戳并记录警告。""" + storage_manager_mock.save_symbol_timestamp.side_effect = Exception("mysql down") + refresh_time = datetime(2026, 7, 4, 10, 0, 0) + + with patch("app.services.cache.get_storage_manager", return_value=storage_manager_mock): + from app.services import cache + + with caplog.at_level(logging.WARNING, logger="app.services.cache"): + cache.update_symbol_timestamp(db, "AG2606", "futures", refresh_time) + + storage_manager_mock.save_symbol_timestamp.assert_called_once_with("AG2606", "futures", refresh_time) + sqlite_record = db.query(SymbolTimestamp).filter_by(symbol="AG2606").first() + assert sqlite_record is not None + assert sqlite_record.last_refresh_at == refresh_time + assert sqlite_record.refresh_count == 1 + assert "StorageManager 时间戳写入失败" in caplog.text + def test_get_symbol_timestamp_uses_storage_when_available(self, db, storage_manager_mock): """StorageManager 可用时优先读取合约时间戳。""" storage_manager_mock.get_symbol_timestamp.return_value = {