delete conflicting episode action if current episode actions updates to same episode url

This commit is contained in:
thrillfall 2023-02-24 20:48:53 +01:00
parent ee84d2f670
commit bf8fee14e3
3 changed files with 65 additions and 40 deletions

View File

@ -69,7 +69,17 @@ class EpisodeActionSaver
$this->ensureGuidDoesNotGetNulledWithOldData($episodeActionToUpdate, $episodeActionEntity); $this->ensureGuidDoesNotGetNulledWithOldData($episodeActionToUpdate, $episodeActionEntity);
try {
return $this->episodeActionWriter->update($episodeActionEntity); return $this->episodeActionWriter->update($episodeActionEntity);
} catch (UniqueConstraintViolationException $uniqueConstraintViolationException) {
$this->deleteConflictingEpisodeAction($episodeActionEntity, $userId);
} catch (Exception $exception) {
if ($exception->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
$this->deleteConflictingEpisodeAction($episodeActionEntity, $userId);
}
}
return $this->episodeActionWriter->update($episodeActionEntity);
} }
private function ensureGuidDoesNotGetNulledWithOldData(EpisodeAction $episodeActionToUpdate, EpisodeActionEntity $episodeActionEntity): void private function ensureGuidDoesNotGetNulledWithOldData(EpisodeAction $episodeActionToUpdate, EpisodeActionEntity $episodeActionEntity): void
@ -115,4 +125,17 @@ class EpisodeActionSaver
return $episodeAction; return $episodeAction;
} }
/**
* @param EpisodeActionEntity $episodeActionEntity
* @param string $userId
* @return void
*/
private function deleteConflictingEpisodeAction(EpisodeActionEntity $episodeActionEntity, string $userId): void
{
$collidingEpisodeActionId = $this->episodeActionRepository->findByEpisodeUrl($episodeActionEntity->getGuid(), $userId)->getId();
if ($collidingEpisodeActionId !== $episodeActionEntity->getId()) {
$this->episodeActionRepository->deleteEpisodeActionByEpisodeUrl($episodeActionEntity->getGuid(), $userId);
}
}
} }

View File

@ -52,6 +52,11 @@ class EpisodeActionRepository {
); );
} }
public function deleteEpisodeActionByEpisodeUrl(string $episodeUrl, string $userId) : void {
$episodeAction = $this->episodeActionMapper->findByEpisodeUrl($episodeUrl, $userId);
$this->episodeActionMapper->delete($episodeAction);
}
private function mapEntityToEpisodeAction(EpisodeActionEntity $episodeActionEntity): EpisodeAction private function mapEntityToEpisodeAction(EpisodeActionEntity $episodeActionEntity): EpisodeAction
{ {
return new EpisodeAction( return new EpisodeAction(

View File

@ -18,13 +18,14 @@ class EpisodeActionSaverGuidBackwardCompatibilityTest extends TestCase
private \OCP\AppFramework\IAppContainer $container; private \OCP\AppFramework\IAppContainer $container;
public function setUp(): void { public function setUp(): void
{
parent::setUp(); parent::setUp();
$app = new App('gpoddersync'); $app = new App('gpoddersync');
$this->container = $app->getContainer(); $this->container = $app->getContainer();
} }
public function testUpdateWithoutGuidDoesNotNullGuid() : void public function testUpdateWithoutGuidDoesNotNullGuid(): void
{ {
/** @var EpisodeActionSaver $episodeActionSaver */ /** @var EpisodeActionSaver $episodeActionSaver */
$episodeActionSaver = $this->container->get(EpisodeActionSaver::class); $episodeActionSaver = $this->container->get(EpisodeActionSaver::class);
@ -46,7 +47,7 @@ class EpisodeActionSaverGuidBackwardCompatibilityTest extends TestCase
self::assertNotNull($savedEpisodeActionEntityWithoutGuidFromOldDevice->getGuid()); self::assertNotNull($savedEpisodeActionEntityWithoutGuidFromOldDevice->getGuid());
} }
public function testDoNotFailToUpdateEpisodeActionByGuidIfThereIsAnotherWithTheSameValueForEpisodeUrl() : void public function testDoNotFailToUpdateEpisodeActionByGuidIfThereIsAnotherWithTheSameValueForEpisodeUrl(): void
{ {
//arrange //arrange
/** @var EpisodeActionSaver $episodeActionSaver */ /** @var EpisodeActionSaver $episodeActionSaver */
@ -78,19 +79,15 @@ class EpisodeActionSaverGuidBackwardCompatibilityTest extends TestCase
$episodeActionRepository = $this->container->get(EpisodeActionRepository::class); $episodeActionRepository = $this->container->get(EpisodeActionRepository::class);
$this->assertSame(100, $episodeActionRepository->findByGuid($urlWithParameter, self::USER_ID_0)->getPosition()); $this->assertSame(100, $episodeActionRepository->findByGuid($urlWithParameter, self::USER_ID_0)->getPosition());
try {
//act //act
$episodeActionSaver->saveEpisodeActions( $episodeActionSaver->saveEpisodeActions(
[["podcast" => $podcastUrl, "episode" => $urlWithParameter, "guid" => $urlWithParameter, "action" => "PLAY", "timestamp" => "2021-08-22T23:58:56", "started" => 35, "position" => 100, "total" => 2252]], [["podcast" => $podcastUrl, "episode" => $urlWithParameter, "guid" => $urlWithParameter, "action" => "PLAY", "timestamp" => "2021-08-22T23:58:56", "started" => 35, "position" => 100, "total" => 2252]],
self::USER_ID_0 self::USER_ID_0
)[0]; )[0];
$this->assertSame(1,2); //assert
/** @var EpisodeActionRepository $episodeActionRepository */
} catch (\Exception $exception) { $episodeActionRepository = $this->container->get(EpisodeActionRepository::class);
$this->assertStringContainsString("SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry", $exception->getMessage()); $this->assertSame(100, $episodeActionRepository->findByGuid($urlWithParameter, self::USER_ID_0)->getPosition());
$this->assertStringContainsString("for key 'gpodder_episode_user_id'", $exception->getMessage());
}
} }
} }