2012年7月13日星期五

How to resolve to Number sequnec lock

While working in multi user environment, if you are creating journal/journal line through code then you might the have the number sequence locking problem. For understanding the problem you can use following code.
X++ code with posting jounral
----------------------------------------------------------
static void  checkNumberSeq(Args _args)
{
     NumberSeq  numberSeq;
     Voucher  releaseVoucher;
      ;

      ttsbegin;

     numberSeq  =  NumberSeq::newGetVoucher(VendParameters::numRefVendPaymentVoucher());
      releaseVoucher = numberSeq.voucher();
      NumberSeq::release(VendParameters::numRefVendPaymentVoucher().NumberSequence,releaseVoucher);

      //ttscommit;
      //ttsbegin;
     numberSeq  =  NumberSeq::newGetVoucher(VendParameters::numRefVendPaymentVoucher());
      releaseVoucher = numberSeq.voucher();

      ttscommit;
}
---------------------------------------------------------
If you uncomment ttscommit/ttsbegin in the middle of this job first, it will work fine. If you comment them and run the job again, one NumberSequenceTable record gets locked, and the system hangs during second newGetVoucher() call.

This happens because standard Ax use pessimistic lock while generating new number.
To resolve this problem either you have to use newGetVoucher() out of ttsbegin/ttscommit scope.
Another way to resolve it (not thoroughly tested) is to modify method \Classes\NumberSeq\release as follows:
x++ code
-----------------------------------------------------------------------------------------------
public static  boolean release(NumberSequenceCode  _numberSequenceCode,
                         Num                 _num
                         //#N, 1001 10/01/2008- -->                          ,userConnection     userConnection = null
                         //#N, 1001 10/01/2008-       //numberSequenceTable = NumberSequenceTable::find(_numberSequenceCode,true);
     if  (prmIsDefault(userConnection))
      {
          userConnection = New userConnection();
      }

      userConnection.ttsbegin();
      numberSequenceTable.setConnection(userConnection);
      numberSequenceList.setConnection(userConnection);

     select  forUpdate firstOnly numberSequenceTable
         index  hint SeriesIdx
         where  numberSequenceTable.numberSequence == _numberSequenceCode;
     //#N, 1001 10/01/2008-           userConnection.ttsabort();
         //#N, 1001 10/01/2008- >--          throw  error(strFmt("@SYS26271",_numberSequenceCode));
      }

     if  (!numberSequenceTable.checkBlocked())
      {
         //#N, 1001 10/01/2008- -->           userConnection.ttsabort();
         //#N, 1001 10/01/2008- >--          throw  error("@SYS18447");
      }

     if  (numberSequenceTable.continuous == NoYes::No)
         ok =  TRUE;
      else
      {
          select forupdate firstonly numberSequenceList
              index hint StatIdx
              where numberSequenceList.numberSequence == _numberSequenceCode  &&
                    numberSequenceList.num            == _num;

         if  (numberSequenceList)
          {
              if (numberSequenceList.status == NumStatus::Free)
              {
                  ok = TRUE;
              }
              else if (numberSequenceList.status == NumStatus::Active || numberSequenceList.status == NumStatus::Reserved) { if (numberSequenceList.transId)
                  {
                      numberSequenceList.status   = NumStatus::Free;
                      numberSequenceList.transId  = 0;
                      numberSequenceList.update();

                      select forupdate firstonly numberSequenceTTS
                          index hint TransIdIdx
                          where numberSequenceTTS.transId ==  numberSequenceList.transId;

                      if (numberSequenceTTS)
                          numberSequenceTTS.delete();

                      ok = TRUE;
                  }
                  else
                  {
                      xSession = new xSession(sessionId());

                      if (numberSequenceList.sessionId        == xSession.masterSessionId() ?  xSession.masterSessionId() : sessionId() &&
                          numberSequenceList.sessionLoginDate == xSession.loginDate()     &&
                          numberSequenceList.sessionLoginTime ==  xSession.loginTime())
                      {
                          numberSequenceList.status   = NumStatus::Free;
                          numberSequenceList.update();
                          ok = TRUE;
                      }
                      else
                      {
                          if (NumberSeqCleanUp::isProcessDead(numberSequenceList))
                          {
                              numberSequenceList.status   =  NumStatus::Free;
                              numberSequenceList.update();
                              ok = TRUE;
                          }
                          else
                          {
                              ok = FALSE;
                          }

                      }
                  }
              }
          }
          else
          {
              numberSequenceList.numberSequence    =  _numberSequenceCode;
              numberSequenceList.transId           = 0;
              numberSequenceList.status            = NumStatus::Free;
              numberSequenceList.num               = _num;
              numberSequenceList.insert();
              ok = TRUE;
          }
      }

     //#N, 1001 10/01/2008- -->       userConnection.ttscommit();
     //#N, 1001 10/01/2008- >--       ttscommit;

     return  ok;
}
-------------------------------------------------------------------------------------------

没有评论:

发表评论