add: Plugin 基类支持 [workers.config.database] 配置接入 PostgreSQL(url 优先,SQLite 回落)

This commit is contained in:
2026-08-17 17:26:59 +08:00
parent c560f38690
commit d8230bc0ca
3 changed files with 55 additions and 13 deletions
+13 -4
View File
@@ -45,11 +45,11 @@ logger = logging.getLogger(__name__)
class MyPlugin(Plugin):
type = "my_plugin"
db_name = "my_plugin.db" # 自动在 data_dir 下建 SQLite 库;不需要则置 None
db_name = "my_plugin.db" # SQLite:自动在 data_dir 下建库;config 含 database.url 时优先走 PostgreSQL;不需要则置 None
auto_bind = True # 首次初始化时自动 auto_bind_models(self.type)
async def on_init(self):
# 数据库已由基类自动初始化(self.db)
# 数据库已由基类自动初始化(self.db,SQLite 或 PostgreSQL)
self.set_var("db", self.db) # 写入插件 global_var 模块
# self.spawn_task(self._background_loop()) # 后台任务(cleanup 自动取消)
# self.register_cleanup(self._close_client) # 注册清理钩子(逆序执行)
@@ -59,6 +59,15 @@ class MyPlugin(Plugin):
...
# PostgreSQL 接入(可选):在插件 config.toml 配置 database 段后,
# 基类 init_database() 检测到 url 即走 Database.from_config 接入 PG::
#
# # config/workers/my_plugin/config.toml
# [workers.config.database]
# type = "postgresql"
# url = "postgresql+asyncpg://user:pwd@127.0.0.1:5432/mydb"
# generate_schemas = true
# 暴露给 app lifespan 的模块级入口(bound method,签名与旧写法一致)
plugin = MyPlugin()
create_workers = plugin.create_workers
@@ -70,7 +79,7 @@ cleanup = plugin.cleanup
| 属性 / 方法 | 说明 |
| -------------- | ---------------------------------------------------------------------------- |
| `type` | 插件类型(worker type),匹配 subject 前缀与 `config/workers/<type>`(必填) |
| `db_name` | 默认 SQLite 文件名(放 `data_dir` 下);`None` 表示不自动建库 |
| `db_name` | 默认 SQLite 文件名(放 `data_dir` 下);config 含 `database.url` 时优先走 PostgreSQL;`None` 表示不自动建库 |
| `auto_bind` | 首次初始化时是否自动 `auto_bind_models(self.type)` |
| `on_init()` | 首次 `create_workers` 时调用一次,初始化资源 |
| `on_cleanup()` | `cleanup` 时调用,清理自定义资源 |
@@ -79,7 +88,7 @@ cleanup = plugin.cleanup
- **幂等**:重复 `create_workers` 只初始化一次(`asyncio.Lock` 守卫,并发调用安全)
- **统一日志**:`logger` 自动带 `[type]` 前缀
- **数据库**:`init_database()` 统一建路径、建表、记录,`cleanup` 自动 `dispose()`
- **数据库**:`init_database()` 统一建库建表、记录,`cleanup` 自动 `dispose()`(SQLite 按 `db_name`;config 含 `database.url` 时走 PostgreSQL)
- **global_var**:`set_var()` / `get_var()` 统一读写插件 `global_var` 模块;`cleanup` 时自动将已发布的变量重置为 `None`,避免业务代码拿到已释放的资源
- **后台任务**:`spawn_task()` 跟踪,`cleanup` 时自动取消并 `gather`
- **清理钩子**:`register_cleanup()` 注册,`cleanup` 时逆序执行
+1 -1
View File
@@ -4,7 +4,7 @@ requires = ["hatchling"]
[project]
name = "chongming-worker"
version = "0.1.0"
version = "0.2.0"
description = "chongming worker"
readme = "README.md"
requires-python = ">=3.12"
+41 -8
View File
@@ -18,11 +18,11 @@ Plugin 基类 — 统一 Worker 插件初始化与清理生命周期
class MyPlugin(Plugin):
type = "myname"
db_name = "myname.db" # 自动在 data_dir 下建库;不需要则置 None
db_name = "myname.db" # SQLite:自动在 data_dir 下建库;config 含 database.url 时优先走 PostgreSQL;不需要则置 None
auto_bind = True # 首次初始化时自动 auto_bind_models("myname")
async def on_init(self):
# 数据库已由基类 _bootstrap 初始化(self.db)
# 数据库已由基类 _bootstrap 初始化(self.db,SQLite 或 PostgreSQL)
self.set_var("db", self.db)
# 需要后台任务时:
# self.spawn_task(self._background_loop())
@@ -31,6 +31,15 @@ Plugin 基类 — 统一 Worker 插件初始化与清理生命周期
# 关闭自定义客户端等(后台任务与数据库由基类统一处理)
...
# PostgreSQL 接入(可选):在插件 config.toml 配置 database 段后,
# 基类 init_database() 检测到 url 即走 Database.from_config 接入 PG::
#
# # config/workers/<name>/config.toml
# [workers.config.database]
# type = "postgresql"
# url = "postgresql+asyncpg://user:pwd@127.0.0.1:5432/mydb"
# generate_schemas = true
# 暴露给 app lifespan 的模块级入口(bound method,签名与旧写法一致)
plugin = MyPlugin()
create_workers = plugin.create_workers
@@ -39,7 +48,8 @@ Plugin 基类 — 统一 Worker 插件初始化与清理生命周期
框架自动处理:
- 幂等:重复 ``create_workers`` 只会初始化一次
- 统一日志:``logger`` 自动带 ``[type]`` 前缀
- 数据库:``_bootstrap()`` / ``init_database()`` 统一建路径、建表、记录,``cleanup`` 自动 dispose
- 数据库:``_bootstrap()`` / ``init_database()`` 统一建库建表、记录,``cleanup`` 自动 dispose
(SQLite 按 ``db_name`` 建库;config 含 ``database.url`` 时优先走 PostgreSQL)
- global_var:``set_var()`` 写入插件自己的 ``global_var`` 模块(白名单由插件决定)
- 后台任务:``spawn_task()`` 跟踪,``cleanup`` 时自动取消
- 清理钩子:``register_cleanup()`` 注册,``cleanup`` 时逆序执行
@@ -70,7 +80,7 @@ class Plugin:
#: 插件类型(worker type),必须被子类覆盖
type: str = "default"
#: 默认数据库文件名(data_dir 下);None 表示不自动建库
#: 默认 SQLite 文件名(data_dir 下);config 含 database.url 时优先走 PostgreSQL;None 表示不自动建库
db_name: str | None = None
#: 首次初始化时自动调用 auto_bind_models
auto_bind: bool = True
@@ -94,11 +104,11 @@ class Plugin:
# ------------------------------------------------------------------
async def _bootstrap(self) -> None:
"""
默认资源引导:按 db_name 初始化数据库。
默认资源引导:按 db_name(SQLite)或 database.url(PostgreSQL)初始化数据库。
由基类在 on_init 之前自动调用;子类需要完全自定义建库逻辑时覆写此方法。
"""
if self.db_name:
if self.db_name or self._database_config().get("url"):
await self.init_database(self.db_name)
async def on_init(self) -> None:
@@ -195,15 +205,38 @@ class Plugin:
# ------------------------------------------------------------------
# 辅助方法
# ------------------------------------------------------------------
def _database_config(self) -> dict:
"""提取运行时配置中的 database 段(不存在或非 dict 时返回空 dict)。"""
db_conf = self.config.get("database") if isinstance(self.config, dict) else None
if isinstance(db_conf, dict):
return db_conf
return {}
async def init_database(self, filename: str | None = None) -> Any:
"""
在 data_dir 下初始化 SQLite 数据库,返回 Database 实例并存入 self.db。
初始化数据库并存入 self.db,支持两种后端:
- PostgreSQL:config 含 ``database.url``(如插件 config.toml 的
``[workers.config.database]`` 配置 type/url)时优先走 ``Database.from_config``;
- SQLite:否则在 data_dir 下按文件名建库(现有插件零改动)。
Args:
filename: 数据库文件名(默认取 self.db_name)
filename: SQLite 数据库文件名(默认取 self.db_name)
"""
from chongming_database import Database
db_conf = self._database_config()
if db_conf.get("url"):
db = Database.from_config(db_conf)
await db.initialize(
generate_schemas=db_conf.get("generate_schemas", True)
)
self.db = db
self.logger.info(
"[%s] 数据库已初始化 (PostgreSQL): %s", self.type, db_conf["url"]
)
return db
filename = filename or self.db_name
if not filename:
raise ValueError("未指定数据库文件名(请设置 db_name 或传入 filename)")