8000 feature #11668 [HttpFoundation] MongoDbSessionHandler supports auto e… · symfony/symfony@73c7eae · GitHub
[go: up one dir, main page]

Skip to content

Commit 73c7eae

Browse files
feature #11668 [HttpFoundation] MongoDbSessionHandler supports auto expiry via configurable expiry_field (catchamonkey)
This PR was merged into the 2.6-dev branch. Discussion ---------- [HttpFoundation] MongoDbSessionHandler supports auto expiry via configurable expiry_field | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #11508 | License | MIT | Doc PR | no This PR applies #11510 to master instead of 2.3 Should be merged on master: - [x] after #11667 is merged to 2.3 - [x] and after 2.3 is merged back to master Commits ------- beca900 [HttpFoundation] MongoDbSessionHandler supports auto expiry via configurable expiry_field
2 parents 7f38207 + beca900 commit 73c7eae

File tree

2 files changed

+94
-10
lines changed

2 files changed

+94
-10
lines changed

src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ public function __construct($mongo, array $options)
6262
$this->mongo = $mongo;
6363

6464
$this->options = array_merge(array(
65-
'id_field' => '_id',
66-
'data_field' => 'data',
67-
'time_field' => 'time',
65+
'id_field' => '_id',
66+
'data_field' => 'data',
67+
'time_field' => 'time',
68+
'expiry_field' => false,
6869
), $options);
6970
}
7071

@@ -109,6 +110,9 @@ public function gc($maxlifetime)
109110
*
110111
* See: http://docs.mongodb.org/manual/tutorial/expire-data/
111112
*/
113+
if (false !== $this->options['expiry_field']) {
114+
return true;
115+
}
112116
$time = new \MongoDate(time() - $maxlifetime);
113117

114118
$this->getCollection()->remove(array(
@@ -123,12 +127,27 @@ public function gc($maxlifetime)
123127
*/
124128
public function write($sessionId, $data)
125129
{
130+
$fields = array(
131+
$this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
132+
$this->options['time_field'] => new \MongoDate(),
133+
);
134+
135+
/* Note: As discussed in the gc method of this class. You can utilise
136+
* TTL collections in MongoDB 2.2+
137+
* We are setting the "expiry_field" as part of the write operation here
138+
* You will need to create the index on your collection that expires documents
139+
* at that time
140+
* e.g.
141+
* db.MySessionCollection.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
142+
*/
143+
if (false !== $this->options['expiry_field']) {
144+
$expiry = new \MongoDate(time() + (int) ini_get('session.gc_maxlifetime'));
145+
$fields[$this->options['expiry_field']] = $expiry;
146+
}
147+
126148
$this->getCollection()->update(
127149
array($this->options['id_field'] => $sessionId),
128-
array('$set' => array(
129-
$this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
130-
$this->options['time_field'] => new \MongoDate(),
131-
)),
150+
array('$set' => $fields),
132151
array('upsert' => true, 'multiple' => false)
133152
);
134153

src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected function setUp()
4141
'data_field' => 'data',
4242
'time_field' => 'time',
4343
'database' => 'sf2-test',
44-
'collection' => 'session-test'
44+
'collection' => 'session-test',
4545
);
4646

4747
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
@@ -100,6 +100,45 @@ public function testWrite()
100100
$that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
101101
}
102102

103+
public function testWriteWhenUsingExpiresField()
104+
{
105+
$this->options = array(
106+
'id_field' => '_id',
107+
'data_field' => 'data',
108+
'time_field' => 'time',
109+
'database' => 'sf2-test',
110+
'collection' => 'session-test',
111+
'expiry_field' => 'expiresAt'
112+
);
113+
114+
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
115+
116+
$collection = $this->createMongoCollectionMock();
117+
118+
$this->mongo->expects($this->once())
119+
->method('selectCollection')
120+
->with($this->options['database'], $this->options['collection'])
121+
->will($this->returnValue($collection));
122+
123+
$that = $this;
124+
$data = array();
125+
126+
$collection->expects($this->once())
127+
->method('update')
128+
->will($this->returnCallback(function ($criteria, $updateData, $options) use ($that, &$data) {
129+
$that->assertEquals(array($that->options['id_field'] => 'foo'), $criteria);
130+
$that->assertEquals(array('upsert' => true, 'multiple' => false), $options);
131+
132+
$data = $updateData['$set'];
133+
}));
134+
135+
$this->assertTrue($this->storage->write('foo', 'bar'));
136+
137+
$this->assertEquals('bar', $data[$this->options['data_field']]->bin);
138+
$that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
139+
$that->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]);
140+
}
141+
103142
public function testReplaceSessionData()
104143
{
105144
$collection = $this->createMongoCollectionMock();
@@ -154,10 +193,36 @@ public function testGc()
154193
->method('remove')
155194
->will($this->returnCallback(function ($criteria) use ($that) {
156195
$that->assertInstanceOf('MongoDate', $criteria[$that->options['time_field']]['$lt']);
157-
$that->assertGreaterThanOrEqual(time() - -1, $criteria[$that->options['time_field']]['$lt']->sec);
196+
$that->assertGreaterThanOrEqual(time() - 1, $criteria[$that->options['time_field']]['$lt']->sec);
158197
}));
159198

160-
$this->assertTrue($this->storage->gc(-1));
199+
$this->assertTrue($this->storage->gc(1));
200+
}
201+
202+
public function testGcWhenUsingExpiresField()
203+
{
204+
$this->options = array(
205+
'id_field' => '_id',
206+
'data_field' => 'data',
207+
'time_field' => 'time',
208+
'database' => 'sf2-test',
209+
'collection' => 'session-test',
210+
'expiry_field' => 'expiresAt'
211+
);
212+
213+
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
214+
215+
$collection = $this->createMongoCollectionMock();
216+
217+
$this->mongo->expects($this->never())
218+
->method('selectCollection');
219+
220+
$that = $this;
221+
222+
$collection->expects($this->never())
223+
->method('remove');
224+
225+
$this->assertTrue($this->storage->gc(1));
161226
}
162227

163228
public function testGetConnection()

0 commit comments

Comments
 (0)
0