ForcePilot/backend/package/yuxi/channel/gateway/device_registry.py
Kris ecd3c90e80 feat(channel/gateway): 新增完整网关通道模块
新增设备身份管理、认证限流、并发通道、Webhook路由、RBAC权限控制、SSE/轮询降级等全套网关通道功能,包含:
1. 设备身份生成与签名验证
2. 设备令牌认证与速率限制
3. 内存+数据库双重设备注册表
4. 并发通道限流管理
5. Webhook安全处理与路由
6. RBAC权限校验系统
7. OpenAI API兼容适配层
8. Tailscale认证支持
9. HTTP轮询降级机制
2026-05-21 10:26:33 +08:00

62 lines
1.7 KiB
Python

import logging
import threading
logger = logging.getLogger(__name__)
_registry: dict[str, str] = {}
_registry_lock = threading.Lock()
def register_device(device_id: str, public_key_pem: str) -> None:
with _registry_lock:
_registry[device_id] = public_key_pem
logger.info("Device registered: device_id=%s", device_id)
try:
from yuxi.channel.gateway.device_registry_db import db_save_device
import asyncio
try:
loop = asyncio.get_running_loop()
loop.create_task(db_save_device(device_id, public_key_pem))
except RuntimeError:
pass
except Exception:
logger.debug("DB device save skipped: device_id=%s", device_id)
def unregister_device(device_id: str) -> bool:
with _registry_lock:
if device_id in _registry:
del _registry[device_id]
logger.info("Device unregistered: device_id=%s", device_id)
return True
return False
async def lookup_public_key(device_id: str) -> str | None:
with _registry_lock:
key = _registry.get(device_id)
if key is not None:
return key
key = await _db_lookup(device_id)
if key is not None:
with _registry_lock:
_registry[device_id] = key
return key
async def _db_lookup(device_id: str) -> str | None:
try:
from yuxi.channel.gateway.device_registry_db import db_lookup_public_key
return await db_lookup_public_key(device_id)
except Exception:
logger.debug("DB device lookup skipped: device_id=%s", device_id)
return None
def list_devices() -> list[str]:
with _registry_lock:
return list(_registry.keys())