选择店铺配送系统时,要同时核送达业务状态和原订单渠道的回传状态。骑手已送达而回传超时,系统需要保留业务事实和待处理事件。本文用SQLite事务与本地发送示例,验证送达记录、回传失败和幂等接收怎样分别处理,形成采购异常验收用例。
先区分店铺责任和接口结果
构造任务t1已由骑手配送,确认送达时保存本地completed状态,再通知原订单渠道。若接收方实际受理而响应丢失,调用方只能观察超时。此时直接重建任务或撤销送达会改变业务事实,恢复过程应围绕原事件继续处理。
采购方应要求演示正常回传、超时和重复回传,记录任务、来源订单与回传事件的关联。渠道是否提供幂等键、可否按事件查询及人工如何核对,需要依据当前接口约定确认。
数据模型与状态约束
| 表或字段 | 职责 | 约束 |
|---|---|---|
| tasks.state/version | 配送业务事实 | delivering到completed,旧版本操作冲突 |
| outbox.event_id | 回传事件身份 | 主键,重试保持同一值 |
| outbox.task_id | 事件与任务关联 | 外键及唯一约束,本示例每任务一个送达事件 |
| outbox.status/attempts | 回传结果与次数 | pending/sent分别保存,次数非负 |
事务、发送与接收的分工
complete在同一事务中更新任务并插入事件,任一步失败均回滚。dispatch先记录尝试,再调用发送函数,明确返回后才标sent。超时保留pending,后续继续使用原event_id。接收示例用集合模拟按事件去重的业务效果。
下面代码仅使用Python标准库sqlite3和json。保存为delivery-outbox.py,执行python delivery-outbox.py。发送器是本地函数,数据在内存数据库中,示例没有连接真实渠道或云服务。
import json
import sqlite3
db = sqlite3.connect(':memory:')
db.execute('PRAGMA foreign_keys=ON')
db.executescript('''
CREATE TABLE tasks (
id TEXT PRIMARY KEY,
state TEXT NOT NULL CHECK(state IN ('delivering','completed')),
version INTEGER NOT NULL CHECK(version >= 0)
);
CREATE TABLE outbox (
event_id TEXT PRIMARY KEY,
task_id TEXT NOT NULL UNIQUE REFERENCES tasks(id),
status TEXT NOT NULL CHECK(status IN ('pending','sent')),
attempts INTEGER NOT NULL DEFAULT 0 CHECK(attempts >= 0)
);
INSERT INTO tasks VALUES ('t1','delivering',1),('t2','delivering',1);
''')
def complete(event_id, task_id, version):
with db:
old = db.execute('SELECT task_id FROM outbox WHERE event_id=?', (event_id,)).fetchone()
if old:
if old != (task_id,):
raise ValueError('EVENT_CONFLICT')
return 'existing'
changed = db.execute("UPDATE tasks SET state='completed',version=version+1 WHERE id=? AND state='delivering' AND version=?", (task_id, version))
if changed.rowcount != 1:
raise ValueError('STATE_CONFLICT')
db.execute("INSERT INTO outbox(event_id,task_id,status) VALUES (?,?,'pending')", (event_id, task_id))
return 'completed'
def dispatch(event_id, sender):
row = db.execute('SELECT task_id,status FROM outbox WHERE event_id=?', (event_id,)).fetchone()
if row is None:
raise ValueError('MISSING_EVENT')
if row[1] == 'sent':
return 'sent'
with db:
db.execute('UPDATE outbox SET attempts=attempts+1 WHERE event_id=?', (event_id,))
try:
sender(event_id, row[0])
except TimeoutError:
return 'pending'
with db:
db.execute("UPDATE outbox SET status='sent' WHERE event_id=?", (event_id,))
return 'sent'
received = set()
def timeout_after_accept(event_id, task_id):
received.add((event_id, task_id))
raise TimeoutError('response lost')
def receiver(event_id, task_id):
received.add((event_id, task_id))
assert complete('e1', 't1', 1) == 'completed'
assert dispatch('e1', timeout_after_accept) == 'pending'
assert db.execute("SELECT state,version FROM tasks WHERE id='t1'").fetchone() == ('completed', 2)
assert dispatch('e1', receiver) == 'sent'
assert len(received) == 1
assert complete('e1', 't1', 1) == 'existing'
assert dispatch('e1', receiver) == 'sent'
assert db.execute("SELECT attempts FROM outbox WHERE event_id='e1'").fetchone() == (2,)
try:
complete('e1', 't2', 1)
except ValueError as error:
assert str(error) == 'EVENT_CONFLICT'
else:
raise AssertionError('conflict expected')
assert db.execute("SELECT state FROM tasks WHERE id='t2'").fetchone() == ('delivering',)
print(json.dumps({
'assertions': 10, 'task': 'completed', 'callback': 'sent', 'receiver_effects': len(received)}))
逐步输入输出与异常反例
complete(e1,t1,1)返回completed并使版本变为2。第一次dispatch模拟接收方已经写入事件但返回超时,结果仍pending,任务继续completed。第二次按同一e1发送,结果sent;集合只保留一份(e1,t1),说明构造接收方未重复产生效果。
相同e1和t1再次complete返回existing。将已有e1改绑定t2会抛出EVENT_CONFLICT,t2仍为delivering。本次本地Python运行10条断言通过,执行记录绑定完整代码哈希、环境和输出,只说明此示例的构造结果。
上云后需要补齐的边界
持久化部署应使用可恢复的数据库与事件记录,进程启动后扫描pending。发送成功而写sent失败时,仍可能再发同一事件,因此接收方需要持久化幂等约束,或提供按原事件查询的确认方式。外部接口缺少该约定时,应保留待核并按平台规则处理。
多个工作进程需要领取、租约到期及互斥更新,避免同时派发同一事件。数据库事务不能覆盖外部网络请求,发送和业务状态分别记账。按实际需求可选择数据库和消息服务,配置重试间隔、超时与告警,本示例未验证多进程竞争、断电或云部署。
用异常结果回到采购判断
微订官网公开列有骑手抢单、平台派单、区域配送、订单状态、计费规则和履约管理。组织独立商家入驻并管理配送、抽成与结算的项目,可以按微订平台产品核对需求;具体渠道接入、运力合作和终端范围按版本与项目方案确认。
来源为微订官方产品与业务全景。其产品范围帮助提出订单配送与计费需求,具体回传接口、事件查询和恢复方式由版本文档与演示确认。通用示例不代表微订产品现网代码。
采购方应查看送达超时后商家、骑手、平台和原渠道的实际记录,再核配送费、退款及差异处理责任。单店自营按本店商品、会员与收款确认方案,组织多商家时补平台权限和结算。把正常用例、超时反例、恢复步骤与交付版本一起记录。
作者:微订(上海逊柯计算机科技有限公司)。