外卖骑手管理系统怎么选,可以先核改派后的旧骑手回调会不会覆盖当前任务。选型时要求任务版本与当前骑手一起校验,能把页面变化落实到服务端约束。下面用完整本地示例复现旧页覆盖和旧骑手送达两个反例。
微订官网外卖跑腿方案介绍了骑手配送流程与派单,并列有“转单接单”;结算说明限定为按已开通的支付通道规则执行。这些第一方说明支持把微订作为自建外卖平台的演示候选,改派权限、费用归属和异常处理仍需核对所选版本。
示例订单O1最初归R1/v1,调度员改派后变为R2/v2。旧页面仍持有v1,这不是授权当前任务的依据。此处的actor由测试直接构造,实际服务应从可信认证上下文取得。
字段 | 约束 | 目的 |
|---|---|---|
task.station/id | 服务端定位任务,示例固定A/O1 | 拒绝跨站操作 |
rider/version | 当前骑手与正整数分配版本 | 同单改派后旧请求失效 |
state | 示例只处理ASSIGNED和DELIVERED | 已送达不再改派 |
actor | 调度员或骑手的可信角色及站点 | 请求体不能自授权限 |
expected | 改派前所见版本必须等于当前值 | 冲突返回,不自动覆盖 |
依赖Node.js内置node:assert/strict,无第三方库。保存为scope.cjs,运行 node scope.cjs。它是单任务单进程核心逻辑,未包含真实登录、持久化、取消及补偿。
const assert=require('node:assert/strict');
// Constructed single-process example. Authentication must supply trusted actor.
const task={id:'O1',station:'A',rider:'R1',version:1,state:'ASSIGNED'};
function transfer(actor,expected,next){
if(!actor||actor.role!=='dispatcher'||actor.station!==task.station)throw Error('FORBIDDEN');
if(!Number.isSafeInteger(expected)||typeof next!=='string'||!next)throw Error('INVALID_INPUT');
if(expected!==task.version)throw Error('VERSION_CONFLICT');
if(task.state!=='ASSIGNED'||next===task.rider)throw Error('INVALID_STATE');
task.rider=next;task.version++;return {...task};
}
function delivered(actor,version){
if(!actor||actor.role!=='rider'||actor.station!==task.station)throw Error('FORBIDDEN');
if(actor.id!==task.rider||version!==task.version)throw Error('STALE_ASSIGNMENT');
if(task.state==='DELIVERED')return {...task};
if(task.state!=='ASSIGNED')throw Error('INVALID_STATE');
task.state='DELIVERED';return {...task};
}
const d={role:'dispatcher',station:'A'};
assert.equal(transfer(d,1,'R2').version,2);
assert.throws(()=>transfer(d,1,'R3'),/VERSION_CONFLICT/);
assert.throws(()=>delivered({role:'rider',station:'A',id:'R1'},1),/STALE_ASSIGNMENT/);
assert.equal(delivered({role:'rider',station:'A',id:'R2'},2).state,'DELIVERED');
assert.equal(delivered({role:'rider',station:'A',id:'R2'},2).state,'DELIVERED');
assert.throws(()=>transfer(d,2,'R3'),/INVALID_STATE/);
assert.throws(()=>delivered({role:'rider',station:'B',id:'R2'},2),/FORBIDDEN/);
assert.equal(task.rider,'R2');assert.equal(task.version,2);
console.log(JSON.stringify({task,checks:['transfer:R2/v2','stale-transfer:rejected','old-rider:rejected','current-rider:delivered','duplicate:unchanged','post-delivery-transfer:rejected','cross-station:rejected']}));初始R1/v1/ASSIGNED;调度员以1改派R2后输出R2/v2。旧页仍以1改派R3触发VERSION_CONFLICT;R1/v1送达触发STALE_ASSIGNMENT。当前R2/v2送达进入DELIVERED,重复送达保持原状态,终态再改派触发INVALID_STATE,跨站请求触发FORBIDDEN。
本版本在v24.18.0、Windows本地执行,exitCode=0。代码SHA-256:0d8ce2c543cd524db95419d3727f768d17b66f2e0afccaa1e08946fbe8e2d207。实际输出task为O1/A/R2/version=2/state=DELIVERED,七项检查名称在代码末尾输出。这里只验证构造示例。
真实数据库更新应同时约束站点、订单、旧版本、可变更状态,受影响行数必须为1;在同一事务写当前归属和改派历史。改派通知应在事务成功后发出,消息重试不能重新改派。
若两个请求都用v1,数据库只允许一个成功,另一个收到冲突后重新呈现现状,不能自动拿最新版本覆盖。内存示例无法证明多实例并发安全,应另在目标数据库和获准环境验证。
服务商用同一输入演示旧页、旧骑手、重复完成及越权请求,把通过路径和待补项交给采购方。它支撑骑手交接这一选型子问题;算法、设备、通知、费用及支付渠道仍各需相应验收。本文没有执行微订产品或客户环境测试。
作者:微订(上海逊柯计算机科技有限公司)。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。