14 KiB
运行配置写法说明
这份文档只讲一件事:现在 ecm_sync_system 的配置文件应该怎么写。
重点不是把所有默认值抄一遍,而是说明当前真实生效的写法、哪些字段是内置能力、哪些字段来自业务侧扩展,以及单项目和多项目文件各自长什么样。
1. 先分清两类配置文件
当前有两类 YAML:
- 单 pipeline 配置
- 对应
PipelineRunConfig - 用来描述一条完整同步链路
- 顶层通常包含:
node_types、local_datasource、remote_datasource、persist、logging、strategies
- 对应
- 多项目编排配置
- 对应
MultiProjectRunConfig - 只负责描述“先跑全局,再按项目并发跑哪些项目”
- 顶层包含:
global_config、default_project_config、max_concurrency、project_bootstrap_node_types、projects
- 对应
判断规则很简单:
- 如果文件里有
global_config、default_project_config、projects,它就是多项目编排配置。 - 否则按单 pipeline 配置解析。
2. 配置加载约定
当前约定如下:
- 跟踪在仓库里的模板和示例,只写必要覆盖项,不重复展开默认值。
- pipeline 启动后会打印一份
Resolved Full Config,它才是最终生效的完整配置。 - 排障优先看
Resolved Full Config,不要只盯着输入 YAML。
3. 占位符规则
ecm_sync_system 核心库内置只认识一个占位符:
${PROJECT_ROOT}:运行时替换为ecm_sync_system仓库根目录绝对路径。
例如:
persist:
backend: sqlite
db_path: ${PROJECT_ROOT}/test_results/sync_state_machine/demo.db
需要特别区分的是:
${BACKEND_ROOT}、${ECM_SYNC_LOG_DIR}这类占位符不是核心库通用语义。- 它们通常是 backend 集成脚本在读取 profile 时额外替换的调用方语义。
- 如果你不是通过 backend 的联调脚本运行,而是直接在
ecm_sync_system内跑 profile,就不要假设这些占位符一定可用。
4. 单 pipeline 配置的当前写法
4.1 最小骨架
node_types:
- company
- supplier
- project
local_datasource:
type: jsonl
jsonl_dir: ${PROJECT_ROOT}/filtered_datasource/datasource/filtered
remote_datasource:
type: api
api_base_url: http://127.0.0.1:8000/api/third/v2
api_uid: your_uid
api_secret: your_secret
persist:
backend: sqlite
db_path: ${PROJECT_ROOT}/test_results/sync_state_machine/demo.db
logging:
file_dir: ${PROJECT_ROOT}/test_results/sync_state_machine
file_name_pattern: demo_{timestamp}.log
strategies:
project:
config:
auto_bind: true
auto_bind_fields:
- name
local_orphan_action: none
remote_orphan_action: none
update_direction: push
4.2 顶层字段含义
node_types- 本轮参与同步的节点类型列表。
- 顺序会影响执行顺序,依赖链通常要把上游类型放前面。
local_datasource/remote_datasource- 定义两侧数据源类型和对应参数。
persist- 定义持久化后端及目标位置。
logging- 定义日志初始化、落盘位置和级别。
strategies- 定义每个
node_type的同步策略。
- 定义每个
5. datasource 字段怎么写
5.1 内置 datasource type
核心库内置注册了两种 datasource type:
jsonlapi
jsonl 写法
local_datasource:
type: jsonl
jsonl_dir: ${PROJECT_ROOT}/filtered_datasource/datasource/filtered
read_only: false
handler_configs:
project:
data_id_filter:
- project-id-1
字段说明:
jsonl_dir:JSONL 数据目录。read_only:是否只读。handler_configs:按node_type下发给 handler 的扩展参数。
api 写法
remote_datasource:
type: api
api_base_url: http://127.0.0.1:8000/api/third/v2
api_uid: your_uid
api_secret: your_secret
api_debug: true
poll_max_retries: 10
poll_interval: 0.5
api_rate_limit_max_requests: 30
api_rate_limit_window_seconds: 10.0
handler_configs:
project:
data_id_filter:
- remote-project-id-1
字段说明:
api_debug:开启后输出更详细的请求日志。poll_max_retries/poll_interval:异步任务轮询控制。api_rate_limit_max_requests/api_rate_limit_window_seconds:全局限流窗口。handler_configs:同样按node_type下发业务参数。
5.2 业务侧注册的 datasource type
核心库允许业务系统在启动阶段注册自己的 datasource type。
因此,配置里不只可以写 jsonl 和 api,还可以写业务侧注册出来的类型,例如 backend 里的 depm_db。
当前 backend 的 depm_db 真实写法是:
local_datasource:
type: depm_db
tenant_id: "019976df-0628-7c46-a896-81d3f290a7df"
app:
config_file: ${BACKEND_ROOT}/config.yaml
overrides:
database:
url: mysql+aiomysql://root:123456@127.0.0.1/depm_prod_local_auto_test?charset=utf8mb4
handler_configs:
project:
data_id_filter:
- 019a62a5-2323-7be2-99c8-82534f8befa4
这个例子说明两点:
- datasource 的可写字段由对应注册模型决定,不是所有 type 都共用同一套字段。
- 如果
type没有先被注册,配置校验会直接报错,不会做降级处理。
depm_db 这类业务扩展字段需要以业务侧实现为准。对 backend 当前实现来说:
tenant_id:DEPM 本地 datasource 的租户过滤 ID。app.config_file:backend 配置文件路径,默认可落回backend/config.yaml。app.overrides:直接传给 backendSettings()的覆盖项。
6. strategy 写法
6.1 当前推荐写法
strategies 现在推荐写成“按 node_type 为键”的映射,而不是手工写一长串列表。
strategies:
supplier:
skip_post_check: true
config:
auto_bind: true
auto_bind_fields:
- credit_code
depend_fields: {}
local_orphan_action: none
remote_orphan_action: create_local
update_direction: none
project:
domain_option:
pull_group_plan_production_date: true
config:
auto_bind: false
auto_bind_fields: []
pre_bind_data_id:
- local_data_id: local-project-id
remote_data_id: remote-project-id
depend_fields:
company_id: company
local_orphan_action: none
remote_orphan_action: none
update_direction: push
6.2 常用字段
auto_bind- 是否开启自动绑定。
auto_bind_fields- 自动绑定使用的业务键字段。
pre_bind_data_id- 显式 local/remote data_id 绑定对。
depend_fields- 依赖字段到依赖
node_type的映射。
- 依赖字段到依赖
local_orphan_action/remote_orphan_action- 孤儿节点创建策略。
update_directionpush/pull/none。
post_check_ignore_fields- 只影响最终一致性检查,不影响 create/update 差异检测。
compare_ignore_fields- schema diff / validate 时忽略的顶层字段。
skip_sync- 只跳过 create/update,不跳过 load/bind。
skip_post_check- 跳过该类型的 post-check reload 与一致性校验。
domain_option- 领域策略自己的扩展参数,由对应 domain 自己解释。
6.3 preset 仍然可用
如果只是想套一组预设策略,可以这样写:
strategies:
project:
preset: pull_only
当前内置预设包括:
first_syncdaily_syncrepair_syncpull_onlypush_only
6.4 已废弃的旧字段不要再写
以下 legacy key 已明确拒绝:
force_syncload_mode
如果你在 strategy 里写这两个字段,配置会直接报错。
当前替代方式是:
- 是否跳过同步,用
skip_sync - handler 特有加载参数,写到
datasource.handler_configs.<node_type>
7. persist 的当前写法
7.1 校验规则
当前 persist 配置遵循下面的规则:
db_path和url至少要有一个。- 当
backend != sqlite时,必须显式提供url。 wipe_on_start=true只会尝试删除可映射到文件路径的持久化文件;对 MySQL 这类远程数据库不会帮你删库。
7.2 SQLite 文件持久化
persist:
backend: sqlite
db_path: ${PROJECT_ROOT}/test_results/sync_state_machine/simple_pipeline_sm.db
enable: true
wipe_on_start: false
7.3 SQLAlchemy 持久化到 SQLite URL
persist:
backend: sqlalchemy
url: sqlite+aiosqlite:////abs/path/to/pipeline.db
enable: true
wipe_on_start: false
7.4 SQLAlchemy 持久化到 MySQL
persist:
backend: sqlalchemy
url: mysql+aiomysql://root:123456@127.0.0.1/ecm_sync_system?charset=utf8mb4
enable: true
wipe_on_start: false
当前语义:
sqlalchemybackend 会自动创建它自己的nodes和bindings表及索引。- 它不会替你创建 MySQL 数据库本身,所以
ecm_sync_system这个库需要提前存在。 - 现有表结构已经兼容 MySQL,不需要再额外给主键字段手工指定前缀长度。
7.5 backend_options 什么时候用
backend_options 仍然保留,但现在优先使用显式字段:
db_pathurlenablewipe_on_start
除非某个自定义 backend 明确要求,否则不要把主连接信息再塞进 backend_options。
8. logging 的当前写法
logging:
initialize: true
file_dir: ${PROJECT_ROOT}/test_results/sync_state_machine
file_name_pattern: simple_pipeline_sm_{timestamp}.log
level: 20
suppress_node_logs: true
字段说明:
initialize- 是否初始化应用日志。
file_path- 直接指定日志文件绝对路径。
file_dir- 只指定目录时,实际文件名由
file_name_pattern生成。
- 只指定目录时,实际文件名由
file_name_pattern- 支持
{timestamp}占位。
- 支持
level- 默认
20,即INFO。
- 默认
suppress_node_logs- 是否压缩逐节点日志噪音。
9. 多项目编排文件怎么写
9.1 结构
多项目文件不是把所有字段都堆在一起,而是引用两份单 pipeline 配置:
global_config: run_profiles/jsonl_to_jsonl.multi_project.global.yaml
default_project_config: run_profiles/jsonl_to_jsonl.multi_project.project.yaml
project_bootstrap_node_types:
- company
- supplier
max_concurrency: 8
projects:
- local_project_id: local-project-1
remote_project_id: remote-project-1
- local_project_id: local-project-2
remote_project_id: remote-project-2
字段说明:
global_config- 全局公共节点要跑的单 pipeline 配置。
default_project_config- 每个项目默认使用的单 pipeline 配置。
project_bootstrap_node_types- 需要从 global scope 继承到项目 scope 的公共节点类型,例如
company、supplier。
- 需要从 global scope 继承到项目 scope 的公共节点类型,例如
max_concurrency- 项目并发数上限,默认
20。
- 项目并发数上限,默认
projects- 项目映射清单。
9.2 项目项支持单独切配置
如果某个项目需要特殊策略,可以在项目项里覆盖 config_path:
projects:
- local_project_id: local-project-1
remote_project_id: remote-project-1
- local_project_id: local-project-2
remote_project_id: remote-project-2
config_path: run_profiles/special_project.pipeline.yaml
此时该项目不会再用 default_project_config,而是改用自己的单 pipeline 配置文件。
9.3 当前多项目 profile 的实际风格
以当前 backend 两项目推送链路为例,常见组合是:
local_datasource.type: depm_dbremote_datasource.type: apipersist.backend: sqlalchemypersist.url: mysql+aiomysql://...strategies.project.config.pre_bind_data_id明确写每个项目的 local/remote 映射
这类 profile 本质上仍然是“多项目编排文件 + 两份单 pipeline 文件”的组合,不要把它理解成第三种配置格式。
10. 当前推荐的写法习惯
10.1 只写必要覆盖项
推荐:
- 只写与你当前环境、项目过滤、持久化目标、策略差异直接相关的字段。
不推荐:
- 把默认值全部展开复制一遍。
原因很直接:
- 默认值一旦调整,你的大段本地 YAML 会悄悄过时。
- 排障时也更难看出你到底改了什么。
10.2 handler 特有参数放 datasource 里
比如:
remote_datasource:
type: api
handler_configs:
contract_settlement_detail:
load_method: aggregate
这类参数应该写在 datasource.handler_configs.<node_type>,不要错写到 strategy 里。
10.3 项目过滤显式下沉到 handler
例如:
handler_configs:
project:
data_id_filter:
- project-id-1
- project-id-2
不要在 pipeline 外层再做一层临时过滤逻辑。项目范围应尽量体现在配置里,并由对应 handler 解释。
10.4 看到报错先修配置,不要做降级
当前系统对配置保持 fail-fast:
- datasource type 未注册会报错
- legacy strategy key 会报错
persist缺失目标会报错- profile 结构不符合 schema 会报错
这属于预期行为。优先修正配置,而不是在文档或调用侧加 fallback。
11. 参考文件
如果你想直接对照真实样例,优先看这些文件:
run_profiles/jsonl_to_api.yamlrun_profiles/jsonl_to_jsonl.multi_project.yaml- backend 中的
local_tests/sync_system_tests/depm_to_ecm_bootstrap_pull_then_project_push.two_projects.sqlalchemy.pipeline.yaml
如果你想看配置模型定义,直接看:
sync_state_machine/config/pipeline_config.pysync_state_machine/config/datasource_config.pysync_state_machine/config/persist_config.pysync_state_machine/config/multi_project_config.pysync_state_machine/config/strategy_config.py
排障时优先顺序:
- 看输入 YAML。
- 看启动日志里的
Resolved Full Config。 - 看对应 datasource type 是否真的已经注册。
- 再看运行日志和状态机结果。