65 lines
2.4 KiB
Python
Executable File
65 lines
2.4 KiB
Python
Executable File
"""驱动基类:统一初始化、请求节流;缓存由装饰器处理。"""
|
|
|
|
import asyncio
|
|
import contextvars
|
|
import time
|
|
from abc import ABC, abstractmethod
|
|
from typing import List, Optional, Dict, Any
|
|
from core.base import FileItem, OperationResult, DriverInfo
|
|
from core.log_manager import get_writer, LogModule
|
|
|
|
# 协程级额外 API 延迟补偿,供缓存保持/STRM 等任务叠加在 operation_delay 之上,不影响其他协程
|
|
_extra_api_delay: contextvars.ContextVar[int] = contextvars.ContextVar('extra_api_delay', default=0)
|
|
|
|
|
|
class BaseDriver(ABC):
|
|
def __init__(self, config):
|
|
self.config = config
|
|
self.account_id = getattr(config, 'account_id', 'default')
|
|
self._cache_manager = None
|
|
self._log = get_writer(LogModule.DRIVER)
|
|
self._request_interval_lock = asyncio.Lock()
|
|
self._last_request_started_at: Optional[float] = None
|
|
|
|
def set_cache_manager(self, cache_manager):
|
|
self._cache_manager = cache_manager
|
|
|
|
def is_connectivity_test(self) -> bool:
|
|
"""account_id='temp_test' 代表只是新增/编辑账号时做一次连通性验证,不写入任何持久状态。"""
|
|
account_id = getattr(self, "_account_id", None) or getattr(self, "account_id", None)
|
|
return str(account_id) == "temp_test"
|
|
|
|
async def wait_for_request_interval(self) -> None:
|
|
delay_ms = int(getattr(self.config, "operation_delay", 0) or 0) + _extra_api_delay.get()
|
|
if delay_ms <= 0:
|
|
return
|
|
|
|
async with self._request_interval_lock:
|
|
now = time.monotonic()
|
|
if self._last_request_started_at is not None:
|
|
elapsed_ms = (now - self._last_request_started_at) * 1000
|
|
remaining_ms = delay_ms - elapsed_ms
|
|
if remaining_ms > 0:
|
|
await asyncio.sleep(remaining_ms / 1000.0)
|
|
self._last_request_started_at = time.monotonic()
|
|
|
|
@classmethod
|
|
@abstractmethod
|
|
def get_info(cls) -> DriverInfo:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def init(self) -> None:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def close(self) -> None:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def test_connection(self) -> OperationResult:
|
|
raise NotImplementedError
|
|
|
|
def __str__(self) -> str:
|
|
return f"<{self.__class__.__name__} account_id={self.account_id}>"
|