mezzio/mezzio-session-ext

Prevent session locking?

Closed this issue · 8 comments

By default php ext-session locks the session file until the end of the script execution or until session_write_close is explicitely called, thus blocking any other xhr request. This can affect a SPA's execution time. Should we start the session with the read_and_close option "on" and reopen the session file when and if we need to persist session data (if it changed from the initial reading)?


Originally posted by @pine3ree at zendframework/zend-expressive-session-ext#26

AFAIK the session is a "lazy session", it's calling session_write_close only when regenerating the id or when persisting data at the end when returning the response.

To start a session session_start is used.


Originally posted by @geerteltink at zendframework/zend-expressive-session-ext#26 (comment)

Hello @xtreamwayz,
yes but session_start is called at first operation (get/set/unset) and the session file stays locked for other scripts (SPA xhr calls fro instance) only when returning the response: if the scripts runs for 150ms, any other session-aware script from the same web-user/browser is blocked for 150ms. If we start an ext-session with read_and_close it gets unlocked as soon as it's read. We would then reopen the session just when and if we need to write changes.


Originally posted by @pine3ree at zendframework/zend-expressive-session-ext#26 (comment)

I understand it now. Here is an article that explains it in depth: https://ma.ttias.be/php-session-locking-prevent-sessions-blocking-in-requests/

From PHP.net:

In addition to the normal set of configuration directives, a read_and_close option may also be provided. If set to TRUE, this will result in the session being closed immediately after being read, thereby avoiding unnecessary locking if the session data won't be changed.

Solution:

    private function startSession(string $id, array $options = []) : void
    {
        session_id($id);
        session_start(array_merge([
            'read_and_close' => true,  // <-------
            'use_cookies'      => false,
            'use_only_cookies' => true,
            'cache_limiter'    => '',
        ], $options));
    }

Originally posted by @geerteltink at zendframework/zend-expressive-session-ext#26 (comment)

Exactly @xtreamwayz,
but in order to write changes we also need (if session data changed) to reopen the session w/o the read_and_close flag, set changes and then call session_write_close(). Basically:

  1. Open for reading stored data and close (read_and_close flag or call session_write_close directly)
  2. Use read data and, if needed, set new/changed data (this is done internally)
  3. See if there are any changes, if there are then reopen the session, set data to $_SESSION and call session_write_close.

Most SPAs just need to read session data (user identification), so step 3 will not be called so often.

kind regards


Originally posted by @pine3ree at zendframework/zend-expressive-session-ext#26 (comment)

@pine3ree Would you be willing to submit a PR? With the background here, it definitely makes sense.


Originally posted by @weierophinney at zendframework/zend-expressive-session-ext#26 (comment)

Please read the PR comment...open for suggestions and tests....
zendframework/zend-expressive-session-ext#43


Originally posted by @pine3ree at zendframework/zend-expressive-session-ext#26 (comment)

Hello @weierophinney,

this issue that I originally opened on zend-expressive can be closed, as the optional non-locking feature was implemented!
Kind regards.