Azure CosmosDb Stored Procedure IfMatch Predicate











up vote
1
down vote

favorite












In a DocDb stored procedure, as the first step in a process retrieving data that I'm mutating, I read and then use the data iff it matches the etag like so:



collection.readDocument(reqSelf, function(err, doc) {
if (doc._etag == requestEtag) {
// Success - want to update
} else {
// CURRENTLY: Discard the read result I just paid lots of RUs to read
// IDEALLY: check whether response `options` or similar indicates retrieval
was skipped due to doc not being present with that etag anymore
...
// ... Continue with an alternate strategy
}
});


Is there a way to pass an options to the readDocument call such that the callback will be informed "It's changed so we didn't get it, as you requested" ?



(My real problem here is that I can't find any documentation other than the readDocument undocumentation in the js-server docs)










share|improve this question
























  • Wait a second. I started writing up the answer but then I thought, why would you do that? The document that you get from readDocument is always the latest document (ofc based on your consistency level). Even if you pass an access condition and the condition isn't met, you will still get the latest document.
    – Nick Chapsas
    Nov 17 at 23:34










  • You are seeing it the wrong way. What you need to do is to pass the etag on the update call itself, not the read. That's where the access condition will actually be checked and fail if the document's etag doesn't meet the criteria
    – Nick Chapsas
    Nov 17 at 23:35










  • @NickChapsas the advantage of not actually getting the document if it has changed is that the RU charges (and latency due to the data traveling) are avoided - you always pay 1 RU if the etag matches. I get the point of the etag to make the update conditional. In my case, if the etag has changed, then the document has been superseded and I hence need to do a different (more expensive) search (and it's in this case I want to avoid getting data I won't use).
    – Ruben Bartelink
    Nov 18 at 13:44










  • The problem is that because readDocument is not meant to work with an accessCondition, even if you provide one that doesn't match the etag, you will still get the latest version of the document without any errors.
    – Nick Chapsas
    Nov 18 at 14:16










  • I too suspect that is the case - however its a bit ironic that I could do the same pre-flight check from the client side with an If-Match predicate for 1 RU before I invoke the stored proc
    – Ruben Bartelink
    Nov 18 at 15:43

















up vote
1
down vote

favorite












In a DocDb stored procedure, as the first step in a process retrieving data that I'm mutating, I read and then use the data iff it matches the etag like so:



collection.readDocument(reqSelf, function(err, doc) {
if (doc._etag == requestEtag) {
// Success - want to update
} else {
// CURRENTLY: Discard the read result I just paid lots of RUs to read
// IDEALLY: check whether response `options` or similar indicates retrieval
was skipped due to doc not being present with that etag anymore
...
// ... Continue with an alternate strategy
}
});


Is there a way to pass an options to the readDocument call such that the callback will be informed "It's changed so we didn't get it, as you requested" ?



(My real problem here is that I can't find any documentation other than the readDocument undocumentation in the js-server docs)










share|improve this question
























  • Wait a second. I started writing up the answer but then I thought, why would you do that? The document that you get from readDocument is always the latest document (ofc based on your consistency level). Even if you pass an access condition and the condition isn't met, you will still get the latest document.
    – Nick Chapsas
    Nov 17 at 23:34










  • You are seeing it the wrong way. What you need to do is to pass the etag on the update call itself, not the read. That's where the access condition will actually be checked and fail if the document's etag doesn't meet the criteria
    – Nick Chapsas
    Nov 17 at 23:35










  • @NickChapsas the advantage of not actually getting the document if it has changed is that the RU charges (and latency due to the data traveling) are avoided - you always pay 1 RU if the etag matches. I get the point of the etag to make the update conditional. In my case, if the etag has changed, then the document has been superseded and I hence need to do a different (more expensive) search (and it's in this case I want to avoid getting data I won't use).
    – Ruben Bartelink
    Nov 18 at 13:44










  • The problem is that because readDocument is not meant to work with an accessCondition, even if you provide one that doesn't match the etag, you will still get the latest version of the document without any errors.
    – Nick Chapsas
    Nov 18 at 14:16










  • I too suspect that is the case - however its a bit ironic that I could do the same pre-flight check from the client side with an If-Match predicate for 1 RU before I invoke the stored proc
    – Ruben Bartelink
    Nov 18 at 15:43















up vote
1
down vote

favorite









up vote
1
down vote

favorite











In a DocDb stored procedure, as the first step in a process retrieving data that I'm mutating, I read and then use the data iff it matches the etag like so:



collection.readDocument(reqSelf, function(err, doc) {
if (doc._etag == requestEtag) {
// Success - want to update
} else {
// CURRENTLY: Discard the read result I just paid lots of RUs to read
// IDEALLY: check whether response `options` or similar indicates retrieval
was skipped due to doc not being present with that etag anymore
...
// ... Continue with an alternate strategy
}
});


Is there a way to pass an options to the readDocument call such that the callback will be informed "It's changed so we didn't get it, as you requested" ?



(My real problem here is that I can't find any documentation other than the readDocument undocumentation in the js-server docs)










share|improve this question















In a DocDb stored procedure, as the first step in a process retrieving data that I'm mutating, I read and then use the data iff it matches the etag like so:



collection.readDocument(reqSelf, function(err, doc) {
if (doc._etag == requestEtag) {
// Success - want to update
} else {
// CURRENTLY: Discard the read result I just paid lots of RUs to read
// IDEALLY: check whether response `options` or similar indicates retrieval
was skipped due to doc not being present with that etag anymore
...
// ... Continue with an alternate strategy
}
});


Is there a way to pass an options to the readDocument call such that the callback will be informed "It's changed so we didn't get it, as you requested" ?



(My real problem here is that I can't find any documentation other than the readDocument undocumentation in the js-server docs)







javascript azure stored-procedures azure-cosmosdb etag






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 at 21:56

























asked Nov 17 at 21:50









Ruben Bartelink

42.7k17139198




42.7k17139198












  • Wait a second. I started writing up the answer but then I thought, why would you do that? The document that you get from readDocument is always the latest document (ofc based on your consistency level). Even if you pass an access condition and the condition isn't met, you will still get the latest document.
    – Nick Chapsas
    Nov 17 at 23:34










  • You are seeing it the wrong way. What you need to do is to pass the etag on the update call itself, not the read. That's where the access condition will actually be checked and fail if the document's etag doesn't meet the criteria
    – Nick Chapsas
    Nov 17 at 23:35










  • @NickChapsas the advantage of not actually getting the document if it has changed is that the RU charges (and latency due to the data traveling) are avoided - you always pay 1 RU if the etag matches. I get the point of the etag to make the update conditional. In my case, if the etag has changed, then the document has been superseded and I hence need to do a different (more expensive) search (and it's in this case I want to avoid getting data I won't use).
    – Ruben Bartelink
    Nov 18 at 13:44










  • The problem is that because readDocument is not meant to work with an accessCondition, even if you provide one that doesn't match the etag, you will still get the latest version of the document without any errors.
    – Nick Chapsas
    Nov 18 at 14:16










  • I too suspect that is the case - however its a bit ironic that I could do the same pre-flight check from the client side with an If-Match predicate for 1 RU before I invoke the stored proc
    – Ruben Bartelink
    Nov 18 at 15:43




















  • Wait a second. I started writing up the answer but then I thought, why would you do that? The document that you get from readDocument is always the latest document (ofc based on your consistency level). Even if you pass an access condition and the condition isn't met, you will still get the latest document.
    – Nick Chapsas
    Nov 17 at 23:34










  • You are seeing it the wrong way. What you need to do is to pass the etag on the update call itself, not the read. That's where the access condition will actually be checked and fail if the document's etag doesn't meet the criteria
    – Nick Chapsas
    Nov 17 at 23:35










  • @NickChapsas the advantage of not actually getting the document if it has changed is that the RU charges (and latency due to the data traveling) are avoided - you always pay 1 RU if the etag matches. I get the point of the etag to make the update conditional. In my case, if the etag has changed, then the document has been superseded and I hence need to do a different (more expensive) search (and it's in this case I want to avoid getting data I won't use).
    – Ruben Bartelink
    Nov 18 at 13:44










  • The problem is that because readDocument is not meant to work with an accessCondition, even if you provide one that doesn't match the etag, you will still get the latest version of the document without any errors.
    – Nick Chapsas
    Nov 18 at 14:16










  • I too suspect that is the case - however its a bit ironic that I could do the same pre-flight check from the client side with an If-Match predicate for 1 RU before I invoke the stored proc
    – Ruben Bartelink
    Nov 18 at 15:43


















Wait a second. I started writing up the answer but then I thought, why would you do that? The document that you get from readDocument is always the latest document (ofc based on your consistency level). Even if you pass an access condition and the condition isn't met, you will still get the latest document.
– Nick Chapsas
Nov 17 at 23:34




Wait a second. I started writing up the answer but then I thought, why would you do that? The document that you get from readDocument is always the latest document (ofc based on your consistency level). Even if you pass an access condition and the condition isn't met, you will still get the latest document.
– Nick Chapsas
Nov 17 at 23:34












You are seeing it the wrong way. What you need to do is to pass the etag on the update call itself, not the read. That's where the access condition will actually be checked and fail if the document's etag doesn't meet the criteria
– Nick Chapsas
Nov 17 at 23:35




You are seeing it the wrong way. What you need to do is to pass the etag on the update call itself, not the read. That's where the access condition will actually be checked and fail if the document's etag doesn't meet the criteria
– Nick Chapsas
Nov 17 at 23:35












@NickChapsas the advantage of not actually getting the document if it has changed is that the RU charges (and latency due to the data traveling) are avoided - you always pay 1 RU if the etag matches. I get the point of the etag to make the update conditional. In my case, if the etag has changed, then the document has been superseded and I hence need to do a different (more expensive) search (and it's in this case I want to avoid getting data I won't use).
– Ruben Bartelink
Nov 18 at 13:44




@NickChapsas the advantage of not actually getting the document if it has changed is that the RU charges (and latency due to the data traveling) are avoided - you always pay 1 RU if the etag matches. I get the point of the etag to make the update conditional. In my case, if the etag has changed, then the document has been superseded and I hence need to do a different (more expensive) search (and it's in this case I want to avoid getting data I won't use).
– Ruben Bartelink
Nov 18 at 13:44












The problem is that because readDocument is not meant to work with an accessCondition, even if you provide one that doesn't match the etag, you will still get the latest version of the document without any errors.
– Nick Chapsas
Nov 18 at 14:16




The problem is that because readDocument is not meant to work with an accessCondition, even if you provide one that doesn't match the etag, you will still get the latest version of the document without any errors.
– Nick Chapsas
Nov 18 at 14:16












I too suspect that is the case - however its a bit ironic that I could do the same pre-flight check from the client side with an If-Match predicate for 1 RU before I invoke the stored proc
– Ruben Bartelink
Nov 18 at 15:43






I too suspect that is the case - however its a bit ironic that I could do the same pre-flight check from the client side with an If-Match predicate for 1 RU before I invoke the stored proc
– Ruben Bartelink
Nov 18 at 15:43














2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










Technically you can do that by creating a responseOptions object and passing it to the call.



function sample(selfLink, requestEtag) {
var collection = getContext().getCollection();

var responseOptions = { accessCondition: { type: "IfMatch", condition: requestEtag } };

var isAccepted = collection.readDocument(selfLink, responseOptions, function(err, doc, options) {
if(err){
throw new Error('Error thrown. Check the status code for PreconditionFailed errors');
}

var response = getContext().getResponse();
response.setBody(doc);

});

if (!isAccepted) throw new Error('The query was not accepted by the server.');
}


However, even if the etag you provide is not the one that the document has, you won't get an error and you will properly get the document itself back. It's just not supposed to work with that using the readDocument function in a stored procedure.






share|improve this answer




























    up vote
    0
    down vote













    Thanks to some pushing from @Nick Chapsas, and this self-answer from @Redman I worked out that in my case I can achieve my goal (either read the current document via the self-link, or the newer one that has replaced it bearing the same id) by instead generating an Alt link within the stored procedure like so:



    var docId = collection.getAltLink() + "/docs/"+req.id;
    var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
    if (err) throw err;
    // Will be null or not depending on whether it exists
    executeUpsert(doc);
    });
    if (!isAccepted) throw new Error("readDocument not Accepted");





    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














       

      draft saved


      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53355886%2fazure-cosmosdb-stored-procedure-ifmatch-predicate%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      1
      down vote



      accepted










      Technically you can do that by creating a responseOptions object and passing it to the call.



      function sample(selfLink, requestEtag) {
      var collection = getContext().getCollection();

      var responseOptions = { accessCondition: { type: "IfMatch", condition: requestEtag } };

      var isAccepted = collection.readDocument(selfLink, responseOptions, function(err, doc, options) {
      if(err){
      throw new Error('Error thrown. Check the status code for PreconditionFailed errors');
      }

      var response = getContext().getResponse();
      response.setBody(doc);

      });

      if (!isAccepted) throw new Error('The query was not accepted by the server.');
      }


      However, even if the etag you provide is not the one that the document has, you won't get an error and you will properly get the document itself back. It's just not supposed to work with that using the readDocument function in a stored procedure.






      share|improve this answer

























        up vote
        1
        down vote



        accepted










        Technically you can do that by creating a responseOptions object and passing it to the call.



        function sample(selfLink, requestEtag) {
        var collection = getContext().getCollection();

        var responseOptions = { accessCondition: { type: "IfMatch", condition: requestEtag } };

        var isAccepted = collection.readDocument(selfLink, responseOptions, function(err, doc, options) {
        if(err){
        throw new Error('Error thrown. Check the status code for PreconditionFailed errors');
        }

        var response = getContext().getResponse();
        response.setBody(doc);

        });

        if (!isAccepted) throw new Error('The query was not accepted by the server.');
        }


        However, even if the etag you provide is not the one that the document has, you won't get an error and you will properly get the document itself back. It's just not supposed to work with that using the readDocument function in a stored procedure.






        share|improve this answer























          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          Technically you can do that by creating a responseOptions object and passing it to the call.



          function sample(selfLink, requestEtag) {
          var collection = getContext().getCollection();

          var responseOptions = { accessCondition: { type: "IfMatch", condition: requestEtag } };

          var isAccepted = collection.readDocument(selfLink, responseOptions, function(err, doc, options) {
          if(err){
          throw new Error('Error thrown. Check the status code for PreconditionFailed errors');
          }

          var response = getContext().getResponse();
          response.setBody(doc);

          });

          if (!isAccepted) throw new Error('The query was not accepted by the server.');
          }


          However, even if the etag you provide is not the one that the document has, you won't get an error and you will properly get the document itself back. It's just not supposed to work with that using the readDocument function in a stored procedure.






          share|improve this answer












          Technically you can do that by creating a responseOptions object and passing it to the call.



          function sample(selfLink, requestEtag) {
          var collection = getContext().getCollection();

          var responseOptions = { accessCondition: { type: "IfMatch", condition: requestEtag } };

          var isAccepted = collection.readDocument(selfLink, responseOptions, function(err, doc, options) {
          if(err){
          throw new Error('Error thrown. Check the status code for PreconditionFailed errors');
          }

          var response = getContext().getResponse();
          response.setBody(doc);

          });

          if (!isAccepted) throw new Error('The query was not accepted by the server.');
          }


          However, even if the etag you provide is not the one that the document has, you won't get an error and you will properly get the document itself back. It's just not supposed to work with that using the readDocument function in a stored procedure.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 18 at 22:29









          Nick Chapsas

          2,184214




          2,184214
























              up vote
              0
              down vote













              Thanks to some pushing from @Nick Chapsas, and this self-answer from @Redman I worked out that in my case I can achieve my goal (either read the current document via the self-link, or the newer one that has replaced it bearing the same id) by instead generating an Alt link within the stored procedure like so:



              var docId = collection.getAltLink() + "/docs/"+req.id;
              var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
              if (err) throw err;
              // Will be null or not depending on whether it exists
              executeUpsert(doc);
              });
              if (!isAccepted) throw new Error("readDocument not Accepted");





              share|improve this answer

























                up vote
                0
                down vote













                Thanks to some pushing from @Nick Chapsas, and this self-answer from @Redman I worked out that in my case I can achieve my goal (either read the current document via the self-link, or the newer one that has replaced it bearing the same id) by instead generating an Alt link within the stored procedure like so:



                var docId = collection.getAltLink() + "/docs/"+req.id;
                var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
                if (err) throw err;
                // Will be null or not depending on whether it exists
                executeUpsert(doc);
                });
                if (!isAccepted) throw new Error("readDocument not Accepted");





                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  Thanks to some pushing from @Nick Chapsas, and this self-answer from @Redman I worked out that in my case I can achieve my goal (either read the current document via the self-link, or the newer one that has replaced it bearing the same id) by instead generating an Alt link within the stored procedure like so:



                  var docId = collection.getAltLink() + "/docs/"+req.id;
                  var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
                  if (err) throw err;
                  // Will be null or not depending on whether it exists
                  executeUpsert(doc);
                  });
                  if (!isAccepted) throw new Error("readDocument not Accepted");





                  share|improve this answer












                  Thanks to some pushing from @Nick Chapsas, and this self-answer from @Redman I worked out that in my case I can achieve my goal (either read the current document via the self-link, or the newer one that has replaced it bearing the same id) by instead generating an Alt link within the stored procedure like so:



                  var docId = collection.getAltLink() + "/docs/"+req.id;
                  var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
                  if (err) throw err;
                  // Will be null or not depending on whether it exists
                  executeUpsert(doc);
                  });
                  if (!isAccepted) throw new Error("readDocument not Accepted");






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 18 at 22:20









                  Ruben Bartelink

                  42.7k17139198




                  42.7k17139198






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53355886%2fazure-cosmosdb-stored-procedure-ifmatch-predicate%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                      Alcedinidae

                      Can an atomic nucleus contain both particles and antiparticles? [duplicate]