ForcePilot/backend/package/yuxi/channel/plugins/registry.py
Kris bab30f2715
Some checks failed
Deploy VitePress site to Pages / build (push) Has been cancelled
Ruff Format Check / Ruff Format & Lint (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
feat:0715
2026-07-15 12:30:58 +08:00

95 lines
3.3 KiB
Python

from yuxi.channel.plugins.protocol import ChannelMeta
from yuxi.channel.ports import MetaPort
from yuxi.utils.logging_config import logger
class ChannelRegistry:
"""渠道插件注册表,支持别名解析。"""
def __init__(self) -> None:
self._plugins: dict[str, MetaPort] = {}
self._alias_to_primary: dict[str, str] = {}
def register(self, plugin: MetaPort) -> None:
meta = plugin.get_meta()
existing = self._plugins.get(meta.channel_type)
if existing is not None and existing is not plugin:
logger.warning(
"Channel type '%s' is already registered, overwriting with new plugin",
meta.channel_type,
)
self._plugins[meta.channel_type] = plugin
for alias in meta.aliases:
existing_primary = self._alias_to_primary.get(alias)
if existing_primary is not None and existing_primary != meta.channel_type:
logger.warning(
"Channel alias '%s' already registered to '%s', skipping registration for '%s'",
alias,
existing_primary,
meta.channel_type,
)
continue
self._plugins[alias] = plugin
self._alias_to_primary[alias] = meta.channel_type
def register_primary(self, plugin: MetaPort) -> None:
meta = plugin.get_meta()
existing = self._plugins.get(meta.channel_type)
if existing is not None and existing is not plugin:
logger.warning(
"Channel type '%s' is already registered, overwriting with new plugin",
meta.channel_type,
)
self._plugins[meta.channel_type] = plugin
def unregister(self, channel_type: str) -> None:
plugin = self._plugins.pop(channel_type, None)
if plugin is None:
return
meta = plugin.get_meta()
primary = meta.channel_type
for alias in meta.aliases:
if self._alias_to_primary.get(alias) == primary:
self._plugins.pop(alias, None)
self._alias_to_primary.pop(alias, None)
def get_plugin(self, channel_type: str) -> MetaPort | None:
return self._plugins.get(channel_type)
def get_plugins_by_port(self, port: type) -> list[MetaPort]:
seen: set[int] = set()
result: list[MetaPort] = []
for plugin in self._plugins.values():
pid = id(plugin)
if pid in seen:
continue
seen.add(pid)
if isinstance(plugin, port):
result.append(plugin)
return result
def has_port(self, channel_type: str, port: type) -> bool:
plugin = self._plugins.get(channel_type)
return plugin is not None and isinstance(plugin, port)
def list_plugins(self) -> list[ChannelMeta]:
seen: set[int] = set()
result: list[ChannelMeta] = []
for plugin in self._plugins.values():
pid = id(plugin)
if pid in seen:
continue
seen.add(pid)
result.append(plugin.get_meta())
return result
_GLOBAL_REGISTRY: ChannelRegistry | None = None
def get_registry() -> ChannelRegistry:
global _GLOBAL_REGISTRY
if _GLOBAL_REGISTRY is None:
_GLOBAL_REGISTRY = ChannelRegistry()
return _GLOBAL_REGISTRY