Uploaded image for project: 'Node.js Driver'
  1. Node.js Driver
  2. NODE-2145

Queuing transactions to avoid 'Transaction already in progress’ errors?

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Gone away
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: core
    • Labels:
      None
    • MongoDB Version:
      4.0.10, 4.0.7, 4.0.9

      Description

      I will be happy to open a pull request with the code changes, but first I wanted to know if this was a valid approach.

      Currently, if one transaction is in progress, starting another transaction will throw a "Transaction already in progress"{{}} error. For users, a solution might be polling or implementing their own queuing system.

      For an out of the box solution, however, I suggest that instead of the current syntax:

      const session = client.startSession(); session.startTransaction(); 
      //multi-document operations here... 
      session.commitTransaction();

      the following is used:

      const session = client.startSession();
      await session.startTransaction(async (abort) => { 
          
          // multi-document operations here… 
          
          /*  transaction is automatically commited  at the end of the code,
              unless an `abort()` statement is used.  */
       
      });
       

       

      With the 32 lines of code library I wrote called mutually-exclusive-functions, one can queue session.startTransaction calls as they come and execute them one at a time:

      [startTransaction] = exclude([startTransaction]); // (this is done internally, not by the user)

       And startTransaction would have to be rewritten to something like this:

      async startTransaction(multi_document_ops) { 
       
          // previously needed internal code and setup goes here... 
       
          let aborted = false; 
          let abort = () => { 
              aborted = true; 
              abortTransaction();
          } 
       
          await multi_document_ops(abort); 
          if (!aborted) return commitTransaction(); 
      }
       

      startTransaction calls now are mutually exclusive in that only one executes at a time, and subsequent calls wait for previous ones to finish.

      This is an out of the box solution where users won’t need to worry about checking if a transaction is already in progress before trying another one. Also, as a bonus, now the user need not remember to commit the transaction, since it is automatically done for them.

      However, I can’t say whether changing the current “flat” pattern to a callback one for the transaction operations would make some situations impossible or more cumborsome to handle — it could be the other way around too. Also, other drivers seem to follow this flat pattern, and therefor changing the pattern here would make this driver stand out — It’s not up to me to decide if this is good or bad.

        Attachments

          Activity

            People

            Assignee:
            daniel.aprahamian Daniel Aprahamian (Inactive)
            Reporter:
            rashad.saleh@gmail.com Rashad Saleh
            Participants:
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: