Permalink
Browse files

If a PDOException is thrown, try again.

This can occur if the exists check returns no rows, but before this
request inserts into the database a _different_ thread inserts a
session record.
  • Loading branch information...
AD7six committed Jan 23, 2015
1 parent e86365c commit 51bd1d0a2b2d8e6086ec2324ed9c332c9e467a89
@@ -103,6 +103,9 @@ public function read($id) {
/**
* Helper function called on write for database sessions.
*
* Will retry, once, if the save triggers a PDOException which
* can happen if a race condition is encountered
*
* @param int $id ID that uniquely identifies session in database
* @param mixed $data The value of the data to be saved.
* @return bool True for successful write, false otherwise.
@@ -114,7 +117,12 @@ public function write($id, $data) {
$expires = time() + $this->_timeout;
$record = compact('id', 'data', 'expires');
$record[$this->_model->primaryKey] = $id;
return $this->_model->save($record);
try {
return $this->_model->save($record);
} catch (PDOException $e) {
return $this->_model->save($record);
}
}
/**
@@ -207,10 +207,42 @@ public function testConcurrentInsert() {
);
Configure::write('Session.handler.model', 'MockedSessionTestModel');
$mockedModel->expects($this->any())
$counter = 0;
// First save
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(false));
// First validate
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(false));
// Second save
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(false));
// Second validate
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(false));
// Second save retry
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(true));
// Second validate retry
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(false));
// Datasource exists check
$mockedModel->expects($this->at($counter++))
->method('exists')
->will($this->returnValue(true));
$this->storage = new DatabaseSession();
$this->storage->write('foo', 'Some value');

0 comments on commit 51bd1d0

Please sign in to comment.