lunedì 20 maggio 2019

AX 2012 - Creare batch job tramite x++ e aggiunta dipendenze

In questo post vediamo come creare dei batch job schedulabili e suddividere l'esecuzione in task. Sfruttando inoltre le "Batch Dependency" faremo in modo che ogni task parta solo se il precedente termina ( oppure và in errore ). Allo scopo creiamo una semplice classe sysoperation (LIL_WhoAmIService più relativa controller / contract) che prende come parametro un intero e lo restiuisce tramite info log. Il job seguente effettua tutte le operazioni di schedulazione / aggiunta dipendenze:

 static void LIL_TestRunDependency(Args _args)  
 {  
   BatchHeader       batchHeader   = BatchHeader::getCurrentBatchHeader();  
   List          list      = new List(Types::Class);  
   ListEnumerator     le;  
   LIL_WhoAmIController  batchTask,prev;  
   Counter         i;  
   BatchInfo        batchInfo;  
   
   batchHeader = batchHeader::construct();  
   
   batchHeader.parmCaption("Task dependency execution");  
   
   //creo 10 instaze della mia classe, ciascuna con il suo id  
   for(i = 0; i < 10; i++)  
   {  
     batchTask = new LIL_WhoAmIController(classStr(LIL_WhoAmIService),  
                        methodStr(LIL_WhoAmIService, printWhoAmi));  
   
     batchTask.parmWhoAmi(i);  
   
     batchTask.init();  
   
     //in caso di sysoperation è neccessario impostare execution mode = Synchronous  
     //altrimenti le dipendence non vengono rispettate e i task partono tutti  
     //allo stesso momento  
     batchTask.parmExecutionMode(SysOperationExecutionMode::Synchronous);  
   
     batchInfo = batchTask.batchInfo();  
   
     batchInfo.parmCaption(strFmt("Task N%1",batchTask.parmWhoAmi(i)));  
   
     list.addStart(batchTask);  
   }  
   
   //Creazione dipendenze  
   le = list.getEnumerator();  
   while (le.moveNext())  
   {  
     batchTask = le.current();  
   
     if(!prev)  
     {  
       //il primo task non avarà voncoli  
       batchHeader.addRuntimeTask(batchTask,BatchHeader::getCurrentBatchTask().RecId);  
     }  
     else  
     {  
       //i successivi dipendono dal precedente  
       batchHeader.addRuntimeTask(batchTask,BatchHeader::getCurrentBatchTask().RecId);  
       batchHeader.addDependency(prev,batchTask,BatchDependencyStatus::FinishedOrError);  
     }  
   
     prev = le.current();  
   }  
   
   batchHeader.save();  
   
   info("Done");  
 }  

Se lanciamo il job ed aspettiamo la fine dell'esecuzione dei 10 task, possiamo vedere il risultato in batch history:



L'esecuzione ha generato 10 tasks. il Task "N0" come vediamo non ha condizioni. Tutti gli altri dipendono dal precedente, Ad esempio il task N5 dipende dal task N4 e così via.