fix(cache): канонизация ключа канала (Durov/durov/@name -> один ключ) + one-shot миграция
Один канал жил под ключами Durov/durov/@name в трёх слоях (tgcache-файлы, data/cache/ каталоги, SQLite-строки) -> дубли кеша, двойные походы в Telegram, осиротевшие деревья. ID<->username НЕ унифицируем (сознательно). - channel_key.py: canonical_channel_key (strip @, -100... числовые verbatim, иначе lowercase; безопасно и для API-вызовов). - tg_cache._cache_file_path прогоняет ключ через canonical. - post_parser.get_channel_username -> lowercase (обе ветки; канонизирует SQLite/media-URL/t.me). Только эти 2 строки. - api_server.get_media: fs_channel = canonical_channel_key(channel) ПОСЛЕ проверки дайджеста (дайджест — по ИСХОДНОМУ url, иначе ломаются выданные ссылки); fs_channel во всех путях/ключах/download ниже. - migrate_channel_keys_sync в lifespan (после init_db_sync, до client.start, через asyncio.to_thread): канал целиком FS-потом-SQL. Обязательный os.path.samefile guard ДО merge/rmtree — на case-insensitive FS Durov/durov один inode, иначе снесли бы кеш. FS-сбой -> SQL пропуск (строки старорегистровые, дерево видно свиперу, нет вечных orphan). SQL-merge PK-safe (twin -> merge added=max/mime non-NULL + DELETE, иначе plain UPDATE). Идемпотентно. closes #24 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+7
-2
@@ -27,6 +27,7 @@ from message_snapshot import (
|
||||
snapshot_messages,
|
||||
restore_messages,
|
||||
)
|
||||
from channel_key import canonical_channel_key
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -51,11 +52,15 @@ def _safe_key(key: Union[str, int]) -> str:
|
||||
|
||||
|
||||
def _cache_file_path(key: Union[str, int], suffix: str) -> str:
|
||||
"""Return the cache file path <safe_key>.<suffix> (e.g. 'history.json' / 'chatinfo.json')."""
|
||||
"""Return the cache file path <safe_key>.<suffix> (e.g. 'history.json' / 'chatinfo.json').
|
||||
|
||||
The key is first canonicalized so that 'Durov', 'durov' and '@durov' collapse to a
|
||||
single cache file (Telegram usernames are case-insensitive).
|
||||
"""
|
||||
if not os.path.exists(CACHE_DIR):
|
||||
os.makedirs(CACHE_DIR, exist_ok=True)
|
||||
logger.info(f"cache_dir_created: path {CACHE_DIR}")
|
||||
return os.path.join(CACHE_DIR, f"{_safe_key(key)}.{suffix}")
|
||||
return os.path.join(CACHE_DIR, f"{_safe_key(canonical_channel_key(key))}.{suffix}")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
Reference in New Issue
Block a user