Prevent concurrent video update
This commit is contained in:
parent
5cf027bdc4
commit
a2a81f5a7f
|
@ -52,16 +52,16 @@ export {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export async function updateVideo (req: express.Request, res: express.Response) {
|
export async function updateVideo (req: express.Request, res: express.Response) {
|
||||||
const videoInstance = res.locals.videoAll
|
const videoFromReq = res.locals.videoAll
|
||||||
const videoFieldsSave = videoInstance.toJSON()
|
const videoFieldsSave = videoFromReq.toJSON()
|
||||||
const oldVideoAuditView = new VideoAuditView(videoInstance.toFormattedDetailsJSON())
|
const oldVideoAuditView = new VideoAuditView(videoFromReq.toFormattedDetailsJSON())
|
||||||
const videoInfoToUpdate: VideoUpdate = req.body
|
const videoInfoToUpdate: VideoUpdate = req.body
|
||||||
|
|
||||||
const wasConfidentialVideo = videoInstance.isConfidential()
|
const wasConfidentialVideo = videoFromReq.isConfidential()
|
||||||
const hadPrivacyForFederation = videoInstance.hasPrivacyForFederation()
|
const hadPrivacyForFederation = videoFromReq.hasPrivacyForFederation()
|
||||||
|
|
||||||
const [ thumbnailModel, previewModel ] = await buildVideoThumbnailsFromReq({
|
const [ thumbnailModel, previewModel ] = await buildVideoThumbnailsFromReq({
|
||||||
video: videoInstance,
|
video: videoFromReq,
|
||||||
files: req.files,
|
files: req.files,
|
||||||
fallback: () => Promise.resolve(undefined),
|
fallback: () => Promise.resolve(undefined),
|
||||||
automaticallyGenerated: false
|
automaticallyGenerated: false
|
||||||
|
@ -69,8 +69,11 @@ export async function updateVideo (req: express.Request, res: express.Response)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const videoInstanceUpdated = await sequelizeTypescript.transaction(async t => {
|
const videoInstanceUpdated = await sequelizeTypescript.transaction(async t => {
|
||||||
|
// Refresh video since thumbnails to prevent concurrent updates
|
||||||
|
const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoFromReq.id, t)
|
||||||
|
|
||||||
const sequelizeOptions = { transaction: t }
|
const sequelizeOptions = { transaction: t }
|
||||||
const oldVideoChannel = videoInstance.VideoChannel
|
const oldVideoChannel = video.VideoChannel
|
||||||
|
|
||||||
const keysToUpdate: (keyof VideoUpdate & FilteredModelAttributes<VideoModel>)[] = [
|
const keysToUpdate: (keyof VideoUpdate & FilteredModelAttributes<VideoModel>)[] = [
|
||||||
'name',
|
'name',
|
||||||
|
@ -86,25 +89,25 @@ export async function updateVideo (req: express.Request, res: express.Response)
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const key of keysToUpdate) {
|
for (const key of keysToUpdate) {
|
||||||
if (videoInfoToUpdate[key] !== undefined) videoInstance.set(key, videoInfoToUpdate[key])
|
if (videoInfoToUpdate[key] !== undefined) video.set(key, videoInfoToUpdate[key])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoInfoToUpdate.originallyPublishedAt !== undefined && videoInfoToUpdate.originallyPublishedAt !== null) {
|
if (videoInfoToUpdate.originallyPublishedAt !== undefined && videoInfoToUpdate.originallyPublishedAt !== null) {
|
||||||
videoInstance.originallyPublishedAt = new Date(videoInfoToUpdate.originallyPublishedAt)
|
video.originallyPublishedAt = new Date(videoInfoToUpdate.originallyPublishedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Privacy update?
|
// Privacy update?
|
||||||
let isNewVideo = false
|
let isNewVideo = false
|
||||||
if (videoInfoToUpdate.privacy !== undefined) {
|
if (videoInfoToUpdate.privacy !== undefined) {
|
||||||
isNewVideo = await updateVideoPrivacy({ videoInstance, videoInfoToUpdate, hadPrivacyForFederation, transaction: t })
|
isNewVideo = await updateVideoPrivacy({ videoInstance: video, videoInfoToUpdate, hadPrivacyForFederation, transaction: t })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force updatedAt attribute change
|
// Force updatedAt attribute change
|
||||||
if (!videoInstance.changed()) {
|
if (!video.changed()) {
|
||||||
await videoInstance.setAsRefreshed()
|
await video.setAsRefreshed()
|
||||||
}
|
}
|
||||||
|
|
||||||
const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) as MVideoFullLight
|
const videoInstanceUpdated = await video.save(sequelizeOptions) as MVideoFullLight
|
||||||
|
|
||||||
// Thumbnail & preview updates?
|
// Thumbnail & preview updates?
|
||||||
if (thumbnailModel) await videoInstanceUpdated.addAndSaveThumbnail(thumbnailModel, t)
|
if (thumbnailModel) await videoInstanceUpdated.addAndSaveThumbnail(thumbnailModel, t)
|
||||||
|
@ -141,7 +144,7 @@ export async function updateVideo (req: express.Request, res: express.Response)
|
||||||
new VideoAuditView(videoInstanceUpdated.toFormattedDetailsJSON()),
|
new VideoAuditView(videoInstanceUpdated.toFormattedDetailsJSON()),
|
||||||
oldVideoAuditView
|
oldVideoAuditView
|
||||||
)
|
)
|
||||||
logger.info('Video with name %s and uuid %s updated.', videoInstance.name, videoInstance.uuid, lTags(videoInstance.uuid))
|
logger.info('Video with name %s and uuid %s updated.', video.name, video.uuid, lTags(video.uuid))
|
||||||
|
|
||||||
return videoInstanceUpdated
|
return videoInstanceUpdated
|
||||||
})
|
})
|
||||||
|
@ -155,7 +158,7 @@ export async function updateVideo (req: express.Request, res: express.Response)
|
||||||
// Force fields we want to update
|
// Force fields we want to update
|
||||||
// If the transaction is retried, sequelize will think the object has not changed
|
// 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!
|
// So it will skip the SQL request, even if the last one was ROLLBACKed!
|
||||||
resetSequelizeInstance(videoInstance, videoFieldsSave)
|
resetSequelizeInstance(videoFromReq, videoFieldsSave)
|
||||||
|
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue