Code Snippet Series: Wait a Fraction of a Second
This post is part of a series on code snippets. The complete list of posts in the series is available in the document Code Snippets: A Blog Series.
I occasionally need to wait for a lock entry to be dequeued when I have a multi-step scenario where COMMIT WORK AND WAIT is insufficient but waiting a static number of seconds with WAIT UP TO n SECONDS could result in waiting longer than necessary.
With the below code, I reduce wait time to the shortest possible wait–depending on use, even down to one tenth of a second.
DATA lt_enq TYPE STANDARD TABLE OF seqg3. DATA: BEGIN OF ls_time, start TYPE timestampl, now TYPE timestampl, elapsed TYPE tzntstmpl, " in seconds limit TYPE tzntstmpl VALUE 3, " in seconds END OF ls_time. GET TIME STAMP FIELD ls_time-start. WHILE ls_time-elapsed < ls_time-limit. CALL FUNCTION 'ENQUEUE_READ' EXPORTING gname = TABLE_NAME garg = TABLE_KEY TABLES enq = lt_enq EXCEPTIONS communication_failure = 1 system_failure = 2 OTHERS = 3. IF lt_enq IS INITIAL. EXIT. " object is not locked ENDIF. GET TIME STAMP FIELD ls_time-now. ls_time-elapsed = cl_abap_tstmp=>subtract( tstmp1 = ls_time-now tstmp2 = ls_time-start ). ENDWHILE. " elapsed time
I like this one! It's sadly, one that I find I use a lot.
A nice add to this one is to read the lt_enq-guname if the time runs out. Then display it as locked by that user. I've also had a few request to change it from user name to actual person name.
You can definitely take the check further or even swap out the call to ENQUEUE_READ for some other thing you're waiting for, like a dependent record to be created.
This solution is more elegant than my usual solution which just runs a random number of times. Thank you.
There was a similar blog with very interesting discussion on the same topic some time ago:
It's a common problem I'm sure. It's great that these forums exist to share solutions.
It is not much known. But you can also wait fraction of second with WAIT UP TO command 🙂
This is true, but maybe your check will succeed in 0.12 seconds. With two waits of 0.1 seconds you'll end up waiting 0.2 seconds. Think of what you could do with the 0.08 seconds you've saved! LOL. For many programs, the code snippet above is likely overkill, but it also could come in handy for processing very large sets of data where those 0.08 seconds add up to a meaningful time saving.
Unfortunately it's possible only for recent releases (see: https://blogs.sap.com/2019/01/18/while-n-seconds-killing-the-wait-up-to-n-seconds/#comment-448388 )
I remember that it worked in ABAP 7.31 at least…
EDIT: I might be wrong. More info below.
milliseconds since 7.40 SP08 cf ABAP release news
Thank you. But before 7.40 this worked also. They maybe changed only the docu description or some internal definitions...
You can find mentions about "decimal" WAIT UP TO as far as 2008 go... or so... And I remember that it worked in 7.31.
Did you make measurements to make sure that ‘0.5’ and 1 did not wait both 1 second? (conversion to integer type)
But maybe the data object was passed directly as-is to the kernel, so it would depend on the kernel only, who knows.
Yes of course I did few tests before. It waited for a half second, not one second.
EDIT: Tested it now on some old 7.21 server and this waited 10 seconds, so fractions do not work there. Can somebody on 7.31 test how long it wait 🙂 ?
7.31 here (EHP6) - 10 seconds. Captured timestamp before and after. Bummer...
Thank you Jelena! I was probably wrong, or it was dependent also on some other SAP component/s version.
Thanks for bringing this up though! Now I'll keep in mind this would be possible for us in future.
One question for which I have no answer is the impact of repeating code continuously on the CPU load. I observed that a counting loop of a number of seconds has a high impact on the CPU load (and impacts other parallel processes), but a WAIT of the same duration seems to have no impact. So maybe a little WAIT inside the loop is better.
That would be in interesting comparison test. There is probably some balance that needs to be considered between burden on the user (processing time) and burden on the CPU (resources). This is great insight Sandra, thanks for sharing. I always find it interesting when different solutions in ABAP yield the same end result yet have different impacts on performance.
Also with above solution, it will keep querying the enqueue server, which is a central component. So instead of impacting one application server, it can potentially impact the full landscape of application servers.
Thanks for sharing! This is a pretty common problem, so I appreciate the solution.
It is common. So common that maybe a solution should be provided as standard.
or perhaps along with ENQUEUE and DEQUEUE FM, we have WAITQUEUE...
I would totally vote for that! CC Horst Keller
In most cases this problem results of objects booked in update task.
So it can be solved using SET UPDATE TASK LOCAL.