En la siguiente entrada se explica como con un cambio de
enfoque podemos hacer mucho más eficiente el parallel processing o proceso paralelo
con modulo de funciones para así tener más control del mismo y un uso eficiente
de la memoria del servidor.
A continuación mostraré un breve ejemplo:
Acá se seleccionan el número de paquetes en el cual se
debe distribuir la carga en tu función paralela:
SELECTION-SCREEN BEGIN OF BLOCK b03 WITH FRAME TITLE text-010.
SELECTION-SCREEN SKIP.
SELECT-OPTIONS: so_packs for CPETASKLOG-CPEINSTANCEID no INTERVALS.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN END OF BLOCK b03.
SELECTION-SCREEN SKIP.
SELECT-OPTIONS: so_packs for CPETASKLOG-CPEINSTANCEID no INTERVALS.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN END OF BLOCK b03.
Se seleccionan los datos a procesar se hace la llamada al
modulo de funciones que se va a ejecutar en paralelo:
START-OF-SELECTION.
PERFORM GET_DATA CHANGING
tab_datos.
Se inicia el proceso previo al proceso
paralelo:
PERFORM F_PROCESS_PP USING TAB_DATOS
GT_REPROCESS.
Toda la información
que se almacena en gt_reprocess son registros que no fueron procesados por
diferentes razones.
En la próxima entrada
indicaremos como proceder a su reprocesamiento
PERFORM SHOW_LOGS USING
GT_LOG.
“------------------------------------------------------------------------------------
FORM F_PROCESS_PP USING tab_reg_datos like tab_datos
CHANGING P_REPROCESS
LIKE gt_reprocess.
DATA: lineas TYPE i,
ii TYPE string,
lv_msg TYPE string,
zit_trab TYPE TABLE OF zbl02_st_datos_trabajador.
****************************************************************
data : rng_nro TYPE i,
lv_LINE_from type I,
lv_LINE_to type I,
e_cnt_packages TYPE
BANK_DTE_PP_CNT_PACKAGES,
tabix TYPE sytabix.
DATA: lv_range type i.
*****************************************************************
DESCRIBE TABLE tab_reg_datos
LINES gv_lineas.
Se asignan el número
de paquetes en el cual debemos subdividir el trabajo paralelo.
e_cnt_packages = so_packs-low.
DO e_cnt_packages TIMES.
add 1 to rng_nro .
“Esta function nos dice el rango de que linea a que linea va
cada paquete
CALL FUNCTION 'ZMF_FILE_PACK_RANGE'
EXPORTING
I_RANGE_NO = rng_nro
I_CNT_RANGES_TOTAL = e_cnt_packages
I_START_NUM = 1
I_LAST_NUM = gv_lineas
IMPORTING
E_LINE_FROM = lv_LINE_from
E_LINE_TO = lv_LINE_to
EXCEPTIONS
RANGE_INVALID = 1
OTHERS = 2.
IF SY-SUBRC <> 0.
* Implement
suitable error handling here
ENDIF.
·
Agregamos el numero de lineas a una nueva table para
su procesamiento paralelo
APPEND LINES OF tab_reg_trab FROM lv_line_from
TO lv_line_to TO TAB_DATOS.
*
Aca llamamos a nuestra función que se desarrollo en la
entrada anterior con nuevos parámetros
PERFORM CALL_PARALLEL USING TAB_DATOS
rng_nro
CHANGING P_REPROCESS.
free TAB_DATOS[].
ENDDO.
* Se hace esperar a la tarea para que se ejecute
correctamente.
WAIT UNTIL gv_rcv_jobs >= gv_snd_jobs.
ENDFORM. " F_PROCESS_PP
FORM f_procesar_reg USING tab_datos LIKE tab_datos
task TYPE i
CHANGING tab_reprocess
LIKE gt_reprocess.
DATA: lv_msg TYPE string,
modul TYPE i,
wa_reprocess TYPE ty_tasks.
"Fecha para mostrar el log
CONCATENATE
sy-datum+6(2)
sy-datum+4(2)
sy-datum(4)
INTO gv_fecha
SEPARATED BY gc_punto.
*
CLEAR gs_reg_trab.
gv_system = text-003.
* Se obtiene el índice para generar el nombre de la tarea.
gv_index = task.
CONDENSE gv_index.
* Se genera el nombre de la tarea, único por cada registro a
procesar.
CONCATENATE text-006
gv_index
INTO gv_taskname.
* Se llama el RFC
CALL FUNCTION 'ZBL02_FM_PROC_DAT_TRAB' STARTING
NEW TASK gv_taskname
DESTINATION IN GROUP gv_system
PERFORMING f_finalizar_funcion ON END OF
TASK
EXPORTING
it_str_datos_trab = tab_datos
EXCEPTIONS
system_failure = 1
MESSAGE mess
communication_failure = 2 MESSAGE mess
resource_failure = 3.
"Tipo de relación
CASE sy-subrc.
WHEN 0. "Si
no hay error se incrementa contador de éxito.
gv_snd_jobs = gv_snd_jobs + 1.
WHEN 1 or 2.
MESSAGE mess TYPE 'I'.
WHEN 3. "Si hubo error se hace
esperar a la tarea.
IF
gv_snd_jobs >= 1 AND gv_exc_flag = 0.
gv_exc_flag = 1.
WAIT UNTIL gv_rcv_jobs >=
gv_snd_jobs
UP TO 5 SECONDS.
ENDIF.
IF sy-subrc = 0.
gv_exc_flag = 0.
ELSE.
MESSAGE 'Resource failure' TYPE 'I'.
ENDIF.
wa_reprocess-taskname = gv_taskname.
wa_reprocess-tasknro = task.
APPEND wa_reprocess to tab_reprocess
“Aca guardamos solo
la tarea que fallo para su porterior reprocesamiento
free: lv_msg,wa_reprocess.
WHEN OTHERS.
MESSAGE 'Other Error' TYPE 'I'.
ENDCASE.
*
ENDFORM.
Una vez finalizado todos los llamados a la función paralela
el programa llama al perform donde recibimos el resultado de su ejecución y
guardamos los logs correspondientes.
FORM f_finalizar_funcion USING gv_taskname.
DATA: mess
TYPE c LENGTH 80.
task_wa-name = gv_taskname.
gv_rcv_jobs = gv_rcv_jobs + 1.
* Se reciben los resultados del RFC para loguear los
mensajes.
RECEIVE RESULTS FROM FUNCTION ' Z_FM_PARALLELS '
TABLES
e_tab_return = gt_log
“Es importante colocar las exceptions en caso de algún error
de comunicación o el paralelo tenga “algún problema
EXCEPTIONS
system_failure = 1 MESSAGE mess
communication_failure = 2 MESSAGE mess .
IF sy-subrc eq 0.
task_wa-dest = info-rfcdest.
ELSE.
task_wa-dest = mess.
ENDIF.
APPEND task_wa TO task_list.
*
* Se loguean todos los mensajes
CLEAR gs_log.
LOOP AT gt_log INTO gs_log.
CLEAR gv_tam_msj.
gv_tam_msj = strlen( gs_log-message ).
IF gv_tam_msj > 50.
gs_message-msg_text_2 =
gs_log-message+50.
IF gv_tam_msj > 100.
gs_message-msg_text_3 =
gs_log-message+100.
ENDIF.
ENDIF.
gs_message-msgty = gs_log-type.
gs_message-msg_text_1 = gs_log-message.
APPEND gs_message TO gt_message.
CLEAR: gs_message.
* gt_message[].
CLEAR gs_log.
*
ENDLOOP.
FREE: gt_log.
*
ENDFORM.
·
Los puntos relevantes del código se han puesto
en negrita para facilitar su importancia
No hay comentarios.:
Publicar un comentario