]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Fix retrying update on sql serialization conflict
authorChocobozzz <me@florianbigard.com>
Tue, 14 Feb 2023 07:59:27 +0000 (08:59 +0100)
committerChocobozzz <me@florianbigard.com>
Tue, 14 Feb 2023 08:03:22 +0000 (09:03 +0100)
server/controllers/api/video-channel.ts
server/controllers/api/video-playlist.ts
server/controllers/api/videos/update.ts
server/helpers/database-utils.ts
server/lib/activitypub/actors/updater.ts
server/lib/activitypub/videos/updater.ts

index d7c92952a516de29ea417a2a3e1790c6ae0e7750..5b9fb794ae9bb94a7afba909efc060aa59e34a48 100644 (file)
@@ -273,7 +273,6 @@ async function addVideoChannel (req: express.Request, res: express.Response) {
 
 async function updateVideoChannel (req: express.Request, res: express.Response) {
   const videoChannelInstance = res.locals.videoChannel
-  const videoChannelFieldsSave = videoChannelInstance.toJSON()
   const oldVideoChannelAuditKeys = new VideoChannelAuditView(videoChannelInstance.toFormattedJSON())
   const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
   let doBulkVideoUpdate = false
@@ -309,10 +308,9 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
   } catch (err) {
     logger.debug('Cannot update the video channel.', { err })
 
-    // Force fields we want to update
     // If the transaction is retried, sequelize will think the object has not changed
-    // So it will skip the SQL request, even if the last one was ROLLBACKed!
-    resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
+    // So we need to restore the previous fields
+    resetSequelizeInstance(videoChannelInstance)
 
     throw err
   }
index 947f7ca7787de463948e9b48a311c3b2adb57489..bcb60e26513ab46a21103c2abbdb837b60779acb 100644 (file)
@@ -210,7 +210,6 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
 
 async function updateVideoPlaylist (req: express.Request, res: express.Response) {
   const videoPlaylistInstance = res.locals.videoPlaylistFull
-  const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON()
   const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate
 
   const wasPrivatePlaylist = videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE
@@ -275,10 +274,9 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response)
   } catch (err) {
     logger.debug('Cannot update the video playlist.', { err })
 
-    // Force fields we want to update
     // If the transaction is retried, sequelize will think the object has not changed
-    // So it will skip the SQL request, even if the last one was ROLLBACKed!
-    resetSequelizeInstance(videoPlaylistInstance, videoPlaylistFieldsSave)
+    // So we need to restore the previous fields
+    resetSequelizeInstance(videoPlaylistInstance)
 
     throw err
   }
index 260dee2b9f14e6fe594d127294fab02d47bbfba3..e6197c4b1b87dd973a3cb510cfc5f645decd95bd 100644 (file)
@@ -45,7 +45,6 @@ export {
 
 async function updateVideo (req: express.Request, res: express.Response) {
   const videoFromReq = res.locals.videoAll
-  const videoFieldsSave = videoFromReq.toJSON()
   const oldVideoAuditView = new VideoAuditView(videoFromReq.toFormattedDetailsJSON())
   const videoInfoToUpdate: VideoUpdate = req.body
 
@@ -151,10 +150,9 @@ async function updateVideo (req: express.Request, res: express.Response) {
       isNewVideo
     })
   } catch (err) {
-    // Force fields we want to update
     // If the transaction is retried, sequelize will think the object has not changed
-    // So it will skip the SQL request, even if the last one was ROLLBACKed!
-    resetSequelizeInstance(videoFromReq, videoFieldsSave)
+    // So we need to restore the previous fields
+    resetSequelizeInstance(videoFromReq)
 
     throw err
   } finally {
index 62738108607f650af0ca63b25de506f4fb4de03f..0e6b3550371e721624652166ea03d2435538b5c6 100644 (file)
@@ -78,10 +78,8 @@ function updateInstanceWithAnother <M, T extends U, U extends Model<M>> (instanc
   }
 }
 
-function resetSequelizeInstance (instance: Model<any>, savedFields: object) {
-  Object.keys(savedFields).forEach(key => {
-    instance[key] = savedFields[key]
-  })
+function resetSequelizeInstance <T> (instance: Model<T>) {
+  instance.set(instance.previous())
 }
 
 function filterNonExistingModels <T extends { hasSameUniqueKeysThan (other: T): boolean }> (
index fe94af9f1120da0aaa524a970afba66804b3e433..1379804606439b3b623ff59a96e90a3b786a068b 100644 (file)
@@ -13,19 +13,12 @@ export class APActorUpdater {
 
   private accountOrChannel: MAccount | MChannel
 
-  private readonly actorFieldsSave: object
-  private readonly accountOrChannelFieldsSave: object
-
   constructor (
     private readonly actorObject: ActivityPubActor,
     private readonly actor: MActorFull
   ) {
-    this.actorFieldsSave = this.actor.toJSON()
-
     if (this.actorObject.type === 'Group') this.accountOrChannel = this.actor.VideoChannel
     else this.accountOrChannel = this.actor.Account
-
-    this.accountOrChannelFieldsSave = this.accountOrChannel.toJSON()
   }
 
   async update () {
@@ -58,12 +51,12 @@ export class APActorUpdater {
 
       logger.info('Remote account %s updated', this.actorObject.url)
     } catch (err) {
-      if (this.actor !== undefined && this.actorFieldsSave !== undefined) {
-        resetSequelizeInstance(this.actor, this.actorFieldsSave)
+      if (this.actor !== undefined) {
+        resetSequelizeInstance(this.actor)
       }
 
-      if (this.accountOrChannel !== undefined && this.accountOrChannelFieldsSave !== undefined) {
-        resetSequelizeInstance(this.accountOrChannel, this.accountOrChannelFieldsSave)
+      if (this.accountOrChannel !== undefined) {
+        resetSequelizeInstance(this.accountOrChannel)
       }
 
       // This is just a debug because we will retry the insert
index 32cbf7e07d75f0fb5a7a3266f0cead7620c0c73c..0bf32f4401c4150b90125399ea06c898d12afc52 100644 (file)
@@ -13,8 +13,6 @@ export class APVideoUpdater extends APVideoAbstractBuilder {
   private readonly wasPrivateVideo: boolean
   private readonly wasUnlistedVideo: boolean
 
-  private readonly videoFieldsSave: any
-
   private readonly oldVideoChannel: MChannelAccountLight
 
   protected lTags: LoggerTagsFn
@@ -30,8 +28,6 @@ export class APVideoUpdater extends APVideoAbstractBuilder {
 
     this.oldVideoChannel = this.video.VideoChannel
 
-    this.videoFieldsSave = this.video.toJSON()
-
     this.lTags = loggerTagsFactory('ap', 'video', 'update', video.uuid, video.url)
   }
 
@@ -156,8 +152,8 @@ export class APVideoUpdater extends APVideoAbstractBuilder {
   }
 
   private catchUpdateError (err: Error) {
-    if (this.video !== undefined && this.videoFieldsSave !== undefined) {
-      resetSequelizeInstance(this.video, this.videoFieldsSave)
+    if (this.video !== undefined) {
+      resetSequelizeInstance(this.video)
     }
 
     // This is just a debug because we will retry the insert