現在Azure Storageを使用して画像を格納するPython Tornado Webアプリケーションと、画像にメタデータを格納するDocumentDBを構築しています。画像がアップロードされるたびに、Tornado Web Appを実行している2つの可能なDockerコンテナのうち1つを使用して、POSTメソッドを非同期に実行できます。私が持っているエラーは、私がDocumentDBスクリプトに座っているストアドプロシージャに到達したときです。 sprocは、同時に2つの別々のDockerコンテナで2つのスレッドで実行されています。ストアドプロシージャは、次のようになりgen_receipt_id
文書のDOCDBを照会することによってアップロード各画像のための新しいReceiptIDを生成することを意味する:複数のDockerコンテナでDocumentDBストアドプロシージャを実行中に同時実行エラーが発生する
{
"id": "gen_receipt_id",
"counter": 406
}
をSPROC次いで1 counter
プロパティをインクリメントし、その新たなIDをするために使用されメタデータの新しい領収書に添付されます。 SPROCは次のようになります。
function receiptIDSproc() {
var collection = getContext().getCollection();
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
"SELECT * FROM root r WHERE r.id='gen_receipt_id'",
function(err, feed) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!feed || !feed.length) getContext().getResponse().setBody('no docs found');
else {
tryUpdate(feed[0]);
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
function tryUpdate(document) {
var requestOptions = {"If-Match": document._etag,
etag: document._etag};
document.counter += 1;
// Update the document.
var isAccepted = collection.replaceDocument(document._self, document, requestOptions, function (err, updatedDocument,responseOptions) {
if (err) throw err;
// If we have successfully updated the document - return it in the response body.
getContext().getResponse().setBody(updatedDocument);
});
// If we hit execution bounds - throw an exception.
if (!isAccepted) {
throw new Error("The stored procedure timed out.");
}
}
}
をしかし、私は同時に複数の画像をアップロードするために行くとき、私は操作が非同期で起こっとの競合を取得: Fine-Uploader upload conflict
コンソールでのエラーは、次のようになります
[36mtornado2_1 |[0m ERROR:500 POST /v1.0/groups/1/receipts (172.18.0.4) 1684.98ms
[33mtornado1_1 |[0m 407 //Here I'm printing the ID the Sproc generated
[33mtornado1_1 |[0m 2016/9/13/000000000000407
[36mtornado2_1 |[0m 407 //Here I'm printing the ID the Sproc generated
[36mtornado2_1 |[0m 2016/9/13/000000000000407
[32mnginx_1 |[0m 10.0.75.1 - - [13/Sep/2016:16:49:47 +0000] "POST /v1.0/groups/1/receipts HTTP/1.1" 200 17 "http://local.zenxpense.com/upload" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
[33mtornado1_1 |[0m INFO:200 POST /v1.0/groups/1/receipts (172.18.0.4) 1132.49ms
[36mtornado2_1 |[0m WARNING:500 POST /v1.0/groups/1/receipts (172.18.0.4): An error occured while uploading to Azure Storage: HTTP 500: Internal Server Error (An error occured while creating DocumentDB record: Status code: 409
[36mtornado2_1 |[0m {"code":"Conflict","message":"Message: {\"Errors\":[\"Resource with specified id or name already exists\"]}\r\nActivityId: b226be91-f193-4c1b-9cc2-bcd8293bd36b, Request URI: /apps/8ae2ad5a-d261-42ac-aaa1-9ec0fd662d12/services/cc7fdf37-5f62-41db-a9d6-37626da67815/partitions/8063ad6c-33ad-4148-a60f-91c3acbfae6f/replicas/131171655602617741p"})
エラーからわかるように、Sprocは2つの異なるDockerコンテナ407
で同じReceiptIDを実行して生成しています。そのため、競合エラーsincがありますe同じIDを持つ2つのドキュメントを作成しようとしています。私が起こる必要があるのは、Sprocが2つの別々の容器に同じIDを生成するのを防ぐことです。私はEtagsとSprocの "If-Match"ヘッダーを使用してみましたが、各コンテナは文書上に同じEtagを持っているので、エラーは表示されません。
お返事ありがとうございます。しかし、問題は、Sproc自身が必ずしもIDを生成したり、返すことさえしないということです。単にドキュメントに行き、1だけインクリメントします。そして、私のサーバーサイドのPythonはそのドキュメントに現在の 'counter'が何であるかを尋ねます。これが私の新しいIDです。このIDを持つDocDB文書を作成しようとするとエラーが発生します。このIDは、BLOBをAzure Storageにアップロードした後にのみ発生します。つまり、サーバ側のアップロード操作全体をやり直す必要があります。むしろ、Sprocが実行されるたびに常に新しいIDに増分されるようにしたいと思います。 –
IDが逐次である必要がありますか?そうでない場合は、なぜGUIDを使用しないのですか? –
私たちは意図的に独自のIDジェネレータを使用しています。なぜなら、GUIDは常にユニークで、乱雑で順序が乱れているからです。 'eceaeb07-3247-4e79-8999-7b2d83b4ca02'は' 15'に比べてユーザーを追跡するきれいな方法ではありません。 –