我正在运行一系列单元测试(node.js 4.x,aws-sdk,mocha),在每次测试之前将数据加载到表中,然后在测试后清除表。
我有两个失败的测试,因为ConditionExpression
会触发ConditionCheckFailedException
。但如果我增加读/写容量,他们就会通过测试。
我的理解是SDK处理限制异常并为您重试它们,为什么我的测试不会运行得更慢并且通过?相反,似乎测试无法完成scan
- > batchWriteItem
进程,因此当新测试开始时,表中仍有记录。
我被团队成员告知他们已经看到类似的问题,他们只是增加了解决问题的吞吐量。这不适合我。要么我做错了,我的测试有竞争条件,或者我应该有一个模式可以确保我的操作在受到限制时完成?我应该能够使用限制指标来告知何时需要增加吞吐量,但是我仍然可以继续重试,直到内存不足为止。
是否还有其他人遇到过此问题以及您采取了哪些措施来处理此问题?
答案 0 :(得分:1)
经过一些调试后,我注意到了UnprocessedItems
响应元素。在查找UnprocessedItems
in the docs之后,我意识到我应该更仔细地阅读。下面的代码将运行一个带延迟的重试循环(指数退避):
var clearEventTable = function (tableName, client, cleared) {
var exclusiveStartKey = null;
var retryCount = 0;
var read = function(query, callback) {
client.scan(query, function (err, page) {
if(err) {
console.log(err);
return callback(err);
}
retryCount = 0;
exclusiveStartKey = page.LastEvaluatedKey || null;
if(page.Count == 0) {
return callback(null, {});
}
if(page.Count < 25 && exclusiveStartKey) {
console.log("read capacity limit reached: " + JSON.stringify(page, null, 2));
}
var keys = _.map(page.Items, function(n) {
return { DeleteRequest: { Key: n } };
});
var batch = {
RequestItems: {},
ReturnConsumedCapacity: "INDEXES",
ReturnItemCollectionMetrics: "SIZE"
};
batch.RequestItems[tableName] = keys;
callback(null, batch);
});
};
var write = function(batch, callback) {
if(batch && batch.RequestItems){
client.batchWriteItem(batch, function(err, result) {
if(err) {
console.log(err);
return callback(err);
}
if(Object.keys(result.UnprocessedItems).length !== 0) {
console.log("Retry batchWriteItem: " + JSON.stringify(result, null, 2));
retryCount++;
var retry = {
RequestItems: result.UnprocessedItems,
ReturnConsumedCapacity: "INDEXES",
ReturnItemCollectionMetrics: "SIZE"
};
// retry with exponential backoff
var delay = retryCount > 0 ? (50 * Math.pow(2, retryCount - 1)) : 0;
setTimeout(write(retry, callback), delay);
return;
}
callback(null, result);
});
} else {
callback(null);
}
};
var params = {
TableName: tableName,
ProjectionExpression: "aggregateId,id",
Limit: 25, // max 25 per batchWriteItem
ConsistentRead: false,
ReturnConsumedCapacity: "TOTAL"
};
async.doWhilst(function (next) {
// retrieve entities
if (exclusiveStartKey)
params.ExclusiveStartKey = exclusiveStartKey;
async.compose(write, read)(params, function (err, result) {
if (err) next(err);
else next(null, result);
});
}, function () {
// test if we need to load more
return exclusiveStartKey !== null;
}, function (err, r) {
// return results
if (err) {
console.log(err);
return cleared(err);
}
return cleared(null);;
});
};
答案 1 :(得分:0)
还要查看为Lambda设置的内存量。可能太低了,达到最大值会导致IMX无法预测的结果。