Asynchronous change of session in PHP

Author: Denis Trubachev
Date of publication: 2014-05-27 00:26:33

Initially, this problem appeared during going to the same page in another browser tab, if the script is fairly long and, in addition, the work with the session is necessary in the script. Two requests are queued and the next is proceeded only after the previous one is finished. An illustrative example of the code:

<?
  session_start();
  print "Run...
"; flush(); sleep(10); print "Done
"; ?>

General description of the problem

If you successively open multiple tabs that calls this code, the session_start (); function will be proceeded only if there are no more scripts that work with the session.

The problem comes from the fact that the engine, used in php sessions by default, creates its own file for each session, which stores all of its information. Obtain access to the file when calling the function session_start. If the file is used at the moment, then expect to release the session file, and only then the script continues to proceed its code. There is another method of reliefing the session - calling session_close method.

The problem became more common after AJAX requests were promoted greatly. At the moment, most of the sites content is dynamic and is updated or filled with AJAX.

Methods for solving common problems

In most of the forums they suggest using function session_write_close (). An example of articles on this topic. This feature allows you to close the session to record, but reading from the session will be possible. In some cases, it solves the problem. There is another solution to the problem - to store session data in the database. It is more suitable, since it provides access to the records of the session. Storing sessions in the database allows to improve performance, because locking does not occur for asynchronous requests.

There is still something that is not resolved

But the following problem appears: if a user is waiting for registration, let’s say, a user fills in in a form of authorization or registration, and at this moment some AJAX proceeds (for example, some dynamic list with auto-scroll). After sending data from the registration form he should successfully login. Authorized user is known to be provided with more content than the guest, and our case is no exception. This content is generated by registration script. I think it’s easier to grasp it with code.

Script code:

<?
session_start(); //opening a session
echo 'AJAX response'; //preparing html response
saveSessionData('latestRequestTime' => time()); //writing session data into storage
?>

If this script is called by AJAX request immediately after loading the page. Login script will have, let’s say, the following code:

<?
session_start(); //opening a session
$user = register_user($_REQUEST); //registering of a new user
echo 'registration response'; //preparing html response
saveSessionData('logged_user_id' => $user->id, 'latestRequestTime' => time()); //authentication of a user (writing session data into storage)
?>

And then the fun begins: if you record for a long time, this is how workflow looks like:

The problem is that we try to write in the same session different data at different times. Nobody knows what value will be after proceeding, because requests to the server are parallel.

Solving the problem

The proposed solution is: it needs to be created a separate file for each recording session that will store the approximate time of its release. The file stores only timestamp of unlocking time, because this the file will not take up a lot space, even when it’s a large number of users.

If there is a file a lock time has not yet expired, the entry is not made. This fixes the problem with simultaneous recording of the session data in the database. This solution allows all the necessary sessions’ information from the database to be read without any delay.

Implementation description

When recording data from session to the database, session locking is checked. Locking is a file with the session name. If the lock is there, the session recording is not happening. If within this script, we have marked that session is to be locked for a certain time, then at the end of its work, the following occurs:

  1. Creates a lock file
  2. Current session data is written to the database

Results

The problem is quite popular, and urgency of the problem increases with the size of the project. They try to solve it as good as they can and one of the solutions is provided in this article.

Basically we are working with yii framework, then I put the components in extensions. You can download it here.

I would be glad if I helped anyone :)

Links on this topic:

Article comments
Comments:
No results found.
Only logged users can leave comments.