Thread Rating:
  • 1 Vote(s) - 2 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Session is already locked - Causes instability
#1
One of our senior developers is working on an Intraweb app which we are trialing with around 2000 end users per day. On occasions, the handled exception shown below is raised. This would be fine however it leads to approximately 20% of users experiencing a continual timeout waiting on the return of any callback submissions. 

It is important to note it is not all users, or just ones connected after the event that is affected and it always follows on from one of these exceptions. 

It would appear it is from the aSync Callback taking time to complete on a slow connection so the button does not disable quickly enough and though the process lock is in place for the callback if they click it enough before it disables the button then it raises the Exception. 

We have worked around this by adding in an onClick javascript setting 'disabled = true' by directly referencing the button within the DOM, thus client-side. This is just a little labor-intensive and I would have expected it to be experienced by others. The callback is a aSync event and not just a form submission as we have to ensure that certain data is processed before submitting.

As such my questions would simply be:

1) Why does the Exception then affect a percentage of other users and make the platform unstable?

2) Is it possible within Intraweb to automatically force a client-side disable of buttons without having to manually create the javascript to disable or is the technology always designed to be server-side via the aSync callbacks? 

3)  As we are still getting the error (I assume by the user refreshing via the command line) is there any way to ensure it does not affect others.

Thank you in advance for sharing your thoughts. 


-------------------
Exception message  : Session is already locked.
Session ID is invalid.
Exception class    : ESessionAlreadyLocked
Session ID        : xl6wwk6EmwwelmrhI0sdUSvmaNa
Exception details  : UrlPath=/$/callback
Exception address  : 00000000008ECD79
Exception Time    : 2020-07-08 15:19:17.966
------------------------------------------------------------------------------------------------------------------------
//REDACTED
Compiler Version  : 300
//REDACTED
IntraWeb Version  : 15.2.3
Multi-session      : True
//REDACTED
Session count      : 489
//REDACTED
Request PathInfo  : /0~0fvmTbdG-jD5jbI2S4~oC2G4a/$/callback
Request Method    : POST
Request User Agent : Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1
Cookies Count      : 1
Reply
#2
A little context, service running on Windows Server 2019, 8Gb memory, 1Gbps internet connection, we are using IWBootstrap, and TIWBSButton, LockOnSubmit is set to true.

The button has a script event onClick of document.getElementById("BUTTON").disabled = true; to disable on click, which works fine.
The callback is for signing a number of different types of documents using https://captaincodeman.github.io/sign-he...sign-here/

Within the button AsyncClick event we call, most of the time it is rock solid.

WebApplication.
CallBackResponse.
AddJavaScriptToExecute(
'if (signaturePad.isEmpty())' + sLineBreak +
'{' + sLineBreak +
' ajaxNotify("OnPleaseSign");' + sLineBreak +
'} else' + sLineBreak +
'{' + sLineBreak +
' ActivateLock();' + sLineBreak +
' var dataUrl = signaturePad.toDataURL();' + sLineBreak +
' var signature = dataUrl.replace(/^data:image\/(png|jpg);base64,/, "");' + sLineBreak +
' $("#HIDDEN_signature").val(signature);' + sLineBreak +
' AddChangedControl("signature");' + sLineBreak +
' ajaxNotify("OnSignature");' + sLineBreak +
'}'
);
We have tried the code in the onClick script event.

It looks like the IWLocker is shown at the start of Async button event then cleared at the end of the click, the ActivateLock() in the call was added to try and prevent re-clicking.

Looking at logs the callback can be 100ms to a couple of minutes (mobile device?) before it returns, if it’s that long the ActivateLock isn’t happening and the user can click where they like thinking the page is dead.

The odd “Session is already locked” is not the end of the world, but the first causes a cascade of sessions to fail, not all, as other signatures come in.

09:37:27:175 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:38:14:067 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:39:44:900 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:39:50:522 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:40:14:417 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:40:16:840 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:40:51:678 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:41:13:646 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
.
.
.

Exception message : Session is already locked.
Session ID is invalid.
Exception class : ESessionAlreadyLocked

The only option is restart the service. Any help / suggestions welcome.
Reply
#3
I can't answer your question, but I'm certain those who can will want to know your IW version and Delphi version. Some of those will be just starting their day soon. It may save some time if you can post that and any other info about context (recent changes, etc) and whether you can force the error at will.

Dan
Reply
#4
Thanks Dan.

It's compiled under Seattle, though on subscription so all versions available, and it's IW15.2.3.

Yesterday we could only recreate by adding a sleep to button click, but disabling the button in the onClick event cured that.

The only clue is it would appear around the busier times when sessions are in the order of ~300 yet this afternoon issue was ~60 sessions connected.

Since the last restart this afternoon, which isn't a busy time of day, I've recorded the time from the CallBackResponse to the OnSignature event and it runs from ~100ms to 14seconds.

I'm pretty sure during busy periods the elapsed time as been into the minutes, which would would be the issue if the IWLocker progress is clearing at the end of the Async event and the ActivateLock(), the form is not locked as not in a submit, so everything is active, waiting on the callback, and the end user is just clicking submit or cancel as they think the app s dead.
Reply
#5
(07-09-2020, 06:36 PM)DanBarclay Wrote: I can't answer your question, but I'm certain those who can will want to know your IW version and Delphi version.  Some of those will be just starting their day soon.  It may save some time if you can post that and any other info about context (recent changes, etc) and whether you can force the error at will.

Dan

IW 15.2.3
Delphi Seattle
Reply
#6
Most controls have an LockOnAsyncEvents property which could take care of this for you.

If you set it to disable the control for an Async click, it would show the IW locker widget which blocks the whole browser screen.

Isn't that an option for you?
Reply
#7
Besides that, seems that the session lock timeout value is too small for you. Are you using the default timeout value (in older versions it could be like 30 seconds).

If you have processes that can take more time, please consider increasing it.

BTW, if you set it to ZERO, you will never see such errors again. New requests will be put on hold until the first is responded. They will be responded one by one sequentially later.

The property is ServerController.SessionOptions.LockSessionTimeout
Reply
#8
(07-09-2020, 04:08 PM)Ryszard@sfd.co Wrote: A little context, service running on Windows Server 2019, 8Gb memory, 1Gbps internet connection, we are using IWBootstrap, and TIWBSButton, LockOnSubmit is set to true.

The button has a script event onClick of document.getElementById("BUTTON").disabled = true; to disable on click, which works fine.
The callback is for signing a number of different types of documents using https://captaincodeman.github.io/sign-he...sign-here/

Within the button AsyncClick event we call, most of the time it is rock solid.

        WebApplication.
          CallBackResponse.
            AddJavaScriptToExecute(
              'if (signaturePad.isEmpty())' + sLineBreak +
              '{' + sLineBreak +
              '  ajaxNotify("OnPleaseSign");' + sLineBreak +
              '} else' + sLineBreak +
              '{' + sLineBreak +
              '  ActivateLock();' + sLineBreak +
              '  var dataUrl = signaturePad.toDataURL();' + sLineBreak +
              '  var signature = dataUrl.replace(/^data:image\/(png|jpg);base64,/, "");' + sLineBreak +
              '  $("#HIDDEN_signature").val(signature);' + sLineBreak +
              '  AddChangedControl("signature");' + sLineBreak +
              '  ajaxNotify("OnSignature");' + sLineBreak +
              '}'
            );
We have tried the code in the onClick script event.

It looks like the IWLocker is shown at the start of Async button event then cleared at the end of the click, the ActivateLock() in the call was added to try and prevent re-clicking.

Looking at logs the callback can be 100ms to a couple of minutes (mobile device?) before it returns, if it’s that long the ActivateLock isn’t happening and the user can click where they like thinking the page is dead.

The odd “Session is already locked” is not the end of the world, but the first causes a cascade of sessions to fail, not all, as other signatures come in.

09:37:27:175 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:38:14:067 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:39:44:900 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:39:50:522 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:40:14:417 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:40:16:840 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:40:51:678 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
09:41:13:646 IWServerControllerBaseException: Session is already locked. (ESessionAlreadyLocked)
.
.
.

Exception message  : Session is already locked.
Session ID is invalid.
Exception class    : ESessionAlreadyLocked

The only option is restart the service. Any help / suggestions welcome.


This shouldn't happen and I don't think this is caused by IW. Can't one of your processes be just blocking other uses (even a locked table or record in a Database can do it for multiple users)?
Reply
#9
(07-09-2020, 11:49 PM)Alexandre Machado Wrote: Besides that, seems that the session lock timeout value is too small for you. Are you using the default timeout value (in older versions it could be like 30 seconds).

If you have processes that can take more time, please consider increasing it.

BTW, if you set it to ZERO, you will never see such errors again. New requests will be put on hold until the first is responded. They will be responded one by one sequentially later.

The property is ServerController.SessionOptions.LockSessionTimeout

Thank you for the suggestion, it was left as the default 30secs, I will try 0, the system is live so I won't know until restart this evening, and traffic lower over the weekend so it may be next week before results come in.
Reply
#10
That's not the only recommendation. I also suggested that you disable the UI while you post a request. IntraWeb controls have a LockOnAsyncEvents property. Use it. That's the only way to prevent a impatient user to post hundreds of requests in just a few seconds.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)