Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[HttpFoundation] enhance PdoSessionHandler#10931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
stof commentedMay 17, 2014
I suspect your meant to open the PR against 2.3 |
Tobion commentedMay 17, 2014
No since it's a bc break. |
fabpot commentedMay 17, 2014
@Tobion But you have a bunch of unrelated commits in this PR. |
Tobion commentedMay 17, 2014
Because 2.3 is not merged in master yet. |
fabpot commentedMay 17, 2014
@Tobion 2.3 has now been merged into master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Maybe you meantDSN instead ofDNS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
haha true
Tobion commentedMay 19, 2014
This would be ready. Where should I document the change (depends for which version it gets merged)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
dsn*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
thx fixed
stof commentedMay 19, 2014
@Tobion I think similar changes should be done in the DBAL session handler. |
Tobion commentedMay 21, 2014
Tobion commentedMay 22, 2014
@stof you know what fabbot.io is complaining about?http://fabbot.io/report/symfony/symfony/10931/953226bdb666880c61157a42d7839eb42c9c8c9c |
vntw commentedMay 22, 2014
There are some extra spaces after the ';' |
Tobion commentedMay 25, 2014
@venyii Thanks for spotting |
Tobion commentedMay 25, 2014
Reopened against 2.5:#10991 |
Tobion commentedMay 27, 2014
Ok, master 2.6 again. |
Tobion commentedMay 27, 2014
@fabpot ready |
Tobion commentedMay 27, 2014
I'll write a blog post about this soon. |
staabm commentedMay 27, 2014
@Tobion please cross link your post here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I need to add a check that we are not in a transaction, because it would implicit commit it and thus ruin the locking when called after read().http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Hm doesn't really matter since as read() would raise an error anyway when the table doesn't exist. But to be correct rollback should be called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
FYI, PostgreSQL actually supports performing DDL changes in a transaction, and rolling back these changes a whole. Its one of the many reasons why I love PostgreSQL ;)
So if you create a table inside a transaction the table will not be visible outside of the transaction, but the pg_class catalogs tables (and related) are however locked until the transaction is released.
Not a problem in this case, just some useful information :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks for the information
9ca183f toc900de5CompareTobion commentedSep 29, 2014
@fabpot this is ready for merge. I tested the binary data and the different locking strategies with both mysql and sqlite. It works like a charm. But I don't have postgres, oracle, mssql available. So it would be good if the community can test the class with these DBMS. Or I might find time to set it up later. |
Tobion commentedSep 29, 2014
@symfony/deciders ping |
staabm commentedSep 29, 2014
@Tobion should one of the locking strategies be recommended for the "regular-user"? |
Tobion commentedSep 29, 2014
The default strategy (transactional) is recommended because it's most reliable across dbms. |
romainneutron commentedSep 29, 2014
The documentation could enjoy an update in this section:http://symfony.com/doc/current/cookbook/configuration/pdo_session_storage.html#sharing-your-database-connection-information As it's not recommended anymore to share the doctrine connection, we should deprecate this part |
romainneutron commentedSep 29, 2014
What about anauto-save parameter in the framework bundle (in the session section)? |
Tobion commentedSep 29, 2014
@romainneutron this section is only about sharing the connectionsettings. Not the connection itself. So this part is still ok. |
romainneutron commentedSep 29, 2014
woops, you're right |
Tobion commentedSep 29, 2014
I think there are different cases that need to be examined, e.g. an AJAX request to:
|
stof commentedSep 30, 2014
Maybe we could add a listener on |
staabm commentedSep 30, 2014
What about some sort of debugging mechanism (e.g. A class using ArrayAccess) which will throw exceptions in case a code snippet tries to add/manipulate session data after the session has already been written+closed? |
Tobion commentedSep 30, 2014
Tobion commentedOct 2, 2014
Any votes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You should prefix this with[BC BREAK]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
done
fabpot commentedOct 2, 2014
👍 |
Tobion commentedOct 3, 2014
I just realize this also fixes#9029 |
fabpot commentedOct 3, 2014
Thank you so much for working on this@Tobion. This is much appreciated. |
This PR was merged into the 2.6-dev branch.Discussion----------[HttpFoundation] enhance PdoSessionHandler| Q | A| ------------- | ---| Bug fix? | yes| New feature? | yes| BC breaks? | yes| Deprecations? | no| Tests pass? | yes| Fixed tickets |#5483,#2067,#2382,#9029| License | MIT0. [x] Continuation of locking implementation (#10908): Implement different locking strategies - `PdoSessionHandler::LOCK_TRANSACTIONAL` (default): Issues a real row lock but requires a transaction - `PdoSessionHandler::LOCK_ADVISORY`: app-level lock, safe as long as only the PdoSessionHandler accesses sessions, advantage is it does not require a transaction (not implemented for oracle or sqlsrv yet) - `PdoSessionHandler::LOCK_NONE`: basically what is was before, prone to race conditions, means the last session write wins1. [x] Save session data as binary: Encoding session data was definitely the wrong solution. Session data is binary text (esp. when using other session.serialize_handler) that must stay as-is and thus must also be safed in a binary column. Base64 encoding session data just decreses performance and increases storage costs and is semantically wrong because it does not have a character encoding.That saving null bytes in Posgres won't work on a character column is also documented > First, binary strings specifically allow storing octets of value zero and other "non-printable" octets (usually, octets outside the range 32 to 126). Character strings disallow zero octets, and also disallow any other octet values and sequences of octet values that are invalid according to the database's selected character set encoding.http://www.postgresql.org/docs/9.1/static/datatype-binary.html#DATATYPE-BINARY-TABLE2. [x] Implement lazy connections that are only opened when session is used by either passing a dsn string explicitly or falling back to session.save_path ini setting.Fixes#90293. [x] add a create table method that creates the correct table depending on database vendor. This makes the class self-documenting and standalone useable.5. [x] add lifetime column to session table which allows to have different lifetimes for each session6. [x] add isSessionExpired() method to be able to distinguish between a new session and one that expired due to inactivity, e.g. to display flash message to user7. [x] added upgrade and changelog notesCommits-------1bc6680 [HttpFoundation] implement different locking strategies for sessions6f5748e adjust sqlite table definition5978fcf added upgrade and changelog notes for PdoSessionHandler182a5d3 [HttpFoundation] add create table method to pdo session handlere79229d [HttpFoundation] allow different lifetime per sessionaf1bb1f add test for null byte in session data251238d [HttpFoundation] implement lazy connect for pdo session handler7dad54c [HttpFoundation] remove base64 encoding of session data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I guess it will not work at least for PostgreSQL, as thebytea fields are returned as streams for this driver:http://php.net/manual/en/ref.pdo-pgsql.connection.php
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Good catch, I know Travis-ci supports both PostgreSQL and MySQL so maybe we can add an general integration test to make sure all the drivers are working properly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ping@Tobion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@rybakit As I said, I only tested it with mysql and sqlite. I would appreciate if you can test it with postgres and provide a fix.
A unit test with postgres would help for the simple case. But for the locking behavior we would need functional tests with simultaneous connections which is not that easy to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@Tobion I've submitted a fix#12146 with simple unit tests. But I agree that to test it properly we need functional tests for each driver.
Btw, did you consider to splitPdoSessionHandler intoSqlitePdoSessionHandler,MysqlPdoSessionHandler etc. (or create adapters) to ease tuning and remove all thoseif ('sqlite|mysql|...' === $this->driver) checks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Yes I considered that. But then we would probably need to an abstract implementation with all the shared code and also change the pdoeessionhandler to be some sort of proxy, because you can still pass a pdo instance and then need to determine which concrete handler to use. Not sure if that makes things easier.
…with streams (rybakit)This PR was squashed before being merged into the 2.6-dev branch (closes#12146).Discussion----------[HttpFoundation] Fix PdoSessionHandler to work properly with streams| Q | A| ------------- | ---| Bug fix? | yes| New feature? | no| BC breaks? | no| Deprecations? | no| Tests pass? | yes| License | MITRef:#10931 (comment)Commits-------9531a2b [HttpFoundation] Fix PdoSessionHandler to work properly with streams
bestform commentedJul 22, 2015
@Tobion hey, i just wanted to come back at you about this and thank you for implementing our suggestions. It helped us immensely and made it possible to stay up to date with the latest symfony versions. Especially exposing the lock strategies made it possible that we can utilize our session implementation. So, just a quick thank you for your work and for listening and seeking a constructive discussion (see#10908) (I know, it has been a while, but as I just updated our system to be based on symfony 2.7 I realized just how much this change helped) |
Continuation of locking implementation ([HttpFoundation] implement session locking for PDO #10908): Implement different locking strategies
PdoSessionHandler::LOCK_TRANSACTIONAL(default): Issues a real row lock but requires a transactionPdoSessionHandler::LOCK_ADVISORY: app-level lock, safe as long as only the PdoSessionHandler accesses sessions, advantage is it does not require a transaction (not implemented for oracle or sqlsrv yet)PdoSessionHandler::LOCK_NONE: basically what is was before, prone to race conditions, means the last session write winsSave session data as binary: Encoding session data was definitely the wrong solution. Session data is binary text (esp. when using other session.serialize_handler) that must stay as-is and thus must also be safed in a binary column. Base64 encoding session data just decreses performance and increases storage costs and is semantically wrong because it does not have a character encoding.
That saving null bytes in Posgres won't work on a character column is also documented
Implement lazy connections that are only opened when session is used by either passing a dsn string explicitly or falling back to session.save_path ini setting.Fixes[HttpFoundation] PdoSessionHandler should connect to database only if session required #9029
add a create table method that creates the correct table depending on database vendor. This makes the class self-documenting and standalone useable.
add lifetime column to session table which allows to have different lifetimes for each session
add isSessionExpired() method to be able to distinguish between a new session and one that expired due to inactivity, e.g. to display flash message to user
added upgrade and changelog notes