Skip to content

Commit 37a0fec

Browse files
committed
fix: Delete inactive sessions in one query
Signed-off-by: Julius Härtl <[email protected]>
1 parent 2478836 commit 37a0fec

File tree

2 files changed

+118
-18
lines changed

2 files changed

+118
-18
lines changed

lib/Db/SessionMapper.php

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,29 @@ public function findAllInactive() {
9999
return $this->findEntities($qb);
100100
}
101101

102-
public function deleteInactiveWithoutSteps($documentId = -1) {
103-
$qb = $this->db->getQueryBuilder();
104-
$qb->select('session_id')
105-
->from('text_steps');
102+
public function deleteInactiveWithoutSteps(?int $documentId = null): int {
103+
$selectSubQuery = $this->db->getQueryBuilder();
104+
$selectSubQuery->select('s.id')
105+
->from('text_sessions', 's')
106+
->leftJoin('s', 'text_steps', 'st', $selectSubQuery->expr()->eq('st.session_id', 's.id'))
107+
->where($selectSubQuery->expr()->lt('last_contact', $selectSubQuery->createParameter('lastContact')))
108+
->andWhere($selectSubQuery->expr()->isNull('st.id'));
106109
if ($documentId !== null) {
107-
$qb->where($qb->expr()->eq('document_id', $qb->createNamedParameter($documentId)));
110+
$selectSubQuery->andWhere($selectSubQuery->expr()->eq('s.document_id', $selectSubQuery->createParameter('documentId')));
108111
}
109-
$result = $qb
110-
->groupBy('session_id')
111-
->execute();
112-
$activeSessions = $result->fetchAll(\PDO::FETCH_COLUMN);
113-
$result->closeCursor();
114112

115113
$qb = $this->db->getQueryBuilder();
116-
$qb->delete($this->getTableName());
117-
$qb->where($qb->expr()->lt('last_contact', $qb->createNamedParameter(time() - SessionService::SESSION_VALID_TIME)));
118-
if ($documentId !== null) {
119-
$qb->andWhere($qb->expr()->eq('document_id', $qb->createNamedParameter($documentId)));
120-
}
121-
$qb->andWhere($qb->expr()->notIn('id', $qb->createNamedParameter($activeSessions, IQueryBuilder::PARAM_INT_ARRAY)));
122-
return $qb->execute();
114+
$qb->delete($this->getTableName())
115+
->where($qb->expr()->in('id', $qb->createFunction($selectSubQuery->getSQL())));
116+
$qb->setParameters([
117+
'lastContact' => time() - SessionService::SESSION_VALID_TIME,
118+
'documentId' => $documentId,
119+
]);
120+
121+
return $qb->executeStatement();
123122
}
124123

125-
public function deleteByDocumentId($documentId) {
124+
public function deleteByDocumentId($documentId): int {
126125
$qb = $this->db->getQueryBuilder();
127126
$qb->delete($this->getTableName())
128127
->where($qb->expr()->eq('document_id', $qb->createNamedParameter($documentId)));
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
namespace OCA\Text\Db;
4+
5+
/**
6+
* @group DB
7+
*/
8+
class SessionMapperTest extends \Test\TestCase {
9+
10+
private SessionMapper $sessionMapper;
11+
private StepMapper $stepMapper;
12+
13+
public function setUp(): void {
14+
parent::setUp();
15+
$this->sessionMapper = \OCP\Server::get(SessionMapper::class);
16+
$this->stepMapper = \OCP\Server::get(StepMapper::class);
17+
18+
}
19+
20+
public function testDeleteInactiveWithoutSteps() {
21+
$this->sessionMapper->deleteByDocumentId(1);
22+
$this->sessionMapper->deleteByDocumentId(2);
23+
$this->sessionMapper->insert(Session::fromParams([
24+
'userId' => 'admin',
25+
'documentId' => 1,
26+
'lastContact' => 1337,
27+
'token' => uniqid(),
28+
'color' => '00ff00',
29+
]));
30+
$this->sessionMapper->insert(Session::fromParams([
31+
'userId' => 'admin',
32+
'documentId' => 2,
33+
'lastContact' => 1337,
34+
'token' => uniqid(),
35+
'color' => '00ff00',
36+
]));
37+
$this->sessionMapper->deleteInactiveWithoutSteps(1);
38+
self::assertCount(0, $this->sessionMapper->findAll(1));
39+
self::assertCount(1, $this->sessionMapper->findAll(2));
40+
$this->sessionMapper->deleteInactiveWithoutSteps();
41+
self::assertCount(0, $this->sessionMapper->findAll(2));
42+
}
43+
44+
public function testDeleteInactiveWithoutStepsKeep() {
45+
$this->stepMapper->deleteAll(1);
46+
$this->sessionMapper->deleteByDocumentId(1);
47+
$this->sessionMapper->deleteByDocumentId(2);
48+
49+
$s1 = $this->sessionMapper->insert(Session::fromParams([
50+
'userId' => 'admin',
51+
'documentId' => 1,
52+
'lastContact' => 1337,
53+
'token' => uniqid(),
54+
'color' => '00ff00',
55+
]));
56+
$s2 = $this->sessionMapper->insert(Session::fromParams([
57+
'userId' => 'admin',
58+
'documentId' => 2,
59+
'lastContact' => 1337,
60+
'token' => uniqid(),
61+
'color' => '00ff00',
62+
]));
63+
$this->stepMapper->insert(Step::fromParams([
64+
'sessionId' => $s1->getId(),
65+
'documentId' => 1,
66+
'data' => 'YJSDATA',
67+
'version' => 1,
68+
]));
69+
self::assertCount(1, $this->sessionMapper->findAll(1));
70+
71+
$this->sessionMapper->deleteInactiveWithoutSteps(1);
72+
self::assertCount(1, $this->sessionMapper->findAll(1));
73+
self::assertCount(1, $this->sessionMapper->findAll(2));
74+
75+
$this->sessionMapper->deleteInactiveWithoutSteps();
76+
self::assertCount(1, $this->sessionMapper->findAll(1));
77+
self::assertCount(0, $this->sessionMapper->findAll(2));
78+
}
79+
80+
public function testDeleteInactiveWithoutStepsMultiple() {
81+
$this->sessionMapper->deleteByDocumentId(1);
82+
83+
$count = 1010;
84+
for ($i = 0;$i < $count;$i++) {
85+
$this->sessionMapper->insert(Session::fromParams([
86+
'userId' => 'admin',
87+
'documentId' => 1,
88+
'lastContact' => 1337,
89+
'token' => uniqid(),
90+
'color' => '00ff00',
91+
]));
92+
}
93+
94+
self::assertCount($count, $this->sessionMapper->findAll(1));
95+
96+
$deleted = $this->sessionMapper->deleteInactiveWithoutSteps();
97+
self::assertEquals($count, $deleted);
98+
99+
self::assertCount(0, $this->sessionMapper->findAll(1));
100+
}
101+
}

0 commit comments

Comments
 (0)