我有一个插入或更新的DocumentDB存储过程(不替换,而是读取和更新现有文档)。存储过程最多执行两个操作:
该文件也不是特别大。但是,我会不时地(由有界执行引起)或449(冲突更新资源,这是一个瞬态错误)。
IMO这不是一个特别重要的存储过程,但似乎我已经遇到了限制。我可以在客户端做更多工作,但我喜欢存储过程中的ACID保证。
有限执行是否有任何量化指标?我想知道我是在做错事还是确实达到了DocumentDB的限制。
我的存储过程是修改后的https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/update.js,它接收文档而不是id。我特别使用“$ addToSet”,代码看起来像
function unique(arr) {
var uniqueArr = [], map = {};
for (var i = 0; i < arr.length; i++) {
var exists = map[arr[i]];
if (!exists) {
uniqueArr.push(arr[i]);
map[arr[i]] = true;
}
}
return uniqueArr;
}
// The $addToSet operator adds elements to an array only if they do not already exist in the set.
function addToSet(document, update) {
var fields, i;
if (update.$addToSet) {
console.log(">addToSet");
fields = Object.keys(update.$addToSet);
for (i = 0; i < fields.length; i++) {
if (!Array.isArray(document[fields[i]])) {
// Validate the document field; throw an exception if it is not an array.
throw new Error("Bad $addToSet parameter - field in document must be an array.");
}
// convert to array if input is not an array
var newIds = Array.isArray(update.$addToSet[fields[i]])
? update.$addToSet[fields[i]]
: [update.$addToSet[fields[i]]];
var finalIds = unique(document[fields[i]].concat(newIds));
document[fields[i]] = finalIds;
}
}
}
答案 0 :(得分:2)
DocumentDB存储过程必须在5秒内完成。它们也受到集合的预配置吞吐量的限制。如果您配置了5000 RU / s,则存储过程总共不会消耗超过5000 * 5 RU。
当存储过程达到其执行时间或其吞吐量限制时,执行数据库操作(读取,写入,查询)的任何请求都将收到抢占信号,即该请求将不会被接受为该信号。存储过程包装执行,并返回给调用者。如果您检查每次调用的返回代码,您的存储过程将永远不会超时。这是一个显示如何执行此操作的代码段(https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/处提供完整示例):
var isAccepted = collection.replaceDocument(...) {
// additional logic in callback
});
if (!isAccepted) {
// wrap up execution and return
}
关于449
,这是一个并发错误,如果存储过程尝试执行冲突写入,则可以返回该错误。这是免费的副作用,可以安全地从客户端重试。每当遇到此错误时,您都可以实施重试,直到成功模式。