Проблема блокировки при вызове BAPI_PRODORDCONF_CREATE_HDR

Автор tanyxa, Вересень 04, 2018, 10:33:20 ДП

Попередня тема - Наступна тема

0 Користувачі і 1 Гість дивляться цю тему.

tanyxa

Всем доброго времени суток!
Уважаемые эксперты, помогите разобраться с поведением программы. Имеется некий многопозиционный Z документ (каждая позиция содержит отпускающую и принимающую партию, № произв. заказа, значения признаков партии и т.д. ), нужно в цикле пройтись по всем позициям и:

а) обновить классификацию партии указаной в позиции
б) создать подтверждение для произв. заказа. (в данном случае для 2 позиций один и тот же № заказа)

Если все это было успешно сделано - сохранить сам Z документ, иначе вывалить окошко c возникшими ошибками.

Кусок кода:


LOOP AT mt_pcaitm ASSIGNING FIELD-SYMBOL(<fs_item>).
  "Проверка блокировки партии
  DO 300 TIMES.
      CALL FUNCTION 'ENQUEUE_EMMCH1E'
        EXPORTING
          mode_mch1      = 'V'
          matnr          = <fs_item>-mantr
          charg          = <fs_item>-charg
        EXCEPTIONS
          foreign_lock   = 1
          system_failure = 2
          OTHERS         = 3.
      IF sy-subrc = 0.
        EXIT.
      ELSE.
        WAIT UP TO 1 SECONDS.
      ENDIF.
    ENDDO.
   
    SET UPDATE TASK LOCAL.
   ".... Читаем классификацию, присваиваем значения признаков и т.д.
   
    "Обновляем
    CALL FUNCTION 'BAPI_OBJCL_CHANGE'
      EXPORTING
        objectkey          = l_objectkey
        objecttable        = l_objecttable
        classnum           = l_classnum
        classtype          = l_classtype
      TABLES
        allocvaluesnumnew  = lt_allocvaluesnum
        allocvaluescharnew = lt_allocvalueschar
        allocvaluescurrnew = lt_allocvaluescurr
        return             = lt_ret.
       
       IF bapiret_has_errors( lt_ret ) IS NOT INITIAL.
          ycx_static=>raise_bapiret2( it_ret = lt_ret ).
      ENDIF.

      "Далее работаем с заказом
     
      CALL FUNCTION 'Z_CREATE_HDR'
        EXPORTING
          i_aunfr     = <fs_item>-manuf_aufnr
          i_date      = get_pstng_date( ms_pca )
          i_lmnga     = l_lmnga
          i_tplnr     = <fs_item>-tplnr
          i_schgrup   = get_brig_line( <fs_item>-brig_l )-schgrup
          i_kaptprog  = get_brig_line( <fs_item>-brig_l )-kaptprog
          i_batch_in  = <fs_item>-charg_pp
          i_lgort_in  = ms_pca-lgort
          i_batch_out = <fs_item>-charg
          i_lgort_out = ms_pca-lgort
          i_commit   = ' '
          i_testrun   =  '  '
        IMPORTING
          et_return   = lt_return1.

      LOOP AT lt_return1 TRANSPORTING NO FIELDS WHERE type CA 'EAX'.
        EXIT.
      ENDLOOP.

      IF sy-subrc = 0.
        CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
        MESSAGE e076 WITH  |{ <fs_item>-confir }/{ <fs_item>-confco }|  INTO dummy.
        ycx_static=>raise_sy( ).
      ENDIF.

       zcl_doc_stc=>change(
      EXPORTING
        i_send_int  = 'X'
        i_no_commit = 'X'
        is_header   =  ms_header
        it_item     =  mt_pcaitm ).

      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
        EXPORTING
          wait = 'X'.

      DO 300 TIMES.
        CALL FUNCTION 'ENQUEUE_ESORDER'
          EXPORTING
            mode_aufk      = 'V'
            aufnr          = <fs_item>-manuf_aufnr
          EXCEPTIONS
            foreign_lock   = 1
            system_failure = 2
            OTHERS         = 3.

        IF sy-subrc = 0.
          EXIT.
        ELSE.
          WAIT UP TO 1 SECONDS.
        ENDIF.
      ENDDO.

        SELECT SINGLE rsnum FROM rkpf INTO @DATA(l_rsnum)
        WHERE aufnr = @<fs_item>-manuf_aufnr.

      IF sy-subrc = 0.
        DO 300 TIMES.
          CALL FUNCTION 'ENQUEUE_EMRKPF'
            EXPORTING
              mode_rkpf      = 'V'
              rsnum          = l_rsnum
            EXCEPTIONS
              foreign_lock   = 1
              system_failure = 2
              OTHERS         = 3.

          IF sy-subrc = 0.
            EXIT.
          ELSE.
            WAIT UP TO 1 SECONDS.
          ENDIF.
        ENDDO.
      ENDIF.

ENDLOOP.



Внутри FM Z_CREATE_HDR следующий код (сам FM обычный - не RFC и не модуль обновления) :


SET UPDATE TASK LOCAL.

  "....Промежуточные разные вычисления, специфичные для позиции Z документа

CALL FUNCTION 'BAPI_PRODORDCONF_CREATE_HDR'
    EXPORTING
      testrun            = i_testrun
    IMPORTING
      return             = ls_return
    TABLES
      detail_return            = lt_detailreturn
      athdrlevels               = lt_athdrlevels
      goodsmovements     = lt_goodsmovements
      link_conf_goodsmov = lt_link_conf_goodsmov.

  LOOP AT et_return TRANSPORTING NO FIELDS WHERE type CA 'EAX'.
    EXIT.
  ENDLOOP.

  IF sy-subrc NE 0.
    IF i_commit EQ abap_true.
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
        EXPORTING
          wait = 'X'.
    ENDIF.
  ELSE.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  ENDIF.




Странность поведения в том, что на второй итерации LOOP вылетает ошибка блокировки заказа ( объект ESORDER ) , хотя цикл проверки рассчитан аж на 5 минут, по времени выполнения видно что блокировки снимаются гораздо быстрее. Почему так может быть и как правильно дождаться окончания работы BAPI_PRODORDCONF_CREATE_HDR?

Uukrul

А зачем вы сами блокировки выставляете? BAPI-сама вызовет блокировку и сама ее снимет. Попробуйте убрать собственные блокировки, а оставить только проверку на блокирование.

tanyxa

Так я собственную блокировку и не устанавливаю,   CALL FUNCTION 'ENQUEUE_ESORDER' EXPORTING mode_aufk = 'V' это же собственно и есть проверка (физически блокировка не устанавливается при этом) . Т.е. если получилось проэмулировать блокирование заказа - то можно переходить к следующей итерации. 

Uukrul

Цитата: tanyxa від Вересень 04, 2018, 12:00:03 ПП
Так я собственную блокировку и не устанавливаю,   CALL FUNCTION 'ENQUEUE_ESORDER' EXPORTING mode_aufk = 'V' это же собственно и есть проверка
Да не обратил внимание на параметр V. ну в общем проверку сделайте так:

CALL FUNCTION 'ENQUEUE_EMMCH1E'
        EXPORTING
          mode_mch1      = 'V'
          matnr          = <fs_item>-mantr
          charg          = <fs_item>-charg
         _wait = abap_true
        EXCEPTIONS
          foreign_lock   = 1
          system_failure = 2
          OTHERS         = 3.

И уберите цикл, оно с параметром _wait, теоретически само будет выжидать где-то до 5 секунд (зависти от настройки профиля системы) пока не получится поставить блокировку, после чего пойдет дальше.

tanyxa

Uukrul, спасибо за подсказку, но будет ли установка параметра _wait существенно отличаться от варианта с циклом?

Суть проблемы в том что проверка на блокировку отрабатывает и отрабатывает быстро, я вижу что прога не задумывается на 5 минут. Мне неважно сколько времени займет ожидание (ну в разумных пределах конечно), главное чтобы подтверждение заказа для позиции Z документа завершилось.

Но фактически получается похоже процесс обновления еще работает. Я оставила в цикле только  BAPI_PRODORDCONF_CREATE_HDR и проверку ESORDER, но на второй итерации периодически вылетаю с ошибкой блокировки заказа (т.е. этого самого ESORDER)

Uukrul

Цитата: tanyxa від Вересень 04, 2018, 08:09:15 ПП
Uukrul, спасибо за подсказку, но будет ли установка параметра _wait существенно отличаться от варианта с циклом?
Ну теоретически будет и будет более правильно. Как минимум по скорости работы это 100% Далее это все уже получается управляемым, а не прибитым гвоздями в коде программы.

Uukrul

Кстати, если это не поможет, другой вариант идти и говорить с базисом, если блокировка медленно снимается, вполне возможно, что есть какие-то проблемы в настройке таблицы блокировок. Была у меня ситуация когда таблица была очень большой и при определенных параметрах это вызвало проблемы с медленным процессом снятия блокирования.

Uukrul

Цитата: tanyxa від Вересень 04, 2018, 08:09:15 ПП
Uukrul, спасибо за подсказку
Как говориться пожалуйста, но хотелось бы узнать конечный результат всех действий  8)

tanyxa

Цитата: Uukrul від Вересень 08, 2018, 01:58:51 ПП
Как говориться пожалуйста, но хотелось бы узнать конечный результат всех действий  8)

Прошу прощения за задержку, не хотела мешать экспериментами другому разработчику. В общем сделала с параметром _wait, параметр enque/delay_max установлен 5 секунд. Результат особенно не изменился, подтверждение заказа успешно создается, но иногда.. не каждый раз, ( закономерность не поддается определению ) возникают аналогичные грабли - проверка блокировки вроде бы успешно пройдена, но при выполнении BAPI_PRODORDCONF_CREATE_HDR вылетаю с блокировкой заказа. Пока решила проблему следующим образом:


LOOP ... " Цикл по позициям Z документа
   CALL FUNCTION 'BAPI_PRODORDCONF_CREATE_HDR' " Создаю подтверждение

   .....   

   CALL FUNCTION 'ENQUEUE_ESORDER'
          EXPORTING
            mode_aufk      = 'V'
            aufnr          = <fs_item>-manuf_aufnr
            _wait          = abap_true
          EXCEPTIONS
            foreign_lock     = 1
            system_failure = 2
            OTHERS          = 3.

        IF sy-subrc = 2.
          "Если блокировка все не снялась, возможно заказ заблокирован другим пользователем
          "читаем с помощью ENQUEUE_READ и проверяем кто именно заблокировал его     
        ELSEIF ( sy-subrc = 1 )  or ( sy-subrc = 3 )
            zcx_static=>raise_sy( ).
        ELSEIF sy-subrc = 0.
          WAIT UP TO 2 SECONDS.
        ENDIF.

   ENDLOOP.
   

Uukrul

Цитата: tanyxa від Вересень 10, 2018, 10:53:24 ДП
          "Если блокировка все не снялась, возможно заказ заблокирован другим пользователем
          "читаем с помощью ENQUEUE_READ и проверяем кто именно заблокировал его     
Т.е. есть вероятность что заказ блокируется пользователем?

tanyxa

Цитата: Uukrul від Вересень 10, 2018, 01:53:09 ПП
Т.е. есть вероятность что заказ блокируется пользователем?
Этой вероятности нельзя исключать, правда в тестовой системе я не попадала так что кому-то ещё захотелось этот же заказ поредактировать, но в проде всяко возможно. А так проблема блокирования мной же ушла, после того как я добавила 2 секундную паузу после успешной проверки на блокировку