2022-07-26 10:07:31 +00:00
|
|
|
import inspect
|
|
|
|
import os
|
|
|
|
from glob import glob
|
|
|
|
from importlib import import_module
|
|
|
|
from typing import List, Union, Dict
|
|
|
|
|
|
|
|
from logger import Log
|
2022-08-05 11:20:47 +00:00
|
|
|
from models.types import Func
|
2022-07-26 10:07:31 +00:00
|
|
|
from utils.aiobrowser import AioBrowser
|
|
|
|
from utils.mysql import MySQL
|
|
|
|
from utils.redisdb import RedisDB
|
|
|
|
|
|
|
|
ServiceFunctions: List[Func] = []
|
|
|
|
ServiceDict: Dict[str, Func] = {}
|
|
|
|
|
|
|
|
|
|
|
|
def listener_service():
|
|
|
|
"""监听服务"""
|
|
|
|
|
|
|
|
def decorator(func: Func):
|
|
|
|
ServiceFunctions.append(
|
|
|
|
func
|
|
|
|
)
|
|
|
|
return func
|
|
|
|
|
|
|
|
return decorator
|
|
|
|
|
|
|
|
|
2022-08-05 15:11:44 +00:00
|
|
|
class ServicesManager:
|
2022-07-26 10:07:31 +00:00
|
|
|
def __init__(self, mysql: MySQL, redis: RedisDB, browser: AioBrowser):
|
|
|
|
self.browser = browser
|
|
|
|
self.redis = redis
|
|
|
|
self.mysql = mysql
|
|
|
|
self.app_list: List[str] = []
|
|
|
|
self.exclude_list: List[str] = []
|
|
|
|
|
|
|
|
def refresh_list(self, app_paths):
|
|
|
|
self.app_list.clear()
|
|
|
|
app_paths = glob(app_paths)
|
|
|
|
for app_path in app_paths:
|
|
|
|
if os.path.isdir(app_path):
|
|
|
|
app_path = os.path.basename(app_path)
|
|
|
|
self.app_list.append(app_path)
|
|
|
|
|
|
|
|
def add_exclude(self, exclude: Union[str, List[str]]):
|
|
|
|
if isinstance(exclude, str):
|
|
|
|
self.exclude_list.append(exclude)
|
|
|
|
elif isinstance(exclude, list):
|
|
|
|
self.exclude_list.extend(exclude)
|
|
|
|
else:
|
|
|
|
raise TypeError
|
|
|
|
|
|
|
|
def import_module(self):
|
|
|
|
for app_name in self.app_list:
|
|
|
|
if app_name not in self.exclude_list:
|
|
|
|
try:
|
2022-08-05 12:26:12 +00:00
|
|
|
import_module(f"apps.{app_name}")
|
2022-07-26 10:07:31 +00:00
|
|
|
except ImportError as exc:
|
|
|
|
Log.warning(f"Service模块 {app_name} 导入失败", exc)
|
|
|
|
except ImportWarning as exc:
|
|
|
|
Log.warning(f"Service模块 {app_name} 加载成功但有警告", exc)
|
|
|
|
except Exception as exc:
|
|
|
|
Log.warning(f"Service模块 {app_name} 加载失败", exc)
|
|
|
|
else:
|
|
|
|
Log.debug(f"Service模块 {app_name} 加载成功")
|
|
|
|
|
|
|
|
def add_service(self):
|
|
|
|
for func in ServiceFunctions:
|
|
|
|
if callable(func):
|
|
|
|
kwargs = {}
|
|
|
|
try:
|
|
|
|
signature = inspect.signature(func)
|
|
|
|
except ValueError as exception:
|
|
|
|
if "no signature found" in str(exception):
|
|
|
|
Log.warning("no signature found", exception)
|
|
|
|
break
|
|
|
|
elif "not supported by signature" in str(exception):
|
|
|
|
Log.warning("not supported by signature", exception)
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
raise exception
|
|
|
|
else:
|
|
|
|
for parameter_name, parameter in signature.parameters.items():
|
|
|
|
annotation = parameter.annotation
|
|
|
|
if issubclass(annotation, MySQL):
|
|
|
|
kwargs[parameter_name] = self.mysql
|
|
|
|
if issubclass(annotation, RedisDB):
|
|
|
|
kwargs[parameter_name] = self.redis
|
|
|
|
if issubclass(annotation, AioBrowser):
|
|
|
|
kwargs[parameter_name] = self.browser
|
|
|
|
try:
|
|
|
|
handlers_list = func(**kwargs)
|
|
|
|
class_name = handlers_list.__class__.__name__
|
|
|
|
ServiceDict.setdefault(class_name, handlers_list)
|
2022-07-26 16:26:35 +00:00
|
|
|
except BaseException as exc:
|
2022-07-26 10:07:31 +00:00
|
|
|
Log.error("初始化Service失败", exc)
|
|
|
|
finally:
|
|
|
|
pass
|