ForcePilot/backend/package/yuxi/channel/extensions/feishu/file_cache.py
Kris 5e91bb9985 feat(feishu): 新增飞书渠道完整插件实现
新增飞书渠道插件,包含基础配置、事件处理、消息收发、工具调用、权限管理等完整功能模块,支持WebSocket长连接、卡片消息、流式响应、群管理、审批通知等能力
2026-05-21 10:46:42 +08:00

56 lines
1.6 KiB
Python

from __future__ import annotations
import logging
import time
from collections import OrderedDict
logger = logging.getLogger(__name__)
DEFAULT_TTL_SECONDS = 120
class FileCacheEntry:
__slots__ = ("file_key", "file_path", "file_name", "cached_at")
def __init__(self, file_key: str, file_path: str = "", file_name: str = ""):
self.file_key = file_key
self.file_path = file_path
self.file_name = file_name
self.cached_at = time.monotonic()
class FileCache:
def __init__(self, ttl_seconds: int = DEFAULT_TTL_SECONDS):
self._ttl = ttl_seconds
self._entries: OrderedDict[str, FileCacheEntry] = OrderedDict()
def add(self, session_key: str, file_key: str, file_path: str = "", file_name: str = "") -> None:
self._evict_expired()
self._entries[session_key] = FileCacheEntry(file_key, file_path, file_name)
def get(self, session_key: str) -> FileCacheEntry | None:
self._evict_expired()
entry = self._entries.get(session_key)
if entry is not None:
return entry
return None
def clear(self, session_key: str) -> None:
self._entries.pop(session_key, None)
def _evict_expired(self) -> None:
now = time.monotonic()
expired = [k for k, v in self._entries.items() if now - v.cached_at > self._ttl]
for k in expired:
self._entries.pop(k, None)
_cache_instance: FileCache | None = None
def get_file_cache() -> FileCache:
global _cache_instance
if _cache_instance is None:
_cache_instance = FileCache()
return _cache_instance