refactor(module): simplify service instantiation with generics

This commit is contained in:
InfinityPacer
2024-09-27 04:04:56 +08:00
parent 5efcd6e6be
commit 2ce3ddb75a
19 changed files with 244 additions and 242 deletions

View File

@@ -1,6 +1,7 @@
from abc import abstractmethod, ABCMeta
from typing import Dict, Any, Optional, Generic, Tuple, Union, TypeVar
from typing import Generic, Tuple, Union, TypeVar, Type, Dict, Optional, Callable, Any, List
from app.helper.serviceconfig import ServiceConfigHelper
from app.schemas import Notification, MessageChannel, NotificationConf, MediaServerConf, DownloaderConf
@@ -49,29 +50,73 @@ class _ModuleBase(metaclass=ABCMeta):
pass
# 定义一个泛型 T,用于表示具体的配置类型
# 定义泛型,用于表示具体的服务类型和配置类型
TService = TypeVar("TService", bound=object)
TConf = TypeVar("TConf")
class ConfManagerBase(Generic[TConf]):
class ServiceBase(Generic[TService, TConf], metaclass=ABCMeta):
"""
通用管理基类,支持配置管理和实例管理
抽象服务基类,负责服务的初始化、获取实例和配置管理
"""
_configs: Dict[str, TConf] = {}
_instances: Dict[str, Any] = {}
def get_instance(self, name: str) -> Optional[Any]:
def __init__(self):
"""
获取实例 (如服务/客户端)
初始化 ServiceBase 类的实例
"""
self._configs: Dict[str, TConf] = {}
self._instances: Dict[str, TService] = {}
def init_service(self, service_name: str,
service_type: Optional[Union[Type[TService], Callable[..., TService]]] = None):
"""
初始化服务,获取配置并实例化对应服务
:param service_name: 服务名称,作为配置匹配的依据
:param service_type: 服务的类型可以是类类型Type[TService]、工厂函数Callable或 None 来跳过实例化
"""
configs = self.get_configs()
if not configs:
return
for conf in configs:
if conf.enabled and conf.type == service_name:
self._configs[conf.name] = conf
if service_type:
# 通过服务类型或工厂函数来创建实例
if isinstance(service_type, type):
# 如果传入的是类类型,调用构造函数实例化
self._instances[conf.name] = service_type(**conf.config)
else:
# 如果传入的是工厂函数,直接调用工厂函数
self._instances[conf.name] = service_type(conf)
def get_instance(self, name: str) -> Optional[TService]:
"""
获取服务实例
:param name: 实例名称
:return: 返回对应名称的服务实例,若不存在则返回 None
"""
if not name:
return None
return self._instances.get(name)
@abstractmethod
def get_configs(self) -> List[TConf]:
"""
获取服务的配置列表
:return: 返回配置列表
"""
pass
def get_config(self, name: str, ctype: str = None) -> Optional[TConf]:
"""
获取配置,支持类型过滤
:param name: 配置名称
:param ctype: 配置类型,可选,默认不进行类型过滤
:return: 返回符合条件的配置,若不存在则返回 None
"""
if not name:
return None
@@ -81,16 +126,33 @@ class ConfManagerBase(Generic[TConf]):
return conf if getattr(conf, "type", None) == ctype else None
class _MessageBase(ConfManagerBase[NotificationConf]):
class _MessageBase(ServiceBase[TService, NotificationConf]):
"""
消息基类,继承了通用的配置和实例管理功能,指定配置类型为 NotificationConf
消息基类
"""
_channel: MessageChannel = None
def __init__(self):
"""
初始化消息基类,并设置消息通道
"""
super().__init__()
self._channel: Optional[MessageChannel] = None
def get_configs(self) -> List[NotificationConf]:
"""
获取消息通知渠道的配置
:return: 返回消息通知的配置列表
"""
return ServiceConfigHelper.get_notification_configs()
def check_message(self, message: Notification, source: str = None) -> bool:
"""
检查消息渠道及消息类型,如不符合则不处理
检查消息渠道及消息类型,判断是否处理消息
:param message: 要检查的通知消息
:param source: 消息来源,可选
:return: 返回布尔值,表示是否处理该消息
"""
# 检查消息渠道
if message.channel and message.channel != self._channel:
@@ -108,25 +170,63 @@ class _MessageBase(ConfManagerBase[NotificationConf]):
return True
class _DownloaderBase(ConfManagerBase[DownloaderConf]):
class _DownloaderBase(ServiceBase[TService, DownloaderConf]):
"""
下载器基类
"""
_default_server: Any = None
_default_server_name: str = None
def __init__(self):
"""
初始化下载器基类,并设置默认服务器
"""
super().__init__()
self._default_server: Any = None
self._default_server_name: Optional[str] = None
def init_service(self, service_name: str,
service_type: Optional[Union[Type[TService], Callable[..., TService]]] = None):
"""
初始化服务,获取配置并实例化对应服务
:param service_name: 服务名称,作为配置匹配的依据
:param service_type: 服务的类型可以是类类型Type[TService]或工厂函数Callable用于创建服务实例
"""
super().init_service(service_name=service_name, service_type=service_type)
if self._configs:
for conf in self._configs.values():
if conf.default:
self._default_server_name = conf.name
self._default_server = self.get_instance(conf.name)
def get_instance(self, name: str = None) -> Optional[Any]:
"""
获取实例name为空时返回默认实例
:param name: 实例名称,可选,默认为 None
:return: 返回指定名称的实例,若 name 为 None 则返回默认实例
"""
if name:
return self.get_instance(name)
return self._default_server
def get_configs(self) -> List[DownloaderConf]:
"""
获取下载器的配置
class _MediaServerBase(ConfManagerBase[MediaServerConf]):
:return: 返回下载器配置列表
"""
return ServiceConfigHelper.get_downloader_configs()
class _MediaServerBase(ServiceBase[TService, MediaServerConf]):
"""
媒体服务器基类
"""
pass
def get_configs(self) -> List[MediaServerConf]:
"""
获取媒体服务器的配置
:return: 返回媒体服务器配置列表
"""
return ServiceConfigHelper.get_mediaserver_configs()