RTC Forums
May 18, 2024, 05:46:07 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: Concurrent use of shared session  (Read 5016 times)
peteness
Newbie
*
Posts: 4


« on: April 07, 2012, 01:19:47 AM »

Hi.

I have a web application with a bunch of AJAX callbacks and some long-lived calls from the client to the server from the web server to do notifications (similar to COMET's ajax long polling).  I ran into an issue with my long polling call where I was leaving the session "locked" during the polling, which would cause FindSession to return false, which would induce my application to create another session.  Ensuing issues arise because I'm not accessing the same session.  There are many opportunities for overlapping ajax calls from the same browser that all might need some session state information (like "logged_in").

So the root problem here is that I was keeping the session open during long polling, but even after I fix this by unlocking the session, I still have the issue of *possible* failures of FindSession because another Ajax call is servicing something that needs the session object.

I dug around and couldn't find discussion of this or examples, although I'm pretty new to RTC so I may have missed it.

Ideally, I'd want to just block the contending incoming call until the request that is currently using the session releases the lock, but I'm not sure on the best method for this - I could certainly do it external to the RTC framework with a TMonitor or similar, but it seems as though I may be doing it the hard way and that RTC probably has a built-in better method for solving this.

Any tips?

Thanks,
Pete
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: April 07, 2012, 03:23:24 AM »

There are two methods for checking if a Session exists:

FindSession() -> returns TRUE and locks the Session, only if the Session exists and is NOT locked

HaveSession() -> returns TRUE if the Session exists, even if it is currently locked

By using these 2 methods, you can implement a loop, where you wait for a Session to get unlocked if it exists. Make sure to use "Sleep" inside the loop, so you don't end up wasting a lot of CPU power, and ... exist the loop if "HaveSession" returns FALSE. Using a loop counter to exist the loop if the lock remains for "too long" is also a good idea.

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #2 on: October 21, 2013, 01:10:53 AM »

Danijel,

Could you please explain this again, I have the same issue where I need to make 2 calls one after the other and the second call to FindSession fails (probably because it gets lock by the first).

Code:
    if Srv.FindSession( ASessionID ) then
//    if Srv.HaveSession( ASessionID {Srv.Request.cookie[ 'session' ]} ) then  
    begin
      { Session found, we now have full access to the “Session” property. }

      // Check the example above, where we set “login” to TRUE
      if Srv.Session.asBoolean[ 'login' ] then   // If I use HaveSession (commented above) instead of FindSession, this line causes an AV
      begin
        //  Do something
      end;
    end;

Reading your previous comment, sounds like I would have to use HaveSession but if I do I get an AV (sort of a chicken and egg thing).

How can I make 2 very fast (I should say Asynchronous) calls to FindSession and get a True result even if the first call locks the session?

Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: October 21, 2013, 09:10:48 AM »

FindSession locks the session if it exists and makes it available for access through the Session object. Until the Session is unlocked again (by calling UnLockSession manually, or by the components after your event completes execution), any consecutive calls to FindSession will fail (return FALSE) and the Session will NOT be available to you. This is to ensure that only ONE thread will be accessing Session data at a time. Concurrent access to Session data is NOT allowed, because it would lead to data corruption.

HaveSession tells you if the session exists, but it does NOT lock the Session and does NOT make Session data available for access. In other words, calling HaveSession leaves the Session pointer unchanged on the connection component unchanged (= NIL), which is why you will get an AV if you try to use the Session object after HaveSession, if FindSession has returned FALSE.

If you have more than one physical connection using the same Session data, you will have to implement a loop to wait for FindSession to return TRUE if HaveSession returns TRUE. Just make sure to add a Sleep and interrupt the loop if it takes too long (based on your assesment of how long the other thred might need).

For example ...

var
  SesOK:boolean;
  SesTim:Cardinal;  
begin
...
SesTim:=GetTickTime;
SesOK:=Srv.FindSession(ASessionID);
while SesOK=FALSE do
  begin
  if Srv.HaveSession(ASessionID)=FALSE then
    Break // Session does not exist? Break the loop
  else    
    begin
    Sleep(100); // sleep 1/10 of a second  
    SesOK:=Srv.FindSession(ASessionID);
    if not SesOK then
      if GetTickTime-SesTim>5000 then
        Break; // waiting more than 5 seconds? Break the loop
    end;
  end;
if SesOK then
  begin
  // we have the Session, use it ...
  end
else
  begin
  // we do NOT have the Session!
  end;
end;

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #4 on: October 21, 2013, 05:01:35 PM »

Thanks for the clarification Danijel.

Another approach would be to handle it on the front end (in our first Ajax call, by setting async to false, by doing so, the second call succeeds)

Code:
$.ajax({
dataType: HLObj.ajax_dataType,
type: HLObj.ajax_type,
url: HLObj.site_URL+'ServiceName',
data: params,
        async: false   //<-- here
})
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #5 on: October 21, 2013, 05:15:28 PM »

Thanks for sharing.

Best Regards,
Danijel Tkalcec
Logged
mmitton
Newbie
*
Posts: 2


« Reply #6 on: November 05, 2013, 01:41:00 PM »

Hi Danijel,

Am I correct in assuming that this is purely for the write synchronisation between threads and you can still read data without obtaining a session lock?

ie. You only need to FindSession() if you need a lock and need to write session data. You can use HaveSession() if you simply need to acknowledge session existence and then read session data

We have an application in which session data is only written when authentication is performed. After this, we simply need to check that the user is indeed logged in and then read some data from their session.

Regards
Mark
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #7 on: November 05, 2013, 01:55:02 PM »

When using RTC Sessions, a Lock is required for reading as well as writing. This is by design. But, the use of RTC Sessions is not mandatory for Applications working with Sessions. If you need the abbility to have multiple users reading Session data at the same time, you can implement your own Session handling mechanisms.

Best Regards,
Danijel Tkalcec
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.027 seconds with 16 queries.