Skip to content

[HttpFoundation] Precalculate expiry timestamp #21423

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

bcremer
Copy link
Contributor

@bcremer bcremer commented Jan 26, 2017

Removed timestamp and lifetime columns in favor of expiry column.
Based on the work done in #14625.

Fix #13955.

Q A
Branch? master
Bug fix? no
New feature? no
BC breaks? yes
Deprecations? no
Tests pass? yes
Fixed tickets #13955
License MIT
Doc PR TBD

Removed timestamp and lifetime columns in favor of expiry column.
Based on the work done in symfony#14625.

Fix symfony#13955.
@nicolas-grekas
Copy link
Member

nicolas-grekas commented Jan 29, 2017

But what about:

  • keeping the sess_time column asis, but put the expiry inside,
  • fill the lifetime column with zeros
  • trigger a deprecation when false !== $options['db_lifetime_col']
  • when $options['db_lifetime_col'] === false, don't use the lifetime_col at all

In 4.0, we could then just drop the lifetime_col, and keep the sess_time one as is (we don't need to rename it - and btw the DbalSessionHandler already calls it sess_time and puts the expiry inside).

@nicolas-grekas nicolas-grekas added this to the 3.x milestone Jan 29, 2017
@bcremer bcremer force-pushed the session-precalculate-expiry-timestamp branch from 4833d08 to 5342d67 Compare January 30, 2017 10:05
@@ -689,16 +762,13 @@ private function getMergeStatement($sessionId, $data, $maxlifetime)
$mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR);
$mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR);
$mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB);
$mergeStmt->bindParam(4, $maxlifetime, \PDO::PARAM_INT);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the lifetimeCol to 0 was inlined so we don't need different bind params here.

@@ -97,6 +97,7 @@ class PdoSessionHandler implements \SessionHandlerInterface

/**
* @var string Column for lifetime
* @deprecated since version 3.3, to be removed in 4.0
*/
private $lifetimeCol = 'sess_lifetime';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be changed to false? Right now the new behavior it opt-in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it must be opt-in, to keep BC by default

@bcremer bcremer force-pushed the session-precalculate-expiry-timestamp branch from 5342d67 to cc4e4a5 Compare January 30, 2017 12:03
@bcremer
Copy link
Contributor Author

bcremer commented Feb 9, 2017

@nicolas-grekas Anything still todo for me here to get this merged?

@nicolas-grekas
Copy link
Member

LGTM. @Tobion WDYT here?

@@ -8,7 +8,8 @@ CHANGELOG
disabling `Range` and `Content-Length` handling, switching to chunked encoding instead
* added the `Cookie::fromString()` method that allows to create a cookie from a
raw header string

* PdoSessionHandler: Deprecated the the `lifetime` column
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra "the".

@@ -193,6 +195,10 @@ public function __construct($pdoOrDsn = null, array $options = array())
$this->password = isset($options['db_password']) ? $options['db_password'] : $this->password;
$this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions;
$this->lockMode = isset($options['lock_mode']) ? $options['lock_mode'] : $this->lockMode;

if ($this->lifetimeCol !== false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yoda style (false !== ...) same below

@@ -193,6 +195,10 @@ public function __construct($pdoOrDsn = null, array $options = array())
$this->password = isset($options['db_password']) ? $options['db_password'] : $this->password;
$this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions;
$this->lockMode = isset($options['lock_mode']) ? $options['lock_mode'] : $this->lockMode;

if ($this->lifetimeCol !== false) {
@trigger_error('Using the "db_lifetime_col" option is deprecated since version 3.3 as it will be removed in 4.0.', E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should give more insights I think, eg
sprintf('The "%s" column is deprecated since version 3.3 and won't be used anymore in 4.0. Migrate your session database then set the "db_lifetime_col" option to false to opt-in for the new behavior.', $this->lifetimeCol);

I think this deserves an entry in the UPGRADE-3.3+4.0 files, with extended migration info/SQL.

break;
default:
throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver));
if ($this->lifetimeCol === false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yoda

} else {
switch ($this->driver) {
case 'mysql':
// We use varbinary for the ID column because it prevents unwanted conversions:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate comment can be removed IMHO

);
$updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
$updateStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
$updateStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lifetime should be set to zero so that migration is always possible ("time += lifetime")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you expand on what you mean here: where should it to 0?

@@ -389,7 +426,7 @@ public function close()
$this->gcCalled = false;

// delete the session records that have expired
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol < :time";
$sql = "DELETE FROM $this->table WHERE $this->timeCol < :time";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for BC, we should still consider lifetime when the colum is used, isn't it?

@@ -510,7 +547,7 @@ private function doRead($sessionId)
$sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM);

if ($sessionRows) {
if ($sessionRows[0][1] + $sessionRows[0][2] < time()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, for BC, we should still use any values in lifetime?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, the logic must be kept for old session data

"ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)";
break;

if ($this->lifetimeCol === false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yoda

@@ -215,7 +215,8 @@ public function testReadingRequiresExactlySameId()
*/
public function testWriteDifferentSessionIdThanRead()
{
$storage = new PdoSessionHandler($this->getMemorySqlitePdo());
$storage = new PdoSessionHandler($this->getMemorySqlitePdo(), array('db_lifetime_col' => false));
$storage->open('', 'sid');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added by mistake?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in #21857

@Tobion
Copy link
Contributor

Tobion commented Feb 9, 2017

Approach seems ok but it's not BC yet.
Also there is no index on the time column yet. So I don't think there is any gain as the DB still needs to do a full table scan for gc.

@nicolas-grekas
Copy link
Member

@bcremer do you need help - or just a bit more time? please advise :)

@bcremer
Copy link
Contributor Author

bcremer commented Feb 18, 2017

@nicolas-grekas It's not my top priority right know. If anybody likes to pickup please do :)

Will get back onto it otherwise in a few days or so.

@robfrawley
Copy link
Contributor

robfrawley commented Feb 18, 2017

@bcremer I'm happy to help get this finished up; should I clone your branch, make the required changes, and open a new PR, or would you prefer (and do you have the time) to accept pull requests against your branch (this pull request).

@nicolas-grekas
Copy link
Member

@robfrawley please go with a new PR on your own, keeping the first commit from @bcremer, OK?

@robfrawley
Copy link
Contributor

@nicolas-grekas Sounds good, will take a look and get something together for tomorrow.

@robfrawley
Copy link
Contributor

robfrawley commented Mar 3, 2017

@nicolas-grekas Nevermind my original comment; it was my mistake, though there are some BC breaks in this PR. I've already taken care of the style changes (like the yoda-style comments and others) requested. Will be opening up a new PR shortly, but before doing so, I wanted to ask if you guys would like BC unit tests created with the proper @group and @expectedDeprecation annotations, like:

/**
 * @group legacy
 * @expectedDeprecation The "%s" column is deprecated since version 3.3 and won't be used anymore in 4.0. Migrate your session database then set the "db_lifetime_col" option to false to opt-in for the new behavior.
 */

@nicolas-grekas
Copy link
Member

BC is a requirement yes, and legacy and non-legacy tests would be great yes.

@xabbuh
Copy link
Member

xabbuh commented Mar 4, 2017

closing in favour of #21857

@xabbuh xabbuh closed this Mar 4, 2017
@nicolas-grekas nicolas-grekas removed this from the 3.x milestone Mar 24, 2017
@nicolas-grekas nicolas-grekas modified the milestones: 3.3, 3.x Mar 24, 2017
nicolas-grekas added a commit that referenced this pull request Aug 20, 2019
… (azjezz)

This PR was merged into the 4.4 branch.

Discussion
----------

[HttpFoundation] Precalculate session expiry timestamp

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #13955, #21423, #14625
| License       | MIT

Continued work from the original PR #21423 / #21857

Commits
-------

066000a [HttpFoundation] Precalculate session expiry timestamp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Session][3.0] PdoSessionHandler: precalculate expiry timestamp
7 participants