diff --git a/lib/Exceptions/RoomLockedException.php b/lib/Exceptions/RoomLockedException.php new file mode 100644 index 00000000000..69e43d92ec0 --- /dev/null +++ b/lib/Exceptions/RoomLockedException.php @@ -0,0 +1,13 @@ +cache = $cacheFactory->createLocking('talkroom_'); + } + + /** + * @throws RoomLockedException + */ + protected function updateRoomPropertyWithLock(Room $room, string $property, int $value): void { + $cacheKey = $this->cache instanceof NullCache ? null : (string)$room->getId(); + if ($cacheKey !== null) { + $this->cache->add($cacheKey, $this->requestId->getId(), 30); + $sleeps = 0; + while ($this->cache->get($cacheKey) !== $this->requestId->getId()) { + if ($sleeps > 30) { + throw new RoomLockedException(); + } + usleep(10_000); + $sleeps++; + $this->cache->add($cacheKey, $this->requestId->getId(), 30); + } + + if ($sleeps !== 0) { + $room = $this->manager->getRoomById($room->getId()); + } + } + + $update = $this->db->getQueryBuilder(); + $update->update('talk_rooms') + ->set($property, $update->createNamedParameter($value, IQueryBuilder::PARAM_INT)) + ->set('properties_version', $update->func()->add('properties_version', $update->expr()->literal(1, IQueryBuilder::PARAM_INT))) + ->where($update->expr()->eq('id', $update->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) + ->andWhere($update->expr()->eq('properties_version', $update->createNamedParameter($room->getPropertiesVersion(), IQueryBuilder::PARAM_INT))); + $update->executeStatement(); + + $room->setPropertiesVersion($room->getPropertiesVersion() + 1); + if ($cacheKey !== null) { + $this->cache->cad($cacheKey, $this->requestId->getId()); + } } /** @@ -213,11 +259,11 @@ public function setDefaultPermissions(Room $room, int $permissions): void { // Reset custom user permissions to default $this->participantService->updateAllPermissions($room, Attendee::PERMISSIONS_MODIFY_SET, Attendee::PERMISSIONS_DEFAULT); - $update = $this->db->getQueryBuilder(); - $update->update('talk_rooms') - ->set('default_permissions', $update->createNamedParameter($newPermissions, IQueryBuilder::PARAM_INT)) - ->where($update->expr()->eq('id', $update->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))); - $update->executeStatement(); + try { + $this->updateRoomPropertyWithLock($room, 'default_permissions', $newPermissions); + } catch (RoomLockedException $e) { + throw new InvalidArgumentException('locked'); + } $room->setDefaultPermissions($newPermissions);