1
0
forked from erp-dev/erp
Files
erpnew/docs/mdy_plate_order_sync.md

6.2 KiB
Raw Blame History

MDY明道云PlateOrder 同步:任务 / Command / 数据查询说明

这份文档解决什么问题

当你忘记:

  • PlateOrder开版数据表是否有定时同步
  • 手动怎么跑同步?
  • 同步的数据落到哪里、怎么查?

直接看本文档即可。


一、同步“是什么”:从明道云到哪里?

1) 同步目标表(本地暂存)

同步会把明道云“开版数据表”的行写入本地暂存表:

  • 模型:api_v1.models.MDYPlateOrderStaging
  • 字段:
    • mdy_rowid:明道云 rowid唯一
    • raw整行原始数据JSON
    • related可选跨表关联数据list[dict],已做碾平)
    • ctime/utime:明道云系统时间字段(用于排序/增量)

2) 增量游标checkpoint

同步进度记录在:

  • 模型:api_v1.models.DataSync
  • 表名枚举:DataSync.TableName.PLATE_ORDER

Command 默认会读取/写入 checkpoint可以通过参数关闭。


二、有没有“定时任务”Celery Beat

结论:当前没有把 PlateOrder 同步加入 CELERY_BEAT_SCHEDULE

目前 flower/settings.py 里看到的 mdy 定时任务只有:

  • mdy_product_sync:每 10 分钟(api_v1.tasks.sync_mdy_products
  • mdy_customer_sync:每 5 分钟(api_v1.tasks.sync_mdy_customers

但代码里确实存在 PlateOrder 的 Celery task见下文只是 未配置到 beat schedule

补充:与“同步”不同,项目已新增一条“开版暂存 → 腾讯云 TIIA 图库上传”的定时任务(用于把暂存表中的开版图入库到腾讯图库),它是单独的 beat 项,详见:

  • docs/tiia_image_gallery.md 的 “四点五、MDY 开版暂存图片上传到图库”
  • flower/settings.pyCELERY_BEAT_SCHEDULE['daily_mdy_plate_order_staging_tiia_image_upload'](默认 03:20

三、如何手动运行推荐management command

Commandsync_mdy_plate_orders

入口文件:

  • api_v1/management/commands/sync_mdy_plate_orders.py

最常用用法:

  • 默认增量同步(使用 DataSync checkpoint默认抓关联表数据
    • uv run python manage.py sync_mdy_plate_orders

常用参数:

  • --page-size 100:每页拉取条数(默认 100
  • --max-pages 2:本次最多处理多少页(不是最大页码)
  • --max-records 200:本次最多处理多少条
  • --with-related / --without-related:是否抓取跨表关联数据(默认 with-related
  • --max-related-per-type 5:每种关联表最多拉多少条 rowid
  • --request-interval-seconds 0.02每次明道云请求之间最小间隔限流0.02≈50qps
  • --use-checkpoint / --skip-checkpoint:是否读取 DataSync 游标(默认 use
  • --update-checkpoint / --skip-checkpoint-write:是否写入 DataSync 记录(默认写)
  • --sort-direction asc|desc:按 ctime 升/降序抓取(默认 asc

示例:

  • 只拉主表、不拉关联(更快):
    • uv run python manage.py sync_mdy_plate_orders --without-related
  • 从头全量跑一段(不读 checkpoint且跑完不写 checkpoint
    • uv run python manage.py sync_mdy_plate_orders --skip-checkpoint --skip-checkpoint-write
  • 控制单次任务规模(避免跑太久):
    • uv run python manage.py sync_mdy_plate_orders --page-size 100 --max-pages 3 --max-records 250

四、如何通过 Celery 运行(可选)

Celery Taskapi_v1.tasks.sync_mdy_plate_orders

位置:

  • api_v1/tasks.pytask 名:sync_mdy_plate_orders

说明:

  • 该 task 内部调用 api_v1.mdy_plate_order_sync.sync_mdy_plate_orders_to_staging
  • 该 task 目前不在 beat schedule,但可以手动触发

两种触发方式(任选其一):

  1. 通过 celery call适合已有 worker 环境):

    • uv run celery -A flower call api_v1.tasks.sync_mdy_plate_orders --kwargs='{"page_size":100,"max_pages":2,"with_related":true,"request_interval_seconds":0.02}'
  2. 通过 Django shell适合本地临时验证

    • uv run python manage.py shell -c "from api_v1.tasks import sync_mdy_plate_orders; r=sync_mdy_plate_orders.delay(page_size=100,max_pages=2); print(r.id)"

如果你确实需要“定时同步 PlateOrder”可以把该 task 加进 CELERY_BEAT_SCHEDULE;但这属于策略选择(数据量/频率/接口限流),当前项目默认没开。


五、同步后如何查询API

暂存查询接口(只读)

文档:

  • docs/api_v1_mdy_plate_order_staging.md

接口:

  • ListGET /api/v1/mdy-plate-order-staging/?limit=20&offset=0
  • DetailGET /api/v1/mdy-plate-order-staging/{id}/

说明:

  • 支持 LimitOffset 分页
  • 支持按“内部字段名”的 query param 过滤(对前端隐藏 JSONField 细节)

六、相关实现入口(定位用)

  • 同步逻辑(写入暂存+checkpointapi_v1/mdy_plate_order_sync.py
  • 拉取明道云 rowsflower/utils/mingdaoyun/fetch.pyfetch_plate_orders_from_mingdaoyun
  • 明道云客户端:flower/utils/mingdaoyun/client.py(当前 appKey/sign 仍是硬编码)
  • 暂存查询 APIapi_v1/views/mingdaoyun/plate_order_staging.py

七、常见报错:duplicate key value violates ... api_mdy_plate_order_staging_pkey

这到底是哪种“唯一性冲突”?

api_mdy_plate_order_staging_pkey主键id 的约束名,不是 mdy_rowid 的 unique。

这类报错通常意味着:PostgreSQL 自增序列sequence落后于当前表内的最大 id(常见于 restore/copy/import 后)。

当前代码如何处理

sync_mdy_plate_orders_to_staging 在写入暂存表时,如果遇到该主键冲突,会:

  • 自动重置该表的 id sequence 到 MAX(id)(使下一次插入从 MAX(id)+1 开始)
  • 然后对当前 row 再重试一次写入

对应实现:api_v1/mdy_plate_order_sync.py_reset_mdy_plate_order_staging_id_sequence()

手动修复(可选)

如果你想一次性手动修复,可在 PostgreSQL 执行(把 sequence 名替换为实际值):

SELECT setval(
  pg_get_serial_sequence('api_mdy_plate_order_staging', 'id'),
  COALESCE((SELECT MAX(id) FROM api_mdy_plate_order_staging), 1),
  true
);