CosmosDB存储过程:Etag不匹配时抛出异常的实现方案
修改后的存储过程及实现说明
核心修改点
- 区分创建新文档与Etag匹配更新两种场景:
- 若传入文档不含指定Etag标识字段(示例中用
matchEtag),执行创建操作 - 若含Etag字段,执行带Etag校验的更新操作,校验失败时抛出明确可捕获的异常
- 若传入文档不含指定Etag标识字段(示例中用
- 用
replaceDocument替代原upsertDocument处理更新逻辑,通过accessCondition设置Etag匹配规则 - 针对Etag不匹配的412状态码,抛出自定义异常信息,方便Java代码识别处理
修改后的完整代码
function createEvent(items) { var collection = getContext().getCollection(); var collectionLink = collection.getSelfLink(); var count = 0; if (!items) throw new Error("The array is undefined or null."); var numItems = items.length; if (numItems === 0) { getContext().getResponse().setBody(0); return; } tryProcess(items[count], callback); function tryProcess(item, callback) { var options = { disableAutomaticIdGeneration: false }; // 根据是否携带matchEtag判断操作类型 if (item.matchEtag) { // 更新场景:设置Etag匹配条件 options.accessCondition = { type: "IfMatch", condition: item.matchEtag }; // 移除临时Etag字段,避免写入文档 delete item.matchEtag; // 执行带Etag校验的替换操作 var isAccepted = collection.replaceDocument(collectionLink, item, options, callback); } else { // 创建场景:执行新增操作(文档已存在则报错) var isAccepted = collection.createDocument(collectionLink, item, options, callback); } if (!isAccepted) getContext().getResponse().setBody(count); } function callback(err, item, options) { if (err) { // 捕获Etag不匹配的412错误,抛出明确异常 if (err.code === 412) { throw new Error("Etag mismatch: Target document has been modified by other process."); } throw err; } count++; if (count >= numItems) { getContext().getResponse().setBody(count); } else { tryProcess(items[count], callback); } } }
使用注意事项
- 参数约定:
- 创建文档:无需携带
matchEtag字段 - 更新文档:必须携带
matchEtag字段,值为目标文档当前的Etag值
- 创建文档:无需携带
- Java端处理:调用存储过程时,捕获到包含
Etag mismatch的异常即可判定为Etag不匹配场景 - 扩展说明:如果需要创建时允许覆盖已存在文档,可将创建场景的
createDocument改回upsertDocument,但保留更新场景的Etag校验逻辑
内容的提问来源于stack exchange,提问作者Loren
相关产品推荐
相关产品推荐

