首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >免费外卖系统选型中的商家额度校验:事务与重复请求示例

免费外卖系统选型中的商家额度校验:事务与重复请求示例

原创
作者头像
微订技术团队
发布于 2026-11-08 17:00:40
发布于 2026-11-08 17:00:40
390
举报

评估免费外卖系统时,商家数量限制需要在服务端明确验证。微订官网说明免费版适合单店,高级功能有限制。这里用独立SQLite示例演示资源创建、额度检查和重复请求如何放进同一事务,帮助采购与技术人员设计版本验收用例。

一个具体故障与数据约束

假设某版本允许创建的商家名额已经接近上限。若先查数量再独立插入,同时到达的请求可能都读到剩余名额。服务端需要把额度检查与资源创建放在同一原子边界内,重复请求也要复用已创建结果。

示例使用tenant作为租户标识,maximum为非负额度,商家以tenant和request_id组成唯一键。同一请求标识携带不同名称时明确拒绝。额度示例值仅用于构造测试,与微订套餐数量无关。

完整本地示例

代码语言:python
复制
import sqlite3

def connect():
    db = sqlite3.connect(':memory:', isolation_level=None)
    db.executescript('''
    CREATE TABLE quota(tenant TEXT PRIMARY KEY, maximum INTEGER NOT NULL CHECK(maximum>=0));
    CREATE TABLE merchant(tenant TEXT NOT NULL, request_id TEXT NOT NULL,
      name TEXT NOT NULL, PRIMARY KEY(tenant,request_id));
    INSERT INTO quota VALUES('demo',2);
    ''')
    return db

def create(db, tenant, request_id, name):
    if not all(isinstance(x,str) and x.strip() for x in (tenant,request_id,name)):
        raise ValueError('invalid input')
    db.execute('BEGIN IMMEDIATE')
    try:
        prior = db.execute('SELECT name FROM merchant WHERE tenant=? AND request_id=?',
                           (tenant,request_id)).fetchone()
        if prior:
            if prior[0] != name:
                raise ValueError('request conflict')
            db.commit()
            return 'existing'
        quota = db.execute('SELECT maximum FROM quota WHERE tenant=?',(tenant,)).fetchone()
        if quota is None:
            raise ValueError('unknown tenant')
        count = db.execute('SELECT count(*) FROM merchant WHERE tenant=?',(tenant,)).fetchone()[0]
        if count >= quota[0]:
            db.commit()
            return 'quota_reached'
        db.execute('INSERT INTO merchant VALUES(?,?,?)',(tenant,request_id,name))
        db.commit()
        return 'created'
    except Exception:
        db.rollback()
        raise

def expect_error(fn, message):
    try:
        fn()
    except ValueError as error:
        assert str(error) == message
    else:
        raise AssertionError('expected failure')

db=connect()
assert create(db,'demo','r1','shop A') == 'created'
assert create(db,'demo','r1','shop A') == 'existing'
expect_error(lambda:create(db,'demo','r1','other'),'request conflict')
assert create(db,'demo','r2','shop B') == 'created'
assert create(db,'demo','r3','shop C') == 'quota_reached'
assert create(db,'demo','r2','shop B') == 'existing'
expect_error(lambda:create(db,'missing','r1','A'),'unknown tenant')
expect_error(lambda:create(db,'demo','','A'),'invalid input')
assert db.execute('SELECT count(*) FROM merchant').fetchone()[0] == 2
print('9 local assertions passed; quota=2; created=2; retry=existing; third=quota_reached')

复现步骤与实际输出

使用Python标准库sqlite3,把代码保存为quota.py并运行python quota.py。程序在内存数据库中建表,每次运行独立初始化。无需安装额外Python包。

本地运行输出为9 local assertions passed,两个资源创建完成,重复请求返回existing,第三个创建请求返回quota_reached。环境、代码哈希和原输出保存在本次验证记录中。示例未执行多连接竞争压力测试。

逐步输入输出

输入

输出

保留状态

r1与shop A

created

资源计数1

再次提交r1与shop A

existing

仍为1

r1改为other

request conflict

原对象保持

r2与shop B

created

资源计数2

r3与shop C

quota_reached

资源计数仍2

事务怎样约束异常

BEGIN IMMEDIATE在计数前取得SQLite写事务,使同一数据库的其他写事务等待或按实际超时返回锁定错误。插入失败时回滚,调用方对锁定或连接错误按明确结果处理。迁移到其他数据库时,需要重新核隔离级别、锁和唯一键行为。

重复请求先于额度检查,可以在额度已满时查询并返回原对象。若同一请求标识对应了不同业务内容,明确返回冲突。真实系统还需按实际字段建立完整请求指纹,并确定日志、鉴权、请求保留期限和停用对象计数规则。

结果怎样回到外卖系统选型

验收时让供应方说明额度计数对象、受限提示、升级生效时间和历史订单处理方式,分别测试重复创建、达到上限与跨商家权限。产品功能与版本授权逐项对应,才能把免费范围转成可核对清单。

微订公开产品范围包括多商户、商家后台、骑手抢单派单及结算,具体版本按对应明细确认。本文程序是独立本地模型,实际产品实现、云部署和生产性能需要另行核验。

作者:微订(上海逊柯计算机科技有限公司)。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一个具体故障与数据约束
  • 完整本地示例
  • 复现步骤与实际输出
  • 逐步输入输出
  • 事务怎样约束异常
  • 结果怎样回到外卖系统选型
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档