In AX 2012 we deal with three types of progress bars:
RunBase
progressInit
construct
kill
reset
- SysOperationProgress
- SysOperationProgressEmbedded
- SysOperationProgressServer
that initialized in RunBase.progressInit method.
What concerns the latter that runs on the server side for batch jobs and tasks, I have never seen before that the Progress field changed during batch tasks execution.
This is because RunbaseProgress Construct method is called without _disableProgressWithoutGUI parameter; nevertheless, it exists in its own New method. This parameter is always TRUE.
I do not know if this option is disabled by purpose having some other developing perspectives in mind, or simply by mistake.
In fact, it is not enough just to extend constructors accordingly to pass this parameter from your own processing class down to SysOperationProgressServer methods. There is another bug in Construct.
This bug does not take into account the caller class that creates its progress bars passing an empty GUID, so that Update method always refreshes the first progress bar found in SysProgress table. In other words, if you started a few batch tasks simultaneously, you will see an interesting progressing: after 100% it starts from zero and so on until the last task finishes. No progressing for the rest of the tasks.
The third bug is in Reset method, which actually run in turn by progress.Kill method (now marked as obsolete). Unfortunately, I do not inderstand the logic of this approach to reset the progress bar when my tasks is finished. From my point of view, it must be really 'killed' it in the end.
// Sample of your class supposed to be processed as a batch void processSomething() { // maximum number of lines to be processed totalLines = ...; // to enjoy our boring user during a few next hours... this.progressInit("@SYS59011", totalLines, #AviUpdate, 1, null, false, newGuid()); // create the progressbar on the server side if it is not a client session with a new unique GUID while (...) { ... } progress.kill(true); }
RunBase
progressInit
/* This method is called to initialize the Progress object in runbase. */ public void progressInit( str caption, int64 total, Filename animation, int numOfBars = 1, FormBuildControl embedded = null, // Begin: Alexey Voytsekhovskiy, bug fix boolean _ifOnSrvBypass = true, guid _callerId = str2guid('') // End: Alexey Voytsekhovskiy, bug fix ) { if (! progress) progress = RunbaseProgress::construct(numOfBars,embedded // Begin: Alexey Voytsekhovskiy, bug fix // to set progressbar on the server side ,_ifOnSrvBypass, _callerId); // End: Alexey Voytsekhovskiy, bug fix progress.setCaption(caption); progress.setTotal(total); progress.setAnimation(animation); }RunbaseProgress
construct
public static RunbaseProgress construct( int _numOfBars = 1, FormBuildControl _embedded = null, boolean _ifOnSrvBypass = true, // Begin: Alexey Voytsekhovskiy, bug fix guid _callerId = str2guid('') // End: Alexey Voytsekhovskiy, bug fix ) { return new RunbaseProgress(_numOfBars,_embedded, _callerId, -1, DateTimeUtil::minValue(), _ifOnSrvBypass); }
kill
// Begin: Alexey Voytsekhovskiy, reset bug fix #obsolete void kill(boolean _toKill = false) { this.reset(_toKill); } // End: Alexey Voytsekhovskiy, reset bug fix
reset
// Begin: Alexey Voytsekhovskiy, reset bug fix void reset(boolean _toKill = false) // End: Alexey Voytsekhovskiy, reset bug fix { if (oprProgress) oprProgress.reset(); else if (oprProgressServer ) // Begin: Alexey Voytsekhovskiy, reset bug fix oprProgressServer.reset(_toKill); // End: Alexey Voytsekhovskiy, reset bug fix }
SysOperationProgressServer
reset
reset
// Begin: Alexey Voytsekhovskiy, reset bug fix public void reset(boolean _toKill = false) // End: Alexey Voytsekhovskiy, reset bug fix { UserConnection conn; SysProgress progress; int i; if ( bypass ) return; conn = new UserConnection(); progress.setConnection(conn); conn.ttsbegin(); try { // delete existing recoreds for this session. delete_from progress where progress.SessionIdx == sessionIdx && progress.SessionLoginDateTime == sessionLoginDateTime; // create records for this session based on number of bars for (i=1; i<=numOfBars; i++) { // Begin: Alexey Voytsekhovskiy, reset bug fix // if the task finished, we have to really kill the progress bar if(!_toKill) { // End: Alexey Voytsekhovskiy, reset bug fix select forupdate * from progress where progress.CallId == callId && progress.ProgressIndex == i; progress.CallId = callId; progress.SessionIdx = sessionIdx; progress.SessionLoginDateTime = sessionLoginDateTime; progress.ProgressIndex = i; // any other default values? progress.write(); } // add the recid into the map progressRecIds[i] = progress.RecId; currentCount[i] = -1; currentIncrement[i] = 0; total[i] = 0; text[i] = ''; } caption = ''; animation = ''; ticksAtLastUpdate = 0; conn.ttscommit(); } catch { conn.ttsabort(); } }
Let me know, if you find other bugs in this functionality.
No comments:
Post a Comment