Fix retrying update on sql serialization conflict

pull/5615/head
Chocobozzz 2023-02-14 08:59:27 +01:00
parent 4c61660a0a
commit 4565774669
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
6 changed files with 14 additions and 33 deletions

View 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
}

View 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
}

View 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 {

View 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 }> (

View 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

View 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