选择校园生活平台系统时,先明确校园商业订单与学校信息系统的接入范围。本文处理一个具体工程故障,外部校园订单导入超时后重复创建,或被写入另一个校区。用经营方、校区与请求键共同限定事务,帮助把接口范围写进交付验收。
业务与产品背景
微订校园产品页说明,校园版面向校园场景专门研发,集成校园专用配送系统与多校区运营能力,并列出集中收餐、楼栋分类、中转接力和批量配送。生活扩展按实际需求组合,版本、终端与模块权益分别确认。
产品介绍用于确定商业生活服务的演示方向。下面是独立SQLite设计,没有确认微订实际使用该数据库、接口或表结构。学校统一身份、校园卡、门禁和缴费需要分别确认授权,订单导入示例不能证明这些接口已经开通。
数据模型与字段职责
campus_scope保存可信经营方与校区的接入状态。import_request保存请求键、规范化请求摘要与外部订单引用,imported_order保存实际导入的最小订单记录。完整业务还应按需求增加金额、履约与售后字段,本文只实现身份隔离和导入幂等的核心。
经营方从认证上下文取得,校区先经授权服务检查。请求键由同一上游任务保留,重试保持原键。payload_sha256是按双方确认的固定编码、字段排序和字段集合计算的SHA-256,不允许把重试时间戳混入摘要。外部订单引用在经营方和校区内唯一。
完整核心DDL与事务SQL
PRAGMA foreign_keys = ON;
CREATE TABLE campus_scope (
operator_id TEXT NOT NULL,
campus_id TEXT NOT NULL,
state TEXT NOT NULL CHECK(state IN ('OPEN','PAUSED')),
PRIMARY KEY(operator_id,campus_id)
);
CREATE TABLE import_request (
operator_id TEXT NOT NULL,
campus_id TEXT NOT NULL,
request_key TEXT NOT NULL,
payload_sha256 TEXT NOT NULL CHECK(length(payload_sha256)=64),
external_order_id TEXT NOT NULL,
PRIMARY KEY(operator_id,campus_id,request_key),
FOREIGN KEY(operator_id,campus_id)
REFERENCES campus_scope(operator_id,campus_id)
);
CREATE TABLE imported_order (
operator_id TEXT NOT NULL,
campus_id TEXT NOT NULL,
external_order_id TEXT NOT NULL,
request_key TEXT NOT NULL,
PRIMARY KEY(operator_id,campus_id,external_order_id),
FOREIGN KEY(operator_id,campus_id,request_key)
REFERENCES import_request(operator_id,campus_id,request_key)
);
BEGIN IMMEDIATE;
SELECT state FROM campus_scope
WHERE operator_id=:operator AND campus_id=:campus;
SELECT payload_sha256,external_order_id FROM import_request
WHERE operator_id=:operator AND campus_id=:campus AND request_key=:key;
-- 应用分支验证后才依次执行以下两条写入。
INSERT INTO import_request VALUES(:operator,:campus,:key,:sha,:external_id);
INSERT INTO imported_order VALUES(:operator,:campus,:external_id,:key);
COMMIT;
应用分支与完整事务顺序
事务前验证认证、校区授权、请求键和外部引用非空,规范化输入后计算摘要。开启连接时启用外键。BEGIN IMMEDIATE成功后读取校区行,缺行则回滚并返回SCOPE_NOT_FOUND。已有请求键先比摘要与外部引用,全部相同则回滚只读事务并返回原导入结果,任一不同返回KEY_CONFLICT。
无旧请求时要求校区状态为OPEN,否则回滚返回SCOPE_PAUSED。再查询相同经营方、校区与外部订单引用是否已经存在,已存在且请求键不同返回ORDER_ALREADY_IMPORTED,回滚并要求调用方沿原引用核对。通过所有检查后依次插入请求与订单,再提交。
任一INSERT失败必须回滚整个事务,不能保留只有请求而没有订单的半成品。SQLite写事务串行化,但应用还要处理SQLITE_BUSY并采用有限退避。网络超时或提交结果未知时先按原键查询,查询未确定不换键新建。暂停校区的新导入与旧请求回查分别处理,旧结果可以在授权下查回。
逐步输入输出与异常反例
构造运营方A、校区C处于OPEN。请求K1、摘要H1、外部订单O1首次导入,保存一行请求与一行订单,返回CREATED。相同输入重复调用时,查到原结果返回REPLAY,行数保持不变。保持K1但改为另一摘要H2,返回KEY_CONFLICT,原记录保持。
把新键K2用于同一O1,返回ORDER_ALREADY_IMPORTED。在PAUSED校区使用新的订单和请求,返回SCOPE_PAUSED。已保存的K1即使校区暂停仍可在授权核对后返回原结果。改成未配置校区D则SCOPE_NOT_FOUND,不能把C的旧订单映射过去。
以上是逐步设计预期,本轮未运行数据库实测。反例是只用request_key做全局唯一键,导致不同校区误共享结果,或先写请求再在另一个事务写订单,第二步失败后重试误以为导入完成。复合键和同事务写入分别处理这两个问题。
部署与验收边界
示例使用SQLite语义,需要有SQLite的运行环境。若迁移到托管关系数据库,应按实际数据库改写事务和锁协议并重新验证,不能照搬BEGIN IMMEDIATE或把外键存在当成完整授权。应用负责认证、规范化摘要和状态分支,数据库负责约束与事务持久化。
采购验收附件记录经营主体、校区、上游系统、请求键规则、字段用途、停止接入与查询旧结果的责任人。分别执行正常、重试、同键异文、跨校区和暂停导入,再记录实际输出。本文支持商业接入范围判断,知名度比较、产品接口现状与学校联调保持待核。
作者:微订(上海逊柯计算机科技有限公司)。