Skip to content

Commit 5fcbb1c

Browse files
committed
Create the backup user status in 1 query instead of 3
Signed-off-by: Joas Schilling <coding@schilljs.com>
1 parent 658547d commit 5fcbb1c

File tree

3 files changed

+50
-58
lines changed

3 files changed

+50
-58
lines changed

apps/user_status/lib/Db/UserStatusMapper.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,23 @@ public function deleteByIds(array $ids): void {
184184
$qb->executeStatement();
185185
}
186186

187+
/**
188+
* @param string $userId
189+
* @return bool
190+
* @throws \OCP\DB\Exception
191+
*/
192+
public function createBackupStatus(string $userId): bool {
193+
// Prefix user account with an underscore because user_id is marked as unique
194+
// in the table. Starting a username with an underscore is not allowed so this
195+
// shouldn't create any trouble.
196+
$qb = $this->db->getQueryBuilder();
197+
$qb->update($this->tableName)
198+
->set('is_backup', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
199+
->set('user_id', $qb->createNamedParameter('_' . $userId))
200+
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
201+
return $qb->executeStatement() > 0;
202+
}
203+
187204
public function restoreBackupStatuses(array $ids): void {
188205
$qb = $this->db->getQueryBuilder();
189206
$qb->update($this->tableName)

apps/user_status/lib/Service/StatusService.php

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use OCA\UserStatus\Exception\StatusMessageTooLongException;
3636
use OCP\AppFramework\Db\DoesNotExistException;
3737
use OCP\AppFramework\Utility\ITimeFactory;
38+
use OCP\DB\Exception;
3839
use OCP\IConfig;
3940
use OCP\IUser;
4041
use OCP\UserStatus\IUserStatus;
@@ -435,30 +436,18 @@ private function addDefaultMessage(UserStatus $status): void {
435436
}
436437

437438
/**
438-
* @return bool false iff there is already a backup. In this case abort the procedure.
439+
* @return bool false if there is already a backup. In this case abort the procedure.
439440
*/
440441
public function backupCurrentStatus(string $userId): bool {
441442
try {
442-
$this->mapper->findByUserId($userId, true);
443-
return false;
444-
} catch (DoesNotExistException $ex) {
445-
// No backup already existing => Good
446-
}
447-
448-
try {
449-
$userStatus = $this->mapper->findByUserId($userId);
450-
} catch (DoesNotExistException $ex) {
451-
// if there is no status to backup, just return
443+
$this->mapper->createBackupStatus($userId);
452444
return true;
445+
} catch (Exception $ex) {
446+
if ($ex->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
447+
return false;
448+
}
449+
throw $ex;
453450
}
454-
455-
$userStatus->setIsBackup(true);
456-
// Prefix user account with an underscore because user_id is marked as unique
457-
// in the table. Starting an username with an underscore is not allowed so this
458-
// shouldn't create any trouble.
459-
$userStatus->setUserId('_' . $userStatus->getUserId());
460-
$this->mapper->update($userStatus);
461-
return true;
462451
}
463452

464453
public function revertUserStatus(string $userId, string $messageId, string $status): void {

apps/user_status/tests/Unit/Service/StatusServiceTest.php

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
*/
2727
namespace OCA\UserStatus\Tests\Service;
2828

29+
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
30+
use OC\DB\Exceptions\DbalException;
2931
use OCA\UserStatus\Db\UserStatus;
3032
use OCA\UserStatus\Db\UserStatusMapper;
3133
use OCA\UserStatus\Exception\InvalidClearAtException;
@@ -38,6 +40,7 @@
3840
use OCA\UserStatus\Service\StatusService;
3941
use OCP\AppFramework\Db\DoesNotExistException;
4042
use OCP\AppFramework\Utility\ITimeFactory;
43+
use OCP\DB\Exception;
4144
use OCP\IConfig;
4245
use OCP\UserStatus\IUserStatus;
4346
use Test\TestCase;
@@ -723,53 +726,36 @@ public function testCleanStatusCleanedAlready(): void {
723726
parent::invokePrivate($this->service, 'cleanStatus', [$status]);
724727
}
725728

726-
public function testBackupWorkingHasBackupAlready() {
727-
$status = new UserStatus();
728-
$status->setStatus(IUserStatus::ONLINE);
729-
$status->setStatusTimestamp(1337);
730-
$status->setIsUserDefined(true);
731-
$status->setMessageId('meeting');
732-
$status->setUserId('john');
733-
$status->setIsBackup(true);
734-
729+
public function testBackupWorkingHasBackupAlready(): void {
730+
$p = $this->createMock(UniqueConstraintViolationException::class);
731+
$e = DbalException::wrap($p);
735732
$this->mapper->expects($this->once())
736-
->method('findByUserId')
737-
->with('john', true)
738-
->willReturn($status);
733+
->method('createBackupStatus')
734+
->with('john')
735+
->willThrowException($e);
739736

740-
$this->service->backupCurrentStatus('john');
737+
$this->assertFalse($this->service->backupCurrentStatus('john'));
741738
}
742739

743-
public function testBackup() {
744-
$currentStatus = new UserStatus();
745-
$currentStatus->setStatus(IUserStatus::ONLINE);
746-
$currentStatus->setStatusTimestamp(1337);
747-
$currentStatus->setIsUserDefined(true);
748-
$currentStatus->setMessageId('meeting');
749-
$currentStatus->setUserId('john');
750-
751-
$this->mapper->expects($this->at(0))
752-
->method('findByUserId')
753-
->with('john', true)
754-
->willThrowException(new DoesNotExistException(''));
755-
$this->mapper->expects($this->at(1))
756-
->method('findByUserId')
757-
->with('john', false)
758-
->willReturn($currentStatus);
740+
public function testBackupThrowsOther(): void {
741+
$e = new Exception('', Exception::REASON_CONNECTION_LOST);
742+
$this->mapper->expects($this->once())
743+
->method('createBackupStatus')
744+
->with('john')
745+
->willThrowException($e);
759746

760-
$newBackupStatus = new UserStatus();
761-
$newBackupStatus->setStatus(IUserStatus::ONLINE);
762-
$newBackupStatus->setStatusTimestamp(1337);
763-
$newBackupStatus->setIsUserDefined(true);
764-
$newBackupStatus->setMessageId('meeting');
765-
$newBackupStatus->setUserId('_john');
766-
$newBackupStatus->setIsBackup(true);
747+
$this->expectException(Exception::class);
748+
$this->service->backupCurrentStatus('john');
749+
}
767750

751+
public function testBackup(): void {
752+
$e = new Exception('', Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION);
768753
$this->mapper->expects($this->once())
769-
->method('update')
770-
->with($newBackupStatus);
754+
->method('createBackupStatus')
755+
->with('john')
756+
->willReturn(true);
771757

772-
$this->service->backupCurrentStatus('john');
758+
$this->assertTrue($this->service->backupCurrentStatus('john'));
773759
}
774760

775761
public function testRevertMultipleUserStatus(): void {

0 commit comments

Comments
 (0)