diff options
author | Chocobozzz <me@florianbigard.com> | 2021-06-11 10:59:27 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-06-11 11:15:44 +0200 |
commit | 17bb45388ec319d288a1b8387c6c199fe2f6b64f (patch) | |
tree | 96a6b331ce1766eced50f78ab3ce0ed9197d8833 | |
parent | ca4b4b2e5590c1b37cff1fe1be7f797b93351229 (diff) | |
download | PeerTube-17bb45388ec319d288a1b8387c6c199fe2f6b64f.tar.gz PeerTube-17bb45388ec319d288a1b8387c6c199fe2f6b64f.tar.zst PeerTube-17bb45388ec319d288a1b8387c6c199fe2f6b64f.zip |
Optimize rows parsing
-rw-r--r-- | server/models/video/sql/shared/abstract-videos-model-query-builder.ts | 46 | ||||
-rw-r--r-- | server/models/video/sql/shared/abstract-videos-query-builder.ts | 4 | ||||
-rw-r--r-- | server/models/video/sql/shared/video-file-query-builder.ts | 4 | ||||
-rw-r--r-- | server/models/video/sql/shared/video-model-builder.ts | 224 | ||||
-rw-r--r-- | server/models/video/sql/shared/video-tables.ts (renamed from server/models/video/sql/shared/video-attributes.ts) | 5 | ||||
-rw-r--r-- | server/models/video/sql/video-model-get-query-builder.ts | 8 | ||||
-rw-r--r-- | server/models/video/sql/videos-model-list-query-builder.ts | 4 |
7 files changed, 164 insertions, 131 deletions
diff --git a/server/models/video/sql/shared/abstract-videos-model-query-builder.ts b/server/models/video/sql/shared/abstract-videos-model-query-builder.ts index 8ed207eea..8eff59db0 100644 --- a/server/models/video/sql/shared/abstract-videos-model-query-builder.ts +++ b/server/models/video/sql/shared/abstract-videos-model-query-builder.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import validator from 'validator' | 1 | import validator from 'validator' |
2 | import { AbstractVideosQueryBuilder } from './abstract-videos-query-builder' | 2 | import { AbstractVideosQueryBuilder } from './abstract-videos-query-builder' |
3 | import { VideoAttributes } from './video-attributes' | 3 | import { VideoTables } from './video-tables' |
4 | 4 | ||
5 | /** | 5 | /** |
6 | * | 6 | * |
@@ -13,12 +13,12 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
13 | protected joins: string[] = [] | 13 | protected joins: string[] = [] |
14 | protected where: string | 14 | protected where: string |
15 | 15 | ||
16 | protected videoAttributes: VideoAttributes | 16 | protected tables: VideoTables |
17 | 17 | ||
18 | constructor (protected readonly mode: 'list' | 'get') { | 18 | constructor (protected readonly mode: 'list' | 'get') { |
19 | super() | 19 | super() |
20 | 20 | ||
21 | this.videoAttributes = new VideoAttributes(this.mode) | 21 | this.tables = new VideoTables(this.mode) |
22 | } | 22 | } |
23 | 23 | ||
24 | protected buildSelect () { | 24 | protected buildSelect () { |
@@ -44,7 +44,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
44 | this.attributes = { | 44 | this.attributes = { |
45 | ...this.attributes, | 45 | ...this.attributes, |
46 | 46 | ||
47 | ...this.buildAttributesObject('VideoChannel', this.videoAttributes.getChannelAttributes()), | 47 | ...this.buildAttributesObject('VideoChannel', this.tables.getChannelAttributes()), |
48 | ...this.buildActorInclude('VideoChannel->Actor'), | 48 | ...this.buildActorInclude('VideoChannel->Actor'), |
49 | ...this.buildAvatarInclude('VideoChannel->Actor->Avatar'), | 49 | ...this.buildAvatarInclude('VideoChannel->Actor->Avatar'), |
50 | ...this.buildServerInclude('VideoChannel->Actor->Server') | 50 | ...this.buildServerInclude('VideoChannel->Actor->Server') |
@@ -66,7 +66,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
66 | this.attributes = { | 66 | this.attributes = { |
67 | ...this.attributes, | 67 | ...this.attributes, |
68 | 68 | ||
69 | ...this.buildAttributesObject('VideoChannel->Account', this.videoAttributes.getAccountAttributes()), | 69 | ...this.buildAttributesObject('VideoChannel->Account', this.tables.getAccountAttributes()), |
70 | ...this.buildActorInclude('VideoChannel->Account->Actor'), | 70 | ...this.buildActorInclude('VideoChannel->Account->Actor'), |
71 | ...this.buildAvatarInclude('VideoChannel->Account->Actor->Avatar'), | 71 | ...this.buildAvatarInclude('VideoChannel->Account->Actor->Avatar'), |
72 | ...this.buildServerInclude('VideoChannel->Account->Actor->Server') | 72 | ...this.buildServerInclude('VideoChannel->Account->Actor->Server') |
@@ -79,7 +79,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
79 | this.attributes = { | 79 | this.attributes = { |
80 | ...this.attributes, | 80 | ...this.attributes, |
81 | 81 | ||
82 | ...this.buildAttributesObject('Thumbnails', this.videoAttributes.getThumbnailAttributes()) | 82 | ...this.buildAttributesObject('Thumbnails', this.tables.getThumbnailAttributes()) |
83 | } | 83 | } |
84 | } | 84 | } |
85 | 85 | ||
@@ -90,7 +90,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
90 | this.attributes = { | 90 | this.attributes = { |
91 | ...this.attributes, | 91 | ...this.attributes, |
92 | 92 | ||
93 | ...this.buildAttributesObject('VideoFiles', this.videoAttributes.getFileAttributes()) | 93 | ...this.buildAttributesObject('VideoFiles', this.tables.getFileAttributes()) |
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
@@ -107,8 +107,8 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
107 | this.attributes = { | 107 | this.attributes = { |
108 | ...this.attributes, | 108 | ...this.attributes, |
109 | 109 | ||
110 | ...this.buildAttributesObject('VideoStreamingPlaylists', this.videoAttributes.getStreamingPlaylistAttributes()), | 110 | ...this.buildAttributesObject('VideoStreamingPlaylists', this.tables.getStreamingPlaylistAttributes()), |
111 | ...this.buildAttributesObject('VideoStreamingPlaylists->VideoFiles', this.videoAttributes.getFileAttributes()) | 111 | ...this.buildAttributesObject('VideoStreamingPlaylists->VideoFiles', this.tables.getFileAttributes()) |
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
@@ -123,7 +123,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
123 | this.attributes = { | 123 | this.attributes = { |
124 | ...this.attributes, | 124 | ...this.attributes, |
125 | 125 | ||
126 | ...this.buildAttributesObject('userVideoHistory', this.videoAttributes.getUserHistoryAttributes()) | 126 | ...this.buildAttributesObject('userVideoHistory', this.tables.getUserHistoryAttributes()) |
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
@@ -138,7 +138,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
138 | this.attributes = { | 138 | this.attributes = { |
139 | ...this.attributes, | 139 | ...this.attributes, |
140 | 140 | ||
141 | ...this.buildAttributesObject('VideoPlaylistElement', this.videoAttributes.getPlaylistAttributes()) | 141 | ...this.buildAttributesObject('VideoPlaylistElement', this.tables.getPlaylistAttributes()) |
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
@@ -153,8 +153,8 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
153 | this.attributes = { | 153 | this.attributes = { |
154 | ...this.attributes, | 154 | ...this.attributes, |
155 | 155 | ||
156 | ...this.buildAttributesObject('Tags', this.videoAttributes.getTagAttributes()), | 156 | ...this.buildAttributesObject('Tags', this.tables.getTagAttributes()), |
157 | ...this.buildAttributesObject('Tags->VideoTagModel', this.videoAttributes.getVideoTagAttributes()) | 157 | ...this.buildAttributesObject('Tags->VideoTagModel', this.tables.getVideoTagAttributes()) |
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
@@ -166,7 +166,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
166 | this.attributes = { | 166 | this.attributes = { |
167 | ...this.attributes, | 167 | ...this.attributes, |
168 | 168 | ||
169 | ...this.buildAttributesObject('VideoBlacklist', this.videoAttributes.getBlacklistedAttributes()) | 169 | ...this.buildAttributesObject('VideoBlacklist', this.tables.getBlacklistedAttributes()) |
170 | } | 170 | } |
171 | } | 171 | } |
172 | 172 | ||
@@ -178,7 +178,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
178 | this.attributes = { | 178 | this.attributes = { |
179 | ...this.attributes, | 179 | ...this.attributes, |
180 | 180 | ||
181 | ...this.buildAttributesObject('ScheduleVideoUpdate', this.videoAttributes.getScheduleUpdateAttributes()) | 181 | ...this.buildAttributesObject('ScheduleVideoUpdate', this.tables.getScheduleUpdateAttributes()) |
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
@@ -190,7 +190,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
190 | this.attributes = { | 190 | this.attributes = { |
191 | ...this.attributes, | 191 | ...this.attributes, |
192 | 192 | ||
193 | ...this.buildAttributesObject('VideoLive', this.videoAttributes.getLiveAttributes()) | 193 | ...this.buildAttributesObject('VideoLive', this.tables.getLiveAttributes()) |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
@@ -205,8 +205,8 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
205 | this.attributes = { | 205 | this.attributes = { |
206 | ...this.attributes, | 206 | ...this.attributes, |
207 | 207 | ||
208 | ...this.buildAttributesObject('Trackers', this.videoAttributes.getTrackerAttributes()), | 208 | ...this.buildAttributesObject('Trackers', this.tables.getTrackerAttributes()), |
209 | ...this.buildAttributesObject('Trackers->VideoTrackerModel', this.videoAttributes.getVideoTrackerAttributes()) | 209 | ...this.buildAttributesObject('Trackers->VideoTrackerModel', this.tables.getVideoTrackerAttributes()) |
210 | } | 210 | } |
211 | } | 211 | } |
212 | 212 | ||
@@ -219,7 +219,7 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
219 | this.attributes = { | 219 | this.attributes = { |
220 | ...this.attributes, | 220 | ...this.attributes, |
221 | 221 | ||
222 | ...this.buildAttributesObject('VideoFiles->RedundancyVideos', this.videoAttributes.getRedundancyAttributes()) | 222 | ...this.buildAttributesObject('VideoFiles->RedundancyVideos', this.tables.getRedundancyAttributes()) |
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
@@ -232,20 +232,20 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder | |||
232 | this.attributes = { | 232 | this.attributes = { |
233 | ...this.attributes, | 233 | ...this.attributes, |
234 | 234 | ||
235 | ...this.buildAttributesObject('VideoStreamingPlaylists->RedundancyVideos', this.videoAttributes.getRedundancyAttributes()) | 235 | ...this.buildAttributesObject('VideoStreamingPlaylists->RedundancyVideos', this.tables.getRedundancyAttributes()) |
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | ||
239 | protected buildActorInclude (prefixKey: string) { | 239 | protected buildActorInclude (prefixKey: string) { |
240 | return this.buildAttributesObject(prefixKey, this.videoAttributes.getActorAttributes()) | 240 | return this.buildAttributesObject(prefixKey, this.tables.getActorAttributes()) |
241 | } | 241 | } |
242 | 242 | ||
243 | protected buildAvatarInclude (prefixKey: string) { | 243 | protected buildAvatarInclude (prefixKey: string) { |
244 | return this.buildAttributesObject(prefixKey, this.videoAttributes.getAvatarAttributes()) | 244 | return this.buildAttributesObject(prefixKey, this.tables.getAvatarAttributes()) |
245 | } | 245 | } |
246 | 246 | ||
247 | protected buildServerInclude (prefixKey: string) { | 247 | protected buildServerInclude (prefixKey: string) { |
248 | return this.buildAttributesObject(prefixKey, this.videoAttributes.getServerAttributes()) | 248 | return this.buildAttributesObject(prefixKey, this.tables.getServerAttributes()) |
249 | } | 249 | } |
250 | 250 | ||
251 | protected buildAttributesObject (prefixKey: string, attributeKeys: string[]) { | 251 | protected buildAttributesObject (prefixKey: string, attributeKeys: string[]) { |
diff --git a/server/models/video/sql/shared/abstract-videos-query-builder.ts b/server/models/video/sql/shared/abstract-videos-query-builder.ts index c1bbeb71e..7e67fa34f 100644 --- a/server/models/video/sql/shared/abstract-videos-query-builder.ts +++ b/server/models/video/sql/shared/abstract-videos-query-builder.ts | |||
@@ -13,14 +13,14 @@ export class AbstractVideosQueryBuilder { | |||
13 | protected query: string | 13 | protected query: string |
14 | protected replacements: any = {} | 14 | protected replacements: any = {} |
15 | 15 | ||
16 | protected runQuery (transaction?: Transaction, nest?: boolean) { | 16 | protected runQuery (transaction?: Transaction) { |
17 | logger.debug('Running videos query.', { query: this.query, replacements: this.replacements }) | 17 | logger.debug('Running videos query.', { query: this.query, replacements: this.replacements }) |
18 | 18 | ||
19 | const options = { | 19 | const options = { |
20 | transaction, | 20 | transaction, |
21 | replacements: this.replacements, | 21 | replacements: this.replacements, |
22 | type: QueryTypes.SELECT as QueryTypes.SELECT, | 22 | type: QueryTypes.SELECT as QueryTypes.SELECT, |
23 | nest | 23 | next: false |
24 | } | 24 | } |
25 | 25 | ||
26 | return this.sequelize.query<any>(this.query, options) | 26 | return this.sequelize.query<any>(this.query, options) |
diff --git a/server/models/video/sql/shared/video-file-query-builder.ts b/server/models/video/sql/shared/video-file-query-builder.ts index 29b11a298..ad47905c6 100644 --- a/server/models/video/sql/shared/video-file-query-builder.ts +++ b/server/models/video/sql/shared/video-file-query-builder.ts | |||
@@ -19,13 +19,13 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder { | |||
19 | queryWebTorrentVideos (options: BuildVideoGetQueryOptions) { | 19 | queryWebTorrentVideos (options: BuildVideoGetQueryOptions) { |
20 | this.buildWebtorrentFilesQuery(options) | 20 | this.buildWebtorrentFilesQuery(options) |
21 | 21 | ||
22 | return this.runQuery(options.transaction, true) | 22 | return this.runQuery(options.transaction) |
23 | } | 23 | } |
24 | 24 | ||
25 | queryStreamingPlaylistVideos (options: BuildVideoGetQueryOptions) { | 25 | queryStreamingPlaylistVideos (options: BuildVideoGetQueryOptions) { |
26 | this.buildVideoStreamingPlaylistFilesQuery(options) | 26 | this.buildVideoStreamingPlaylistFilesQuery(options) |
27 | 27 | ||
28 | return this.runQuery(options.transaction, true) | 28 | return this.runQuery(options.transaction) |
29 | } | 29 | } |
30 | 30 | ||
31 | private buildWebtorrentFilesQuery (options: BuildVideoGetQueryOptions) { | 31 | private buildWebtorrentFilesQuery (options: BuildVideoGetQueryOptions) { |
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 @@ | |||
1 | import { pick } from 'lodash' | 1 | |
2 | import { logger } from '@server/helpers/logger' | ||
2 | import { AccountModel } from '@server/models/account/account' | 3 | import { AccountModel } from '@server/models/account/account' |
3 | import { ActorModel } from '@server/models/actor/actor' | 4 | import { ActorModel } from '@server/models/actor/actor' |
4 | import { ActorImageModel } from '@server/models/actor/actor-image' | 5 | import { ActorImageModel } from '@server/models/actor/actor-image' |
@@ -15,7 +16,9 @@ import { VideoChannelModel } from '../../video-channel' | |||
15 | import { VideoFileModel } from '../../video-file' | 16 | import { VideoFileModel } from '../../video-file' |
16 | import { VideoLiveModel } from '../../video-live' | 17 | import { VideoLiveModel } from '../../video-live' |
17 | import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist' | 18 | import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist' |
18 | import { VideoAttributes } from './video-attributes' | 19 | import { VideoTables } from './video-tables' |
20 | |||
21 | type 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 | } |
diff --git a/server/models/video/sql/shared/video-attributes.ts b/server/models/video/sql/shared/video-tables.ts index e21b33c73..fddf1210c 100644 --- a/server/models/video/sql/shared/video-attributes.ts +++ b/server/models/video/sql/shared/video-tables.ts | |||
@@ -1,10 +1,10 @@ | |||
1 | 1 | ||
2 | /** | 2 | /** |
3 | * | 3 | * |
4 | * Class to build video attributes we want to fetch from the database | 4 | * Class to build video attributes/join names we want to fetch from the database |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | export class VideoAttributes { | 7 | export class VideoTables { |
8 | 8 | ||
9 | constructor (readonly mode: 'get' | 'list') { | 9 | constructor (readonly mode: 'get' | 'list') { |
10 | 10 | ||
@@ -199,6 +199,7 @@ export class VideoAttributes { | |||
199 | let attributeKeys = [ | 199 | let attributeKeys = [ |
200 | 'id', | 200 | 'id', |
201 | 'filename', | 201 | 'filename', |
202 | 'type', | ||
202 | 'fileUrl', | 203 | 'fileUrl', |
203 | 'onDisk', | 204 | 'onDisk', |
204 | 'createdAt', | 205 | 'createdAt', |
diff --git a/server/models/video/sql/video-model-get-query-builder.ts b/server/models/video/sql/video-model-get-query-builder.ts index 1a921d802..892639076 100644 --- a/server/models/video/sql/video-model-get-query-builder.ts +++ b/server/models/video/sql/video-model-get-query-builder.ts | |||
@@ -1,8 +1,8 @@ | |||
1 | import { Sequelize, Transaction } from 'sequelize' | 1 | import { Sequelize, Transaction } from 'sequelize' |
2 | import { AbstractVideosModelQueryBuilder } from './shared/abstract-videos-model-query-builder' | 2 | import { AbstractVideosModelQueryBuilder } from './shared/abstract-videos-model-query-builder' |
3 | import { VideoAttributes } from './shared/video-attributes' | ||
4 | import { VideoFileQueryBuilder } from './shared/video-file-query-builder' | 3 | import { VideoFileQueryBuilder } from './shared/video-file-query-builder' |
5 | import { VideoModelBuilder } from './shared/video-model-builder' | 4 | import { VideoModelBuilder } from './shared/video-model-builder' |
5 | import { VideoTables } from './shared/video-tables' | ||
6 | 6 | ||
7 | /** | 7 | /** |
8 | * | 8 | * |
@@ -29,7 +29,7 @@ export class VideosModelGetQueryBuilder { | |||
29 | this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) | 29 | this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) |
30 | this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) | 30 | this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) |
31 | 31 | ||
32 | this.videoModelBuilder = new VideoModelBuilder('get', new VideoAttributes('get')) | 32 | this.videoModelBuilder = new VideoModelBuilder('get', new VideoTables('get')) |
33 | } | 33 | } |
34 | 34 | ||
35 | async queryVideos (options: BuildVideoGetQueryOptions) { | 35 | async queryVideos (options: BuildVideoGetQueryOptions) { |
@@ -64,7 +64,7 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuild | |||
64 | queryVideos (options: BuildVideoGetQueryOptions) { | 64 | queryVideos (options: BuildVideoGetQueryOptions) { |
65 | this.buildMainGetQuery(options) | 65 | this.buildMainGetQuery(options) |
66 | 66 | ||
67 | return this.runQuery(options.transaction, true) | 67 | return this.runQuery(options.transaction) |
68 | } | 68 | } |
69 | 69 | ||
70 | private buildMainGetQuery (options: BuildVideoGetQueryOptions) { | 70 | private buildMainGetQuery (options: BuildVideoGetQueryOptions) { |
@@ -102,6 +102,6 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuild | |||
102 | const order = 'ORDER BY "Tags"."name" ASC' | 102 | const order = 'ORDER BY "Tags"."name" ASC' |
103 | const from = `SELECT * FROM "video" ${this.where} LIMIT 1` | 103 | const from = `SELECT * FROM "video" ${this.where} LIMIT 1` |
104 | 104 | ||
105 | return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins.join(' ')} ${this.where} ${order}` | 105 | return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins.join(' ')} ${order}` |
106 | } | 106 | } |
107 | } | 107 | } |
diff --git a/server/models/video/sql/videos-model-list-query-builder.ts b/server/models/video/sql/videos-model-list-query-builder.ts index acb76d80a..459f542a4 100644 --- a/server/models/video/sql/videos-model-list-query-builder.ts +++ b/server/models/video/sql/videos-model-list-query-builder.ts | |||
@@ -21,14 +21,14 @@ export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder | |||
21 | constructor (protected readonly sequelize: Sequelize) { | 21 | constructor (protected readonly sequelize: Sequelize) { |
22 | super('list') | 22 | super('list') |
23 | 23 | ||
24 | this.videoModelBuilder = new VideoModelBuilder(this.mode, this.videoAttributes) | 24 | this.videoModelBuilder = new VideoModelBuilder(this.mode, this.tables) |
25 | } | 25 | } |
26 | 26 | ||
27 | queryVideos (options: BuildVideosListQueryOptions) { | 27 | queryVideos (options: BuildVideosListQueryOptions) { |
28 | this.buildInnerQuery(options) | 28 | this.buildInnerQuery(options) |
29 | this.buildListQueryFromIdsQuery(options) | 29 | this.buildListQueryFromIdsQuery(options) |
30 | 30 | ||
31 | return this.runQuery(undefined, true).then(rows => this.videoModelBuilder.buildVideosFromRows(rows)) | 31 | return this.runQuery(undefined).then(rows => this.videoModelBuilder.buildVideosFromRows(rows)) |
32 | } | 32 | } |
33 | 33 | ||
34 | private buildInnerQuery (options: BuildVideosListQueryOptions) { | 34 | private buildInnerQuery (options: BuildVideosListQueryOptions) { |