## ConnectHub 开发手册 ConnectHub 是一个轻量级企业集成中间件:统一管理多系统集成任务(Job),提供定时调度、执行监控与“一键重试”。 ### 项目结构树 ``` . ├── app │ ├── admin │ │ ├── routes.py │ │ ├── templates │ │ │ └── joblog_details.html │ │ └── views.py │ ├── core │ │ ├── config.py │ │ └── logging.py │ ├── db │ │ ├── crud.py │ │ ├── engine.py │ │ └── models.py │ ├── integrations │ │ └── base.py │ ├── jobs │ │ └── base.py │ ├── plugins │ │ └── manager.py │ ├── security │ │ └── fernet.py │ ├── tasks │ │ ├── celery_app.py │ │ ├── dispatcher.py │ │ └── execute.py │ └── main.py ├── extensions │ └── example │ ├── client.py │ └── job.py ├── docker │ └── Dockerfile ├── docker-compose.yml ├── env.example └── pyproject.toml ``` ### 环境与配置 - `env.example`:环境变量示例(由于环境限制,仓库中使用该文件名;本地运行时请手动创建 `.env` 并参考此文件) - 关键变量: - `DATA_DIR=/data`:容器内数据目录 - `DB_URL=postgresql+psycopg://connecthub:connecthub_pwd_change_me@postgres:5432/connecthub`:PostgreSQL 连接串(容器内通过 service name `postgres` 访问) - `REDIS_URL=redis://redis:6379/0`:Celery Broker/Backend - `FERNET_KEY_PATH=/data/fernet.key`:Fernet key 文件(自动生成并持久化) - `LOG_DIR=/data/logs`:日志目录(可选) ### 核心框架实现要点 #### BaseJob(插件规范) - 位置:`app/jobs/base.py` - 规范:插件必须实现 `run(params, secrets)`,其中: - `params` 来自 `Job.public_cfg`(明文) - `secrets` 来自 `Job.secret_cfg` 解密后的明文(仅内存) #### BaseClient(适配器/SDK) - 位置:`app/integrations/base.py` - 规范:业务 Job 禁止直接写 HTTP;必须通过 Client 访问外部系统(统一超时、重试、日志)。 #### Security(Fernet 加解密) - 位置:`app/security/fernet.py` - 说明: - `secret_cfg` 在数据库中保存 **Fernet 密文 token** - Worker 执行前自动解密,仅在内存中传给 Job - key 自动生成到 `FERNET_KEY_PATH`(默认 `/data/fernet.key`),volume 挂载后可持久化 #### PluginManager(动态加载) - 位置:`app/plugins/manager.py` - `handler_path` 推荐格式:`extensions.example.job:ExampleJob` ### 数据层与 Admin(SQLAdmin) - 模型:`app/db/models.py`(Job / JobLog) - Admin: - `Job`:可视化增删改查 - `JobLog`:可视化查看执行日志(只读) - `JobLog` 详情页自定义 `Retry` 按钮:点击后读取 `snapshot_params` 并触发重试 - 关键文件: - `app/admin/views.py`:ModelView 定义;保存 Job 时自动加密 `secret_cfg` - `app/admin/templates/joblog_details.html`:JobLog 详情模板覆盖,加入 Retry 按钮 - `app/admin/routes.py`:处理 Retry POST 并触发 Celery ### 任务引擎(Celery) - Celery app:`app/tasks/celery_app.py` - 调度: - Beat 每分钟触发一次 `connecthub.dispatcher.tick` - `dispatcher.tick` 读取 DB Jobs,根据 `cron_expr` 到点触发 `connecthub.execute_job` - 执行: - `app/tasks/execute.py` 的 `execute_job`:读库/解密/加载插件/执行/写 JobLog(含异常堆栈) ### 运行指南 1. 在仓库根目录创建 `.env`(参考 `env.example`) 2. 生产模式启动: ```bash docker compose up -d --build ``` 3. 打开 Admin: - `http://localhost:8000/admin` 4. 创建一个示例 Job(ExampleJob): - `id`: `example.hello` - `cron_expr`: `* * * * *`(每分钟) - `handler_path`: `extensions.example.job:ExampleJob` - `public_cfg`: `{"name":"Mars"}` - `secret_cfg`: `{"token":"demo-token"}`(保存时自动加密落库) 5. 等待 Beat 触发执行,或在 JobLog 里查看结果;若失败/想复跑,在 JobLog 详情页点击 **Retry**。 ### 开发模式(实时更新代码) 开发阶段可以使用 dev compose 叠加文件,实现: - `backend`:`uvicorn --reload` - `worker/beat`:监听代码变更后自动重启进程加载新代码 启动命令(二选一): ```bash # 方式 A:直接 docker compose 叠加 docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build # 方式 B:使用脚本 ./connecthub.sh dev-build ./connecthub.sh dev-start ``` 生产环境请只使用 `docker-compose.yml`(不挂载源码、不启用 reload/watch),发布通过重新 build 镜像完成。