2016-05-12 5 views
1

Ich versuche, einen Auslöser für eine Azure DocumentDb-Sammlung zu implementieren, die eine Version eines einzufügenden Dokuments automatisch inkrementieren soll. Der Trigger wird als Pre-Trigger erstellt. Die Herausforderung, der ich gegenüberstehe, ist, dass die Auflistungsklasse keine synchrone API für die Abfrage von Daten zu bieten scheint. Mein Plan für den Auslöser war, vorhandene Dokumente abzufragen, die oberste Version zu erhalten, zu erhöhen und dem Dokument, das in die Sammlung eingefügt wird, den Wert +1 zuzuweisen. Da das Ergebnis der Abfrage jedoch nur asynchron verfügbar ist, ist der Trigger zu diesem Zeitpunkt abgeschlossen und das Dokument wird unverändert eingefügt.
Wie kann ich das Abfrageergebnis abwarten? Hier ist, wie meine aktuellen Trigger wie folgt aussehen:Synchronisiertes Lesen von Daten aus der Azure DocumentDb-Auflistung in einem serverseitigen Auslöser?

// TRIGGER Auto increment version 
    function autoIncrementVersion() { 
     var collection = getContext().getCollection(); 
     var request = getContext().getRequest(); 
     var docToCreate = request.getBody(); 

     // Reject documents that do not have a name property by throwing an exception. 
     if (!docToCreate.Version) { 
     throw new Error('Document must include a "Version" property.'); 
     } 

     var lastVersion; 

     var filter = "SELECT TOP 1 d.Version FROM CovenantsDocuments d ORDER BY d.Version DESC"; 

     var result = collection.queryDocuments(collection.getSelfLink(), filter, {}, 
       function (err, documents, responseOptions) { 
        if (err) throw new Error("Error: " + err.message); 
        if (documents.length != 1 || !documents[0]) { 
         lastVersion = 0; 
        } else { 
lastVersion = documents[0]; 
} 
        //By the time we reach this line, our trigger has already completed? 
        docToCreate.Version = lastVersion + 1; 
       }); 
     if (!result) throw "Unable to read last version of the document"; 

    } 

UPDATE: Das Problem mit der Art und Weise war ich Antrag wurde einreichen. Offensichtlich werden Trigger nicht standardmäßig ausgelöst, ihre Namen müssen explizit als Argument für die Anforderung angegeben werden. In meinem Fall wurde der Trigger nicht ausgelöst, bis ich den Client-Code auf diese geändert:

RequestOptions options = new RequestOptions 
{ 
    PreTriggerInclude = new[] { "autoIncrementVersion"} 
}; 
client.CreateDocumentAsync(url, document, options); 

Antwort

1

automatisch, bis alle anstehenden asynchronen Operationen entweder vollständig wartet Es wird fehlschlagen, oder die Zeit vor der Rückkehr aus. Was du hast, ist nah. Das einzige, was ich sehen kann, ist, dass Sie nie request.setBody(docToCreate) anrufen, nachdem Sie docToCreate ändern.

Das heißt, ich bin nicht 100% sicher, dass dieser Ansatz sicher ist. Alle Operationen innerhalb eines Triggers, Sprocs oder UDFs sind atomar, aber ich bin nicht sicher, ob die Kombination eines Pre-Triggers plus einer Schreiboperation atomar ist. Das Risiko besteht darin, dass zwei simultane Schreibvorgänge ausgeführt werden und den Trigger-Teil vervollständigen, der ihnen die gleiche .Version geben würde. Sie müssen wahrscheinlich die DocumentDB-Produktmanager bitten, dies zu bestätigen. Sie hängen hier rum, damit sie hier antworten können.

Wenn Sie feststellen, dass es nicht atomar ist, können Sie alles (lesen, um die neueste Version zu finden und zu schreiben) in eine gespeicherte Prozedur (sproc) verschieben.

Sie könnten auch in Erwägung ziehen, ein einzelnes Dokument zu erstellen, dessen id Sie hart auf etwas wie 'LAST_VERSION' codieren, um die letzte verwendete Version zu halten. Das bedeutet, dass jeder Schreibvorgang zu einem Lesen + zwei Schreibvorgängen führt (eines für das Dokument und eines zum Aktualisieren dieses Dokuments), aber es kann effizienter sein als Ihr Abfrage + ein Schreibansatz. Sie könnten dies alles in einem Sproc machen oder Sie könnten einen Pre-Trigger verwenden (um die 'LAST_VERSION' + Schreiboperation + Posttrigger zu holen, um das Dokument 'LAST_VERSION' zu aktualisieren), je nachdem was die Produktmanager über Atomizität sagen.

Noch eine Verwarnung zu Ihrem aktuellen Ansatz ... Achten Sie darauf, die Genauigkeit des Index auf dem Feld Version auf -1 gesetzt (Maximale Präzision).

+0

Larry, Vielen dank, Ihre Antwort klingt wie eine Lösung Ich werde versuchen, request.setBody() morgen, dies muss der Grund sein, warum die Version nicht von meinem Auslöser aktualisiert wird. – Volma

+0

Auch wird die Atomizität Aspekt recherchieren. Und wird sicherstellen, dass die Genauigkeit der Version Feld ist richtig. Ein Detail aus Ihre Antwort ist mir jedoch nicht klar - das bisschen über das Werfen von Dokumenten nts.length> 1. Dies ist mein erstes Experiment mit der DocumentDb-Abfragesyntax, also bin ich neugierig, garantiert TOP 1 nicht, dass ich nicht mehr als 1 Datensatz zurückbekomme? Danke noch einmal! – Volma

+0

Sie haben recht, wenn Sie den Wurf nicht mit TOP brauchen. Ich dachte, dass es bestätigen würde, dass keine zwei Dokumente dieselbe Version haben, aber das wird es nicht tun. Ich habe das bearbeitet. –