aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-06-15 09:17:19 +0200
committerChocobozzz <me@florianbigard.com>2021-06-15 10:40:06 +0200
commiteae0365b5c5468e51e9795b0e894815ebda86b4a (patch)
tree5da54b28c94d43d1715a0c69e35eb1cf3a1a959d /server/lib
parent51f636ad0f928bb94069c9143e38df0518f6e4a7 (diff)
downloadPeerTube-eae0365b5c5468e51e9795b0e894815ebda86b4a.tar.gz
PeerTube-eae0365b5c5468e51e9795b0e894815ebda86b4a.tar.zst
PeerTube-eae0365b5c5468e51e9795b0e894815ebda86b4a.zip
Fix missing transactions
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/follow.ts13
-rw-r--r--server/lib/activitypub/process/process-delete.ts7
-rw-r--r--server/lib/activitypub/process/process-follow.ts7
-rw-r--r--server/lib/activitypub/process/process-undo.ts4
-rw-r--r--server/lib/job-queue/handlers/video-transcoding.ts50
-rw-r--r--server/lib/moderation.ts2
-rw-r--r--server/lib/user.ts8
-rw-r--r--server/lib/video-comment.ts13
8 files changed, 46 insertions, 58 deletions
diff --git a/server/lib/activitypub/follow.ts b/server/lib/activitypub/follow.ts
index 351499bd1..c1bd667e0 100644
--- a/server/lib/activitypub/follow.ts
+++ b/server/lib/activitypub/follow.ts
@@ -1,12 +1,13 @@
1import { MActorFollowActors } from '../../types/models' 1import { Transaction } from 'sequelize'
2import { getServerActor } from '@server/models/application/application'
3import { logger } from '../../helpers/logger'
2import { CONFIG } from '../../initializers/config' 4import { CONFIG } from '../../initializers/config'
3import { SERVER_ACTOR_NAME } from '../../initializers/constants' 5import { SERVER_ACTOR_NAME } from '../../initializers/constants'
4import { JobQueue } from '../job-queue'
5import { logger } from '../../helpers/logger'
6import { ServerModel } from '../../models/server/server' 6import { ServerModel } from '../../models/server/server'
7import { getServerActor } from '@server/models/application/application' 7import { MActorFollowActors } from '../../types/models'
8import { JobQueue } from '../job-queue'
8 9
9async function autoFollowBackIfNeeded (actorFollow: MActorFollowActors) { 10async function autoFollowBackIfNeeded (actorFollow: MActorFollowActors, transaction?: Transaction) {
10 if (!CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_BACK.ENABLED) return 11 if (!CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_BACK.ENABLED) return
11 12
12 const follower = actorFollow.ActorFollower 13 const follower = actorFollow.ActorFollower
@@ -16,7 +17,7 @@ async function autoFollowBackIfNeeded (actorFollow: MActorFollowActors) {
16 17
17 const me = await getServerActor() 18 const me = await getServerActor()
18 19
19 const server = await ServerModel.load(follower.serverId) 20 const server = await ServerModel.load(follower.serverId, transaction)
20 const host = server.host 21 const host = server.host
21 22
22 const payload = { 23 const payload = {
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts
index 44f6a87b0..1d2279df5 100644
--- a/server/lib/activitypub/process/process-delete.ts
+++ b/server/lib/activitypub/process/process-delete.ts
@@ -16,7 +16,6 @@ import {
16 MChannelActor, 16 MChannelActor,
17 MCommentOwnerVideo 17 MCommentOwnerVideo
18} from '../../../types/models' 18} from '../../../types/models'
19import { markCommentAsDeleted } from '../../video-comment'
20import { forwardVideoRelatedActivity } from '../send/utils' 19import { forwardVideoRelatedActivity } from '../send/utils'
21 20
22async function processDeleteActivity (options: APProcessorOptions<ActivityDelete>) { 21async function processDeleteActivity (options: APProcessorOptions<ActivityDelete>) {
@@ -139,11 +138,9 @@ function processDeleteVideoComment (byActor: MActorSignature, videoComment: MCom
139 throw new Error(`Account ${byActor.url} does not own video comment ${videoComment.url} or video ${videoComment.Video.url}`) 138 throw new Error(`Account ${byActor.url} does not own video comment ${videoComment.url} or video ${videoComment.Video.url}`)
140 } 139 }
141 140
142 await sequelizeTypescript.transaction(async t => { 141 videoComment.markAsDeleted()
143 markCommentAsDeleted(videoComment)
144 142
145 await videoComment.save() 143 await videoComment.save({ transaction: t })
146 })
147 144
148 if (videoComment.Video.isOwned()) { 145 if (videoComment.Video.isOwned()) {
149 // Don't resend the activity to the sender 146 // Don't resend the activity to the sender
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts
index 9009c6469..f85238f8e 100644
--- a/server/lib/activitypub/process/process-follow.ts
+++ b/server/lib/activitypub/process/process-follow.ts
@@ -43,7 +43,7 @@ async function processFollow (byActor: MActorSignature, activityId: string, targ
43 if (isFollowingInstance && CONFIG.FOLLOWERS.INSTANCE.ENABLED === false) { 43 if (isFollowingInstance && CONFIG.FOLLOWERS.INSTANCE.ENABLED === false) {
44 logger.info('Rejecting %s because instance followers are disabled.', targetActor.url) 44 logger.info('Rejecting %s because instance followers are disabled.', targetActor.url)
45 45
46 await sendReject(activityId, byActor, targetActor) 46 sendReject(activityId, byActor, targetActor)
47 47
48 return { actorFollow: undefined as MActorFollowActors } 48 return { actorFollow: undefined as MActorFollowActors }
49 } 49 }
@@ -84,8 +84,9 @@ async function processFollow (byActor: MActorSignature, activityId: string, targ
84 84
85 // Target sends to actor he accepted the follow request 85 // Target sends to actor he accepted the follow request
86 if (actorFollow.state === 'accepted') { 86 if (actorFollow.state === 'accepted') {
87 await sendAccept(actorFollow) 87 sendAccept(actorFollow)
88 await autoFollowBackIfNeeded(actorFollow) 88
89 await autoFollowBackIfNeeded(actorFollow, t)
89 } 90 }
90 91
91 return { actorFollow, created, isFollowingInstance, targetActor } 92 return { actorFollow, created, isFollowingInstance, targetActor }
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts
index fdb8dac24..d4b2a795f 100644
--- a/server/lib/activitypub/process/process-undo.ts
+++ b/server/lib/activitypub/process/process-undo.ts
@@ -106,7 +106,7 @@ async function processUndoCacheFile (byActor: MActorSignature, activity: Activit
106 const { video } = await getOrCreateAPVideo({ videoObject: cacheFileObject.object }) 106 const { video } = await getOrCreateAPVideo({ videoObject: cacheFileObject.object })
107 107
108 return sequelizeTypescript.transaction(async t => { 108 return sequelizeTypescript.transaction(async t => {
109 const cacheFile = await VideoRedundancyModel.loadByUrl(cacheFileObject.id) 109 const cacheFile = await VideoRedundancyModel.loadByUrl(cacheFileObject.id, t)
110 if (!cacheFile) { 110 if (!cacheFile) {
111 logger.debug('Cannot undo unknown video cache %s.', cacheFileObject.id) 111 logger.debug('Cannot undo unknown video cache %s.', cacheFileObject.id)
112 return 112 return
@@ -114,7 +114,7 @@ async function processUndoCacheFile (byActor: MActorSignature, activity: Activit
114 114
115 if (cacheFile.actorId !== byActor.id) throw new Error('Cannot delete redundancy ' + cacheFile.url + ' of another actor.') 115 if (cacheFile.actorId !== byActor.id) throw new Error('Cannot delete redundancy ' + cacheFile.url + ' of another actor.')
116 116
117 await cacheFile.destroy() 117 await cacheFile.destroy({ transaction: t })
118 118
119 if (video.isOwned()) { 119 if (video.isOwned()) {
120 // Don't resend the activity to the sender 120 // Don't resend the activity to the sender
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts
index 8d659daa6..8f218ca3a 100644
--- a/server/lib/job-queue/handlers/video-transcoding.ts
+++ b/server/lib/job-queue/handlers/video-transcoding.ts
@@ -151,35 +151,31 @@ async function onVideoFileOptimizer (
151 // Outside the transaction (IO on disk) 151 // Outside the transaction (IO on disk)
152 const { videoFileResolution, isPortraitMode } = await videoArg.getMaxQualityResolution() 152 const { videoFileResolution, isPortraitMode } = await videoArg.getMaxQualityResolution()
153 153
154 const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { 154 // Maybe the video changed in database, refresh it
155 // Maybe the video changed in database, refresh it 155 const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid)
156 const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid, t) 156 // Video does not exist anymore
157 // Video does not exist anymore 157 if (!videoDatabase) return undefined
158 if (!videoDatabase) return undefined 158
159 159 let videoPublished = false
160 let videoPublished = false 160
161 161 // Generate HLS version of the original file
162 // Generate HLS version of the original file 162 const originalFileHLSPayload = Object.assign({}, payload, {
163 const originalFileHLSPayload = Object.assign({}, payload, { 163 isPortraitMode,
164 isPortraitMode, 164 resolution: videoDatabase.getMaxQualityFile().resolution,
165 resolution: videoDatabase.getMaxQualityFile().resolution, 165 // If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues
166 // If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues 166 copyCodecs: transcodeType !== 'quick-transcode',
167 copyCodecs: transcodeType !== 'quick-transcode', 167 isMaxQuality: true
168 isMaxQuality: true 168 })
169 }) 169 const hasHls = await createHlsJobIfEnabled(user, originalFileHLSPayload)
170 const hasHls = await createHlsJobIfEnabled(user, originalFileHLSPayload)
171
172 const hasNewResolutions = await createLowerResolutionsJobs(videoDatabase, user, videoFileResolution, isPortraitMode, 'webtorrent')
173
174 if (!hasHls && !hasNewResolutions) {
175 // No transcoding to do, it's now published
176 videoPublished = await videoDatabase.publishIfNeededAndSave(t)
177 }
178 170
179 await federateVideoIfNeeded(videoDatabase, payload.isNewVideo, t) 171 const hasNewResolutions = await createLowerResolutionsJobs(videoDatabase, user, videoFileResolution, isPortraitMode, 'webtorrent')
180 172
181 return { videoDatabase, videoPublished } 173 if (!hasHls && !hasNewResolutions) {
182 }) 174 // No transcoding to do, it's now published
175 videoPublished = await videoDatabase.publishIfNeededAndSave(undefined)
176 }
177
178 await federateVideoIfNeeded(videoDatabase, payload.isNewVideo)
183 179
184 if (payload.isNewVideo) Notifier.Instance.notifyOnNewVideoIfNeeded(videoDatabase) 180 if (payload.isNewVideo) Notifier.Instance.notifyOnNewVideoIfNeeded(videoDatabase)
185 if (videoPublished) Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase) 181 if (videoPublished) Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase)
diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts
index 0cefe1648..14e00518e 100644
--- a/server/lib/moderation.ts
+++ b/server/lib/moderation.ts
@@ -221,7 +221,7 @@ async function createAbuse (options: {
221 const { isOwned } = await associateFun(abuseInstance) 221 const { isOwned } = await associateFun(abuseInstance)
222 222
223 if (isOwned === false) { 223 if (isOwned === false) {
224 await sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction) 224 sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
225 } 225 }
226 226
227 const abuseJSON = abuseInstance.toFormattedAdminJSON() 227 const abuseJSON = abuseInstance.toFormattedAdminJSON()
diff --git a/server/lib/user.ts b/server/lib/user.ts
index a2163abb1..91a682a7e 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -44,11 +44,11 @@ async function createUserAccountAndChannelAndPlaylist (parameters: {
44 displayName: userDisplayName, 44 displayName: userDisplayName,
45 userId: userCreated.id, 45 userId: userCreated.id,
46 applicationId: null, 46 applicationId: null,
47 t: t 47 t
48 }) 48 })
49 userCreated.Account = accountCreated 49 userCreated.Account = accountCreated
50 50
51 const channelAttributes = await buildChannelAttributes(userCreated, channelNames) 51 const channelAttributes = await buildChannelAttributes(userCreated, t, channelNames)
52 const videoChannel = await createLocalVideoChannel(channelAttributes, accountCreated, t) 52 const videoChannel = await createLocalVideoChannel(channelAttributes, accountCreated, t)
53 53
54 const videoPlaylist = await createWatchLaterPlaylist(accountCreated, t) 54 const videoPlaylist = await createWatchLaterPlaylist(accountCreated, t)
@@ -203,13 +203,13 @@ function createDefaultUserNotificationSettings (user: MUserId, t: Transaction |
203 return UserNotificationSettingModel.create(values, { transaction: t }) 203 return UserNotificationSettingModel.create(values, { transaction: t })
204} 204}
205 205
206async function buildChannelAttributes (user: MUser, channelNames?: ChannelNames) { 206async function buildChannelAttributes (user: MUser, transaction?: Transaction, channelNames?: ChannelNames) {
207 if (channelNames) return channelNames 207 if (channelNames) return channelNames
208 208
209 let channelName = user.username + '_channel' 209 let channelName = user.username + '_channel'
210 210
211 // Conflict, generate uuid instead 211 // Conflict, generate uuid instead
212 const actor = await ActorModel.loadLocalByName(channelName) 212 const actor = await ActorModel.loadLocalByName(channelName, transaction)
213 if (actor) channelName = uuidv4() 213 if (actor) channelName = uuidv4()
214 214
215 const videoChannelDisplayName = `Main ${user.username} channel` 215 const videoChannelDisplayName = `Main ${user.username} channel`
diff --git a/server/lib/video-comment.ts b/server/lib/video-comment.ts
index 51a9c747e..c76570a5d 100644
--- a/server/lib/video-comment.ts
+++ b/server/lib/video-comment.ts
@@ -18,9 +18,9 @@ async function removeComment (videoCommentInstance: MCommentOwnerVideo) {
18 await sendDeleteVideoComment(videoCommentInstance, t) 18 await sendDeleteVideoComment(videoCommentInstance, t)
19 } 19 }
20 20
21 markCommentAsDeleted(videoCommentInstance) 21 videoCommentInstance.markAsDeleted()
22 22
23 await videoCommentInstance.save() 23 await videoCommentInstance.save({ transaction: t })
24 }) 24 })
25 25
26 logger.info('Video comment %d deleted.', videoCommentInstance.id) 26 logger.info('Video comment %d deleted.', videoCommentInstance.id)
@@ -95,17 +95,10 @@ function buildFormattedCommentTree (resultList: ResultList<VideoCommentModel>):
95 return thread 95 return thread
96} 96}
97 97
98function markCommentAsDeleted (comment: MComment): void {
99 comment.text = ''
100 comment.deletedAt = new Date()
101 comment.accountId = null
102}
103
104// --------------------------------------------------------------------------- 98// ---------------------------------------------------------------------------
105 99
106export { 100export {
107 removeComment, 101 removeComment,
108 createVideoComment, 102 createVideoComment,
109 buildFormattedCommentTree, 103 buildFormattedCommentTree
110 markCommentAsDeleted
111} 104}