fix(user_status): Avoid unique constraint violations from parallel heartbeats and GET requests

Signed-off-by: Joas Schilling <coding@schilljs.com>
pull/53198/head
Joas Schilling 2025-05-30 08:53:18 +07:00
parent 52299ba9f6
commit f3a26c5f89
No known key found for this signature in database
GPG Key ID: F72FA5B49FFA96B0
1 changed files with 16 additions and 4 deletions

@ -167,7 +167,7 @@ class StatusService {
$userStatus->setIsBackup(false);
if ($userStatus->getId() === null) {
return $this->mapper->insert($userStatus);
return $this->insertWithoutThrowingUniqueConstrain($userStatus);
}
return $this->mapper->update($userStatus);
@ -211,7 +211,7 @@ class StatusService {
$userStatus->setStatusMessageTimestamp($this->timeFactory->now()->getTimestamp());
if ($userStatus->getId() === null) {
return $this->mapper->insert($userStatus);
return $this->insertWithoutThrowingUniqueConstrain($userStatus);
}
return $this->mapper->update($userStatus);
@ -313,7 +313,7 @@ class StatusService {
if ($userStatus->getId() !== null) {
return $this->mapper->update($userStatus);
}
return $this->mapper->insert($userStatus);
return $this->insertWithoutThrowingUniqueConstrain($userStatus);
}
/**
@ -360,7 +360,7 @@ class StatusService {
$userStatus->setStatusMessageTimestamp($this->timeFactory->now()->getTimestamp());
if ($userStatus->getId() === null) {
return $this->mapper->insert($userStatus);
return $this->insertWithoutThrowingUniqueConstrain($userStatus);
}
return $this->mapper->update($userStatus);
@ -584,4 +584,16 @@ class StatusService {
// For users that matched restore the previous status
$this->mapper->restoreBackupStatuses($restoreIds);
}
protected function insertWithoutThrowingUniqueConstrain(UserStatus $userStatus): UserStatus {
try {
return $this->mapper->insert($userStatus);
} catch (Exception $e) {
// Ignore if a parallel request already set the status
if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
throw $e;
}
}
return $userStatus;
}
}