zendframework / zend-expressive-session-ext

PHP ext-session persistence adapter for zend-expressive-session.
BSD 3-Clause "New" or "Revised" License
12 stars 9 forks source link

Prevent session locking? #26

Open pine3ree opened 6 years ago

pine3ree commented 6 years ago

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)?

geerteltink commented 6 years ago

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.

pine3ree commented 6 years ago

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.

geerteltink commented 6 years ago

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));
    }
pine3ree commented 6 years ago

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

weierophinney commented 6 years ago

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

pine3ree commented 5 years ago

Please read the PR comment...open for suggestions and tests.... https://github.com/zendframework/zend-expressive-session-ext/pull/43

weierophinney commented 4 years ago

This repository has been closed and moved to mezzio/mezzio-session-ext; a new issue has been opened at https://github.com/mezzio/mezzio-session-ext/issues/4.