aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video/sql/shared/video-model-builder.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-06-11 10:59:27 +0200
committerChocobozzz <me@florianbigard.com>2021-06-11 11:15:44 +0200
commit17bb45388ec319d288a1b8387c6c199fe2f6b64f (patch)
tree96a6b331ce1766eced50f78ab3ce0ed9197d8833 /server/models/video/sql/shared/video-model-builder.ts
parentca4b4b2e5590c1b37cff1fe1be7f797b93351229 (diff)
downloadPeerTube-17bb45388ec319d288a1b8387c6c199fe2f6b64f.tar.gz
PeerTube-17bb45388ec319d288a1b8387c6c199fe2f6b64f.tar.zst
PeerTube-17bb45388ec319d288a1b8387c6c199fe2f6b64f.zip
Optimize rows parsing
Diffstat (limited to 'server/models/video/sql/shared/video-model-builder.ts')
-rw-r--r--server/models/video/sql/shared/video-model-builder.ts224
1 files changed, 128 insertions, 96 deletions
diff --git a/server/models/video/sql/shared/video-model-builder.ts b/server/models/video/sql/shared/video-model-builder.ts
index 627ea6443..2a60dab04 100644
--- a/server/models/video/sql/shared/video-model-builder.ts
+++ b/server/models/video/sql/shared/video-model-builder.ts
@@ -1,4 +1,5 @@
1import { pick } from 'lodash' 1
2import { logger } from '@server/helpers/logger'
2import { AccountModel } from '@server/models/account/account' 3import { AccountModel } from '@server/models/account/account'
3import { ActorModel } from '@server/models/actor/actor' 4import { ActorModel } from '@server/models/actor/actor'
4import { ActorImageModel } from '@server/models/actor/actor-image' 5import { ActorImageModel } from '@server/models/actor/actor-image'
@@ -15,7 +16,9 @@ import { VideoChannelModel } from '../../video-channel'
15import { VideoFileModel } from '../../video-file' 16import { VideoFileModel } from '../../video-file'
16import { VideoLiveModel } from '../../video-live' 17import { VideoLiveModel } from '../../video-live'
17import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist' 18import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist'
18import { VideoAttributes } from './video-attributes' 19import { VideoTables } from './video-tables'
20
21type SQLRow = { [id: string]: string | number }
19 22
20/** 23/**
21 * 24 *
@@ -28,12 +31,12 @@ export class VideoModelBuilder {
28 private videoStreamingPlaylistMemo: { [ id: number ]: VideoStreamingPlaylistModel } 31 private videoStreamingPlaylistMemo: { [ id: number ]: VideoStreamingPlaylistModel }
29 private videoFileMemo: { [ id: number ]: VideoFileModel } 32 private videoFileMemo: { [ id: number ]: VideoFileModel }
30 33
31 private thumbnailsDone: Set<number> 34 private thumbnailsDone: Set<any>
32 private historyDone: Set<number> 35 private historyDone: Set<any>
33 private blacklistDone: Set<number> 36 private blacklistDone: Set<any>
34 private liveDone: Set<number> 37 private liveDone: Set<any>
35 private redundancyDone: Set<number> 38 private redundancyDone: Set<any>
36 private scheduleVideoUpdateDone: Set<number> 39 private scheduleVideoUpdateDone: Set<any>
37 40
38 private trackersDone: Set<string> 41 private trackersDone: Set<string>
39 private tagsDone: Set<string> 42 private tagsDone: Set<string>
@@ -44,12 +47,12 @@ export class VideoModelBuilder {
44 47
45 constructor ( 48 constructor (
46 readonly mode: 'get' | 'list', 49 readonly mode: 'get' | 'list',
47 readonly videoAttributes: VideoAttributes 50 readonly tables: VideoTables
48 ) { 51 ) {
49 52
50 } 53 }
51 54
52 buildVideosFromRows (rows: any[], rowsWebtorrentFiles?: any[], rowsStreamingPlaylist?: any[]) { 55 buildVideosFromRows (rows: SQLRow[], rowsWebTorrentFiles?: SQLRow[], rowsStreamingPlaylist?: SQLRow[]) {
53 this.reinit() 56 this.reinit()
54 57
55 for (const row of rows) { 58 for (const row of rows) {
@@ -60,7 +63,7 @@ export class VideoModelBuilder {
60 this.setUserHistory(row, videoModel) 63 this.setUserHistory(row, videoModel)
61 this.addThumbnail(row, videoModel) 64 this.addThumbnail(row, videoModel)
62 65
63 if (!rowsWebtorrentFiles) { 66 if (!rowsWebTorrentFiles) {
64 this.addWebTorrentFile(row, videoModel) 67 this.addWebTorrentFile(row, videoModel)
65 } 68 }
66 69
@@ -75,30 +78,11 @@ export class VideoModelBuilder {
75 this.setBlacklisted(row, videoModel) 78 this.setBlacklisted(row, videoModel)
76 this.setScheduleVideoUpdate(row, videoModel) 79 this.setScheduleVideoUpdate(row, videoModel)
77 this.setLive(row, videoModel) 80 this.setLive(row, videoModel)
78
79 if (!rowsWebtorrentFiles && row.VideoFiles.id) {
80 this.addRedundancy(row.VideoFiles.RedundancyVideos, this.videoFileMemo[row.VideoFiles.id])
81 }
82
83 if (!rowsStreamingPlaylist && row.VideoStreamingPlaylists.id) {
84 this.addRedundancy(row.VideoStreamingPlaylists.RedundancyVideos, this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id])
85 }
86 } 81 }
87 } 82 }
88 83
89 for (const row of rowsWebtorrentFiles || []) { 84 this.grabSeparateWebTorrentFiles(rowsWebTorrentFiles)
90 const videoModel = this.videosMemo[row.id] 85 this.grabSeparateStreamingPlaylistFiles(rowsStreamingPlaylist)
91 this.addWebTorrentFile(row, videoModel)
92 this.addRedundancy(row.VideoFiles.RedundancyVideos, this.videoFileMemo[row.VideoFiles.id])
93 }
94
95 for (const row of rowsStreamingPlaylist || []) {
96 const videoModel = this.videosMemo[row.id]
97
98 this.addStreamingPlaylist(row, videoModel)
99 this.addStreamingPlaylistFile(row)
100 this.addRedundancy(row.VideoStreamingPlaylists.RedundancyVideos, this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id])
101 }
102 86
103 return this.videos 87 return this.videos
104 } 88 }
@@ -121,21 +105,45 @@ export class VideoModelBuilder {
121 this.videos = [] 105 this.videos = []
122 } 106 }
123 107
124 private buildVideo (row: any) { 108 private grabSeparateWebTorrentFiles (rowsWebTorrentFiles?: SQLRow[]) {
109 if (!rowsWebTorrentFiles) return
110
111 for (const row of rowsWebTorrentFiles) {
112 const videoModel = this.videosMemo[row.id]
113 this.addWebTorrentFile(row, videoModel)
114 this.addRedundancy(row, 'VideoFiles.RedundancyVideos', this.videoFileMemo[row['VideoFiles.id']])
115 }
116 }
117
118 private grabSeparateStreamingPlaylistFiles (rowsStreamingPlaylist?: SQLRow[]) {
119 if (!rowsStreamingPlaylist) return
120
121 for (const row of rowsStreamingPlaylist || []) {
122 const videoModel = this.videosMemo[row.id]
123
124 this.addStreamingPlaylist(row, videoModel)
125 this.addStreamingPlaylistFile(row)
126 this.addRedundancy(
127 row,
128 'VideoStreamingPlaylists.RedundancyVideos',
129 this.videoStreamingPlaylistMemo[row['VideoStreamingPlaylists.id']]
130 )
131 }
132 }
133
134 private buildVideo (row: SQLRow) {
125 if (this.videosMemo[row.id]) return 135 if (this.videosMemo[row.id]) return
126 136
127 // Build Channel 137 // Build Channel
128 const channel = row.VideoChannel 138 const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts)
129 const channelModel = new VideoChannelModel(pick(channel, this.videoAttributes.getChannelAttributes()), this.buildOpts) 139 channelModel.Actor = this.buildActor(row, 'VideoChannel')
130 channelModel.Actor = this.buildActor(channel.Actor)
131 140
132 const account = row.VideoChannel.Account 141 const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts)
133 const accountModel = new AccountModel(pick(account, this.videoAttributes.getAccountAttributes()), this.buildOpts) 142 accountModel.Actor = this.buildActor(row, 'VideoChannel.Account')
134 accountModel.Actor = this.buildActor(account.Actor)
135 143
136 channelModel.Account = accountModel 144 channelModel.Account = accountModel
137 145
138 const videoModel = new VideoModel(pick(row, this.videoAttributes.getVideoAttributes()), this.buildOpts) 146 const videoModel = new VideoModel(this.grab(row, this.tables.getVideoAttributes(), ''), this.buildOpts)
139 videoModel.VideoChannel = channelModel 147 videoModel.VideoChannel = channelModel
140 148
141 this.videosMemo[row.id] = videoModel 149 this.videosMemo[row.id] = videoModel
@@ -151,143 +159,167 @@ export class VideoModelBuilder {
151 this.videos.push(videoModel) 159 this.videos.push(videoModel)
152 } 160 }
153 161
154 private buildActor (rowActor: any) { 162 private buildActor (row: SQLRow, prefix: string) {
155 const avatarModel = rowActor.Avatar.id !== null 163 const actorPrefix = `${prefix}.Actor`
156 ? new ActorImageModel(pick(rowActor.Avatar, this.videoAttributes.getAvatarAttributes()), this.buildOpts) 164 const avatarPrefix = `${actorPrefix}.Avatar`
165 const serverPrefix = `${actorPrefix}.Server`
166
167 const avatarModel = row[`${avatarPrefix}.id`] !== null
168 ? new ActorImageModel(this.grab(row, this.tables.getAvatarAttributes(), avatarPrefix), this.buildOpts)
157 : null 169 : null
158 170
159 const serverModel = rowActor.Server.id !== null 171 const serverModel = row[`${serverPrefix}.id`] !== null
160 ? new ServerModel(pick(rowActor.Server, this.videoAttributes.getServerAttributes()), this.buildOpts) 172 ? new ServerModel(this.grab(row, this.tables.getServerAttributes(), serverPrefix), this.buildOpts)
161 : null 173 : null
162 174
163 const actorModel = new ActorModel(pick(rowActor, this.videoAttributes.getActorAttributes()), this.buildOpts) 175 const actorModel = new ActorModel(this.grab(row, this.tables.getActorAttributes(), actorPrefix), this.buildOpts)
164 actorModel.Avatar = avatarModel 176 actorModel.Avatar = avatarModel
165 actorModel.Server = serverModel 177 actorModel.Server = serverModel
166 178
167 return actorModel 179 return actorModel
168 } 180 }
169 181
170 private setUserHistory (row: any, videoModel: VideoModel) { 182 private setUserHistory (row: SQLRow, videoModel: VideoModel) {
171 if (!row.userVideoHistory?.id || this.historyDone.has(row.userVideoHistory.id)) return 183 const id = row['userVideoHistory.id']
184 if (!id || this.historyDone.has(id)) return
172 185
173 const attributes = pick(row.userVideoHistory, this.videoAttributes.getUserHistoryAttributes()) 186 const attributes = this.grab(row, this.tables.getUserHistoryAttributes(), 'userVideoHistory')
174 const historyModel = new UserVideoHistoryModel(attributes, this.buildOpts) 187 const historyModel = new UserVideoHistoryModel(attributes, this.buildOpts)
175 videoModel.UserVideoHistories.push(historyModel) 188 videoModel.UserVideoHistories.push(historyModel)
176 189
177 this.historyDone.add(row.userVideoHistory.id) 190 this.historyDone.add(id)
178 } 191 }
179 192
180 private addThumbnail (row: any, videoModel: VideoModel) { 193 private addThumbnail (row: SQLRow, videoModel: VideoModel) {
181 if (!row.Thumbnails?.id || this.thumbnailsDone.has(row.Thumbnails.id)) return 194 const id = row['Thumbnails.id']
195 if (!id || this.thumbnailsDone.has(id)) return
182 196
183 const attributes = pick(row.Thumbnails, this.videoAttributes.getThumbnailAttributes()) 197 const attributes = this.grab(row, this.tables.getThumbnailAttributes(), 'Thumbnails')
184 const thumbnailModel = new ThumbnailModel(attributes, this.buildOpts) 198 const thumbnailModel = new ThumbnailModel(attributes, this.buildOpts)
185 videoModel.Thumbnails.push(thumbnailModel) 199 videoModel.Thumbnails.push(thumbnailModel)
186 200
187 this.thumbnailsDone.add(row.Thumbnails.id) 201 this.thumbnailsDone.add(id)
188 } 202 }
189 203
190 private addWebTorrentFile (row: any, videoModel: VideoModel) { 204 private addWebTorrentFile (row: SQLRow, videoModel: VideoModel) {
191 if (!row.VideoFiles?.id || this.videoFileMemo[row.VideoFiles.id]) return 205 const id = row['VideoFiles.id']
206 if (!id || this.videoFileMemo[id]) return
192 207
193 const attributes = pick(row.VideoFiles, this.videoAttributes.getFileAttributes()) 208 const attributes = this.grab(row, this.tables.getFileAttributes(), 'VideoFiles')
194 const videoFileModel = new VideoFileModel(attributes, this.buildOpts) 209 const videoFileModel = new VideoFileModel(attributes, this.buildOpts)
195 videoModel.VideoFiles.push(videoFileModel) 210 videoModel.VideoFiles.push(videoFileModel)
196 211
197 this.videoFileMemo[row.VideoFiles.id] = videoFileModel 212 this.videoFileMemo[id] = videoFileModel
198 } 213 }
199 214
200 private addStreamingPlaylist (row: any, videoModel: VideoModel) { 215 private addStreamingPlaylist (row: SQLRow, videoModel: VideoModel) {
201 if (!row.VideoStreamingPlaylists?.id || this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]) return 216 const id = row['VideoStreamingPlaylists.id']
217 if (!id || this.videoStreamingPlaylistMemo[id]) return
202 218
203 const attributes = pick(row.VideoStreamingPlaylists, this.videoAttributes.getStreamingPlaylistAttributes()) 219 const attributes = this.grab(row, this.tables.getStreamingPlaylistAttributes(), 'VideoStreamingPlaylists')
204 const streamingPlaylist = new VideoStreamingPlaylistModel(attributes, this.buildOpts) 220 const streamingPlaylist = new VideoStreamingPlaylistModel(attributes, this.buildOpts)
205 streamingPlaylist.VideoFiles = [] 221 streamingPlaylist.VideoFiles = []
206 222
207 videoModel.VideoStreamingPlaylists.push(streamingPlaylist) 223 videoModel.VideoStreamingPlaylists.push(streamingPlaylist)
208 224
209 this.videoStreamingPlaylistMemo[streamingPlaylist.id] = streamingPlaylist 225 this.videoStreamingPlaylistMemo[id] = streamingPlaylist
210 } 226 }
211 227
212 private addStreamingPlaylistFile (row: any) { 228 private addStreamingPlaylistFile (row: SQLRow) {
213 if (!row.VideoStreamingPlaylists?.VideoFiles?.id || this.videoFileMemo[row.VideoStreamingPlaylists.VideoFiles.id]) return 229 const id = row['VideoStreamingPlaylists.VideoFiles.id']
230 if (!id || this.videoFileMemo[id]) return
214 231
215 const streamingPlaylist = this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id] 232 const streamingPlaylist = this.videoStreamingPlaylistMemo[row['VideoStreamingPlaylists.id']]
216 233
217 const attributes = pick(row.VideoStreamingPlaylists.VideoFiles, this.videoAttributes.getFileAttributes()) 234 const attributes = this.grab(row, this.tables.getFileAttributes(), 'VideoStreamingPlaylists.VideoFiles')
218 const videoFileModel = new VideoFileModel(attributes, this.buildOpts) 235 const videoFileModel = new VideoFileModel(attributes, this.buildOpts)
219 streamingPlaylist.VideoFiles.push(videoFileModel) 236 streamingPlaylist.VideoFiles.push(videoFileModel)
220 237
221 this.videoFileMemo[row.VideoStreamingPlaylists.VideoFiles.id] = videoFileModel 238 this.videoFileMemo[id] = videoFileModel
222 } 239 }
223 240
224 private addRedundancy (redundancyRow: any, to: VideoFileModel | VideoStreamingPlaylistModel) { 241 private addRedundancy (row: SQLRow, prefix: string, to: VideoFileModel | VideoStreamingPlaylistModel) {
225 if (!to.RedundancyVideos) to.RedundancyVideos = [] 242 if (!to.RedundancyVideos) to.RedundancyVideos = []
226 243
227 if (!redundancyRow?.id || this.redundancyDone.has(redundancyRow.id)) return 244 const redundancyPrefix = `${prefix}.RedundancyVideos`
245 const id = row[`${redundancyPrefix}.id`]
246
247 if (!id || this.redundancyDone.has(id)) return
228 248
229 const attributes = pick(redundancyRow, this.videoAttributes.getRedundancyAttributes()) 249 const attributes = this.grab(row, this.tables.getRedundancyAttributes(), redundancyPrefix)
230 const redundancyModel = new VideoRedundancyModel(attributes, this.buildOpts) 250 const redundancyModel = new VideoRedundancyModel(attributes, this.buildOpts)
231 to.RedundancyVideos.push(redundancyModel) 251 to.RedundancyVideos.push(redundancyModel)
232 252
233 this.redundancyDone.add(redundancyRow.id) 253 this.redundancyDone.add(id)
234 } 254 }
235 255
236 private addTag (row: any, videoModel: VideoModel) { 256 private addTag (row: SQLRow, videoModel: VideoModel) {
237 if (!row.Tags?.name) return 257 if (!row['Tags.name']) return
238 const association = row.Tags.VideoTagModel
239 258
240 const key = `${association.videoId}-${association.tagId}` 259 const key = `${row['Tags.VideoTagModel.videoId']}-${row['Tags.VideoTagModel.tagId']}`
241 if (this.tagsDone.has(key)) return 260 if (this.tagsDone.has(key)) return
242 261
243 const attributes = pick(row.Tags, this.videoAttributes.getTagAttributes()) 262 const attributes = this.grab(row, this.tables.getTagAttributes(), 'Tags')
244 const tagModel = new TagModel(attributes, this.buildOpts) 263 const tagModel = new TagModel(attributes, this.buildOpts)
245 videoModel.Tags.push(tagModel) 264 videoModel.Tags.push(tagModel)
246 265
247 this.tagsDone.add(key) 266 this.tagsDone.add(key)
248 } 267 }
249 268
250 private addTracker (row: any, videoModel: VideoModel) { 269 private addTracker (row: SQLRow, videoModel: VideoModel) {
251 if (!row.Trackers?.id) return 270 if (!row['Trackers.id']) return
252 const association = row.Trackers.VideoTrackerModel
253 271
254 const key = `${association.videoId}-${association.trackerId}` 272 const key = `${row['Trackers.VideoTrackerModel.videoId']}-${row['Trackers.VideoTrackerModel.trackerId']}`
255 if (this.trackersDone.has(key)) return 273 if (this.trackersDone.has(key)) return
256 274
257 const attributes = pick(row.Trackers, this.videoAttributes.getTrackerAttributes()) 275 const attributes = this.grab(row, this.tables.getTrackerAttributes(), 'Trackers')
258 const trackerModel = new TrackerModel(attributes, this.buildOpts) 276 const trackerModel = new TrackerModel(attributes, this.buildOpts)
259 videoModel.Trackers.push(trackerModel) 277 videoModel.Trackers.push(trackerModel)
260 278
261 this.trackersDone.add(key) 279 this.trackersDone.add(key)
262 } 280 }
263 281
264 private setBlacklisted (row: any, videoModel: VideoModel) { 282 private setBlacklisted (row: SQLRow, videoModel: VideoModel) {
265 if (!row.VideoBlacklist?.id) return 283 const id = row['VideoBlacklist.id']
266 if (this.blacklistDone.has(row.VideoBlacklist.id)) return 284 if (!id || this.blacklistDone.has(id)) return
267 285
268 const attributes = pick(row.VideoBlacklist, this.videoAttributes.getBlacklistedAttributes()) 286 const attributes = this.grab(row, this.tables.getBlacklistedAttributes(), 'VideoBlacklist')
269 videoModel.VideoBlacklist = new VideoBlacklistModel(attributes, this.buildOpts) 287 videoModel.VideoBlacklist = new VideoBlacklistModel(attributes, this.buildOpts)
270 288
271 this.blacklistDone.add(row.VideoBlacklist.id) 289 this.blacklistDone.add(id)
272 } 290 }
273 291
274 private setScheduleVideoUpdate (row: any, videoModel: VideoModel) { 292 private setScheduleVideoUpdate (row: SQLRow, videoModel: VideoModel) {
275 if (!row.ScheduleVideoUpdate?.id) return 293 const id = row['ScheduleVideoUpdate.id']
276 if (this.scheduleVideoUpdateDone.has(row.ScheduleVideoUpdate.id)) return 294 if (!id || this.scheduleVideoUpdateDone.has(id)) return
277 295
278 const attributes = pick(row.ScheduleVideoUpdate, this.videoAttributes.getScheduleUpdateAttributes()) 296 const attributes = this.grab(row, this.tables.getScheduleUpdateAttributes(), 'ScheduleVideoUpdate')
279 videoModel.ScheduleVideoUpdate = new ScheduleVideoUpdateModel(attributes, this.buildOpts) 297 videoModel.ScheduleVideoUpdate = new ScheduleVideoUpdateModel(attributes, this.buildOpts)
280 298
281 this.scheduleVideoUpdateDone.add(row.ScheduleVideoUpdate.id) 299 this.scheduleVideoUpdateDone.add(id)
282 } 300 }
283 301
284 private setLive (row: any, videoModel: VideoModel) { 302 private setLive (row: SQLRow, videoModel: VideoModel) {
285 if (!row.VideoLive?.id) return 303 const id = row['VideoLive.id']
286 if (this.liveDone.has(row.VideoLive.id)) return 304 if (!id || this.liveDone.has(id)) return
287 305
288 const attributes = pick(row.VideoLive, this.videoAttributes.getLiveAttributes()) 306 const attributes = this.grab(row, this.tables.getLiveAttributes(), 'VideoLive')
289 videoModel.VideoLive = new VideoLiveModel(attributes, this.buildOpts) 307 videoModel.VideoLive = new VideoLiveModel(attributes, this.buildOpts)
290 308
291 this.liveDone.add(row.ScheduleVideoUpdate.id) 309 this.liveDone.add(id)
310 }
311
312 private grab (row: SQLRow, attributes: string[], prefix: string) {
313 const result: { [ id: string ]: string | number } = {}
314
315 for (const a of attributes) {
316 const key = prefix
317 ? prefix + '.' + a
318 : a
319
320 result[a] = row[key]
321 }
322
323 return result
292 } 324 }
293} 325}