Skip to content

MSMQ transaction management

Provides StartMQTransaction and EndMQTransaction so a caller can batch multiple Distribute a document calls into a single transactional unit of work against the MSMQ transactional queue, rather than committing a transaction per message.

Field Value
Operation ID OP-05
Trigger StartMQTransaction / EndMQTransaction invoked directly by a caller
Inputs None (StartMQTransaction); inAction As Boolean commit/abort flag (EndMQTransaction)
Outputs A committed or aborted MessageQueueTransaction
Primary components clsPrint.StartMQTransaction, clsPrint.EndMQTransaction
Entry point SAIF.Services.Printing/clsPrint.vb

Steps

  1. StartMQTransaction: if a transaction is not already started (m_TxnStarted = False), creates a new MessageQueueTransaction, begins it, and sets m_TxnStarted = True.
  2. If a transaction is already started, this call is a no-op — calling it twice in a row silently keeps the first transaction rather than starting a second one or raising an error. This idempotent-restart behavior underlies the "if the caller did not start one" framing in BR-PRT-004.
  3. EndMQTransaction(inAction): if m_TxnStarted is True, commits the transaction when inAction = True, or aborts it when inAction = False.
  4. On any exception during commit or abort, the Finally block described in step 3 still executes.
  5. Finally (always runs): resets m_TxnStarted = False and disposes/nulls m_Txn, regardless of whether a transaction was actually started or whether the commit/abort succeeded.
  6. If EndMQTransaction is called when m_TxnStarted = False, the commit/abort branch in step 2 is skipped entirely, but this Finally cleanup still runs harmlessly.

Process flow

flowchart TD
    subgraph Start_flow["StartMQTransaction"]
        S1(["StartMQTransaction called"]) --> S2{"m_TxnStarted?"}
        S2 -->|No| S3["New MessageQueueTransaction,<br>Begin, set flag True"]
        S2 -->|Yes| S4(["No-op"])
    end
    subgraph End_flow["EndMQTransaction(inAction)"]
        E1(["EndMQTransaction called"]) --> E2{"m_TxnStarted?"}
        E2 -->|Yes| E3{"inAction?"}
        E3 -->|True| E4["Commit"]
        E3 -->|False| E5["Abort"]
        E4 --> E6["Finally: reset flag,<br>dispose/null txn"]
        E5 --> E6
        E2 -->|No| E6
    end

Failure and edge-case behavior

  • There is no exception handling around Commit()/Abort() beyond the Finally cleanup — an exception raised from Commit() propagates to the caller after the Finally block has already reset state.
  • Calling StartMQTransaction twice without an intervening EndMQTransaction silently reuses the existing transaction rather than erroring or starting a second one.
  • Distribute a document relies on this same start/commit/rollback mechanic internally when the caller has not started a transaction of their own, per BR-PRT-004 and BR-PRT-005.

Sources

  • SAIF.Services.Printing/clsPrint.vb