'Is it possible to provide estimate hrs or minutes for progress completion? - PROGRESS 4GL
I am using below query for progress completion which shows how much percentage is completed in record updating process. My question or doubt here is Is it possible to provide estimated hrs/minutes for this progress completion?
For example, consider a table has 1000 records and each record gets into some validations before updating and approx time is less than a second(milliseconds). So if a single record takes less than a millisecond to update after gets to validations then what will be estimated for 1000 records? How to calculate and convert into hh:mm:ss? Please help to write a sample query.
DEFINE VARIABLE I AS INTEGER NO-UNDO.
DEFINE VARIABLE iPercentage AS INTEGER NO-UNDO.
DEFINE VARIABLE iComp AS INTEGER NO-UNDO.
DEFINE VARIABLE iRec AS INTEGER NO-UNDO.
ASSIGN
I = 0
iComp = 0
iRec = 0
iPercentage = 0.
/* Calculating Total records*/
FOR EACH <table> NO-LOCK:
iRec = iRec + 1.
END.
/* Taking each records from the same table to update*/
FOR EACH <table> NO-LOCK:
I = I + 1.
IF I = 1 THEN DO:
/*do some more validations*/
iComp = iComp + I.
iPercentage = 100 * (iComp / iRec).
IF iPercentage = 100 THEN DO:
MESSAGE "Record Updation Is completed".
END.
ELSE DO:
I = 0
NEXT.
END.
END.
END.
Solution 1:[1]
This variant here relies on NUM-RESULTS as suggested by nwahmaet and uses a DATETIME-TZ Variable and the INTERVAL function to determine the runtime. Output is done only every 1000's iteration so that the display of the Progress does not cause more load than the processing.
&scoped Table Customer
SESSION:APPL-ALERT-BOXES = FALSE .
DEFINE VARIABLE I AS INTEGER NO-UNDO.
DEFINE VARIABLE iPercentage AS INTEGER NO-UNDO.
DEFINE VARIABLE iComp AS INTEGER NO-UNDO.
DEFINE VARIABLE iRec AS INTEGER NO-UNDO.
DEFINE VARIABLE dtStart AS DATETIME-TZ NO-UNDO.
DEFINE VARIABLE iMsecs AS INTEGER NO-UNDO.
ASSIGN
I = 0
iComp = 0
iRec = 0
iPercentage = 0.
DEFINE QUERY qT FOR {&table} .
OPEN QUERY qT PRESELECT EACH {&Table}.
iRec = QUERY qT:NUM-RESULTS. // if you use a FOR you get 0
dtStart = NOW .
/* Taking each records from the same table to update*/
FOR EACH {&table} NO-LOCK:
I = I + 1.
IF I MODULO 1000 = 0 THEN DO:
PAUSE .05 . // simulate some load
/*do some more validations*/
iComp = iComp + I.
iPercentage = 100 * (iComp / iRec).
iMsecs = INTERVAL (NOW, dtStart, "milliseconds") .
MESSAGE i "of" iRec "/" iMsecs "/"
STRING (INTEGER ((iMsecs / (i / iRec) // iMsecs / % processed = estimated total time
- iMsecs) // minus time already spent
/ 1000), // msecs to seocnds
"hh:mm:ss") // format output
"remaining".
END.
END.
MESSAGE "Record Updation Is completed".
Solution 2:[2]
It is not simple to do in ABL. Maybe not even possible. I think you would have to keep track - ie measure how long such a query takes, and store that somewhere. You could have a db table that has a query name, num records returned (maybe?) and time taken. You can use those records to determine an average time of how long it take to find, say, 100 records and use that with the percentage progress bar. After each query, you create a record in that table recording how long it too.
But doing that is going to add time to the processing of that query. ANd there's nothing in the DB itself that does this for you.
There are also faster method of getting the query count than looping through them all twice.
You can use a query with a PRESELECT clause, which can give you the count.
define query qT for Table.
open query qT preselect each Table.
iRec = query qT:num-results. // if you use a FOR you get 0
get first qT no-lock.
do while available Table:
if query qT:current-result-row mod 50 = 0 then
. // update the progress bar
// do stuff with the data
get next qT no-lock.
end.
Solution 3:[3]
The bit that you are missing is the elapsed time so far. That's pretty easy to obtain:
DEFINE VARIABLE I AS INTEGER NO-UNDO.
DEFINE VARIABLE iPercentage AS INTEGER NO-UNDO.
DEFINE VARIABLE iComp AS INTEGER NO-UNDO.
DEFINE VARIABLE iRec AS INTEGER NO-UNDO.
ASSIGN
I = 0
iComp = 0
iRec = 0
iPercentage = 0.
/* Calculating Total records*/
FOR EACH <table> NO-LOCK:
iRec = iRec + 1.
END.
etime( true ). // set the etime counter to 0
/* Taking each records from the same table to update*/
FOR EACH <table> NO-LOCK:
I = I + 1.
IF I = 1 THEN DO:
/*do some more validations*/
iComp = iComp + I.
iPercentage = 100 * (iComp / iRec).
IF iPercentage = 100 THEN DO:
MESSAGE "Record Updation Is completed".
END.
ELSE DO:
message string( 1000 * ((( etime / ( iComp / iRec )) - etime )) , "hh:mm:ss" ) "remaining".
I = 0
NEXT.
END.
END.
END.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | nwahmaet |
| Solution 3 | Tom Bascom |
