mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-31 12:24:39 +08:00
62 lines
2.2 KiB
Python
62 lines
2.2 KiB
Python
"""
|
||
插件数据库句柄:持有引擎、会话工厂与释放策略。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from pathlib import Path
|
||
|
||
from sqlalchemy.engine import Engine
|
||
from sqlalchemy.orm import Session, scoped_session, sessionmaker
|
||
|
||
__all__ = ["PluginDatabaseHandle"]
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class PluginDatabaseHandle:
|
||
"""
|
||
一个插件专属数据库的连接要素。
|
||
|
||
SQLite 下引擎由本句柄独占,``owns_engine`` 为真;PostgreSQL 下引擎是宿主引擎按
|
||
``schema_translate_map`` 派生的外观,``owns_engine`` 为假——只有前者可以 dispose,
|
||
后者一旦 dispose 会连累宿主与其它插件仍在使用的同一个连接池。PostgreSQL 下本句柄的
|
||
会话与连接在每个事务开始时把 ``search_path`` 限定到插件 schema 本身,未限定的原生 SQL
|
||
因此同样解析到插件自己的表,找不到的表名直接报错而不会落到宿主同名表。
|
||
|
||
:param plugin_id: 所属插件的物理标识
|
||
:param engine: 绑定插件数据库或专属 schema 的同步引擎
|
||
:param session_factory: 为该插件创建独立 Session 的工厂
|
||
:param scoped_session_factory: 为该插件按当前线程复用 Session 的工厂
|
||
:param db_path: SQLite 文件路径;PostgreSQL 模式为 None
|
||
:param schema: PostgreSQL 插件专属 schema;SQLite 模式为 None
|
||
:param owns_engine: 是否独占引擎连接池,决定 dispose 是否释放池资源
|
||
"""
|
||
|
||
plugin_id: str
|
||
engine: Engine
|
||
session_factory: sessionmaker
|
||
scoped_session_factory: scoped_session
|
||
db_path: Path | None
|
||
schema: str | None
|
||
owns_engine: bool
|
||
|
||
def session(self) -> Session:
|
||
"""
|
||
新建一个绑定本库的会话,提交、回滚与关闭由调用方负责。
|
||
"""
|
||
return self.session_factory()
|
||
|
||
def scoped_session(self) -> Session:
|
||
"""
|
||
取当前线程绑定的会话,同一线程内重复调用复用同一个实例。
|
||
"""
|
||
return self.scoped_session_factory()
|
||
|
||
def dispose(self) -> None:
|
||
"""
|
||
释放本句柄独占的连接池;不拥有引擎时不做任何事。
|
||
"""
|
||
if self.owns_engine:
|
||
self.engine.dispose()
|