In stored procedures or triggers, all the Error that the script throws will be transported back and translated into client side exceptions, with stack trace. So one way to debug the script is by using throw new Error(...) as a breakpoint in the script, stepping through the script and throwing at different points to validate that the code behaves as expected.
Assuming you are using partitioned collection. The triggers, just like stored procedures, are scoped in a single partition (https://azure.microsoft.com/en-us/documentation/articles/documentdb-programming/#database-program-transactions). Therefore, what the triggers can access and update must be within that partition where the triggers are running.
In your example, without the change of your trigger script, you will need to pre-create one metadata document for each partition key value. Then, to get the final statistics of the collection, you will need to query all the metadata documents (there will be more than one) and do your final aggregation across these metadata documents on the client side.
Another option is to auto-create the metadata document inside the trigger. This will avoid creating more than necessary metadata documents since you only need one metadata document per partition. Here is the my modification of your original script that does the creation:
/**
* This script runs as a trigger:
* for each inserted document, look at document.size and update aggregate properties of metadata document: minSize, maxSize, totalSize.
*/
function updateMetadata() {
// HTTP error codes sent to our callback funciton by DocDB server.
var ErrorCode = {
RETRY_WITH: 449,
}
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
// Get the document from request (the script runs as trigger, thus the input comes in request).
var doc = getContext().getRequest().getBody();
// Check the doc (ignore docs with invalid/zero size and metaDoc itself) and call updateMetadata.
if (!doc.isMetadata && doc.size != undefined && doc.size > 0) {
getAndUpdateMetadata();
}
function getAndUpdateMetadata() {
// Get the meta document. We keep it in the same collection. it's the only doc that has .isMetadata = true.
var isAccepted = collection.queryDocuments(collectionLink, 'SELECT * FROM TestColl r WHERE r.isMetadata = true', function (err, feed, options) {
if (err) throw err;
var metaDoc;
if (!feed || !feed.length) {
// Create the meta doc for this partition, using the partition key value from the request document
metaDoc = {
"id": "metadata",
"isMetadata": true,
"minSize": 0,
"maxSize": 0,
"totalSize": 0,
}
metaDoc.partitionKey = doc.partitionKey;
}
else {
// Found the metadata document for this partition. So just use it
metaDoc = feed[0];
}
// Update metaDoc.minSize:
// for 1st document use doc.Size, for all the rest see if it's less than last min.
if (metaDoc.minSize == 0) metaDoc.minSize = doc.size;
else metaDoc.minSize = Math.min(metaDoc.minSize, doc.size);
// Update metaDoc.maxSize.
metaDoc.maxSize = Math.max(metaDoc.maxSize, doc.size);
// Update metaDoc.totalSize.
metaDoc.totalSize += doc.size;
// Update/replace the metadata document in the store.
var isAccepted;
if (!feed || !feed.length) {
// Create the metadata document if it doesn't exist
isAccepted = collection.createDocument(collectionLink, metaDoc, function (err) {
if (err) throw err;
// Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again
// and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).
// We have to take care of that on the client side.
});
}
else {
// Replace the metadata document
isAccepted = collection.replaceDocument(metaDoc._self, metaDoc, function (err) {
if (err) throw err;
// Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again
// and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).
// We have to take care of that on the client side.
});
}
if (!isAccepted) throw new Error("The call replaceDocument(metaDoc) returned false.");
});
if (!isAccepted) throw new Error("The call queryDocuments for metaDoc returned false.");
}
}
Hope this helps. Feel free to post back if you have further questions.
Thanks.
Lengning