Optimize list my playlists SQL query

pull/2396/head
Chocobozzz 2020-01-09 09:26:59 +01:00
parent 119b16e5ac
commit 6b0c3c7ca9
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
3 changed files with 36 additions and 23 deletions

View File

@ -42,6 +42,7 @@ export class VideoPlaylistService {
private videoExistsCache: { [ id: number ]: VideoExistInPlaylist[] } = {} private videoExistsCache: { [ id: number ]: VideoExistInPlaylist[] } = {}
private myAccountPlaylistCache: ResultList<CachedPlaylist> = undefined private myAccountPlaylistCache: ResultList<CachedPlaylist> = undefined
private myAccountPlaylistCacheRunning = false
private myAccountPlaylistCacheSubject = new Subject<ResultList<CachedPlaylist>>() private myAccountPlaylistCacheSubject = new Subject<ResultList<CachedPlaylist>>()
constructor ( constructor (
@ -78,12 +79,20 @@ export class VideoPlaylistService {
} }
listMyPlaylistWithCache (user: AuthUser, search?: string) { listMyPlaylistWithCache (user: AuthUser, search?: string) {
if (!search && this.myAccountPlaylistCache) return of(this.myAccountPlaylistCache) if (!search) {
if (this.myAccountPlaylistCacheRunning) return
if (this.myAccountPlaylistCache) return of(this.myAccountPlaylistCache)
}
this.myAccountPlaylistCacheRunning = true
return this.listAccountPlaylists(user.account, undefined, '-updatedAt', search) return this.listAccountPlaylists(user.account, undefined, '-updatedAt', search)
.pipe( .pipe(
tap(result => { tap(result => {
if (!search) this.myAccountPlaylistCache = result if (!search) {
this.myAccountPlaylistCacheRunning = false
this.myAccountPlaylistCache = result
}
}) })
) )
} }

View File

@ -133,9 +133,9 @@ async function listAccountPlaylists (req: express.Request, res: express.Response
const serverActor = await getServerActor() const serverActor = await getServerActor()
// Allow users to see their private/unlisted video playlists // Allow users to see their private/unlisted video playlists
let privateAndUnlisted = false let listMyPlaylists = false
if (res.locals.oauth && res.locals.oauth.token.User.Account.id === res.locals.account.id) { if (res.locals.oauth && res.locals.oauth.token.User.Account.id === res.locals.account.id) {
privateAndUnlisted = true listMyPlaylists = true
} }
const resultList = await VideoPlaylistModel.listForApi({ const resultList = await VideoPlaylistModel.listForApi({
@ -145,7 +145,7 @@ async function listAccountPlaylists (req: express.Request, res: express.Response
count: req.query.count, count: req.query.count,
sort: req.query.sort, sort: req.query.sort,
accountId: res.locals.account.id, accountId: res.locals.account.id,
privateAndUnlisted, listMyPlaylists,
type: req.query.playlistType type: req.query.playlistType
}) })

View File

@ -68,7 +68,7 @@ type AvailableForListOptions = {
type?: VideoPlaylistType type?: VideoPlaylistType
accountId?: number accountId?: number
videoChannelId?: number videoChannelId?: number
privateAndUnlisted?: boolean, listMyPlaylists?: boolean,
search?: string search?: string
} }
@ -124,27 +124,31 @@ type AvailableForListOptions = {
] ]
}, },
[ ScopeNames.AVAILABLE_FOR_LIST ]: (options: AvailableForListOptions) => { [ ScopeNames.AVAILABLE_FOR_LIST ]: (options: AvailableForListOptions) => {
// Only list local playlists OR playlists that are on an instance followed by actorId
const inQueryInstanceFollow = buildServerIdsFollowedBy(options.followerActorId) let whereActor: WhereOptions = {}
const whereActor = {
[ Op.or ]: [
{
serverId: null
},
{
serverId: {
[ Op.in ]: literal(inQueryInstanceFollow)
}
}
]
}
const whereAnd: WhereOptions[] = [] const whereAnd: WhereOptions[] = []
if (options.privateAndUnlisted !== true) { if (options.listMyPlaylists !== true) {
whereAnd.push({ whereAnd.push({
privacy: VideoPlaylistPrivacy.PUBLIC privacy: VideoPlaylistPrivacy.PUBLIC
}) })
// Only list local playlists OR playlists that are on an instance followed by actorId
const inQueryInstanceFollow = buildServerIdsFollowedBy(options.followerActorId)
whereActor = {
[ Op.or ]: [
{
serverId: null
},
{
serverId: {
[ Op.in ]: literal(inQueryInstanceFollow)
}
}
]
}
} }
if (options.accountId) { if (options.accountId) {
@ -301,7 +305,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
type?: VideoPlaylistType, type?: VideoPlaylistType,
accountId?: number, accountId?: number,
videoChannelId?: number, videoChannelId?: number,
privateAndUnlisted?: boolean, listMyPlaylists?: boolean,
search?: string search?: string
}) { }) {
const query = { const query = {
@ -319,7 +323,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
followerActorId: options.followerActorId, followerActorId: options.followerActorId,
accountId: options.accountId, accountId: options.accountId,
videoChannelId: options.videoChannelId, videoChannelId: options.videoChannelId,
privateAndUnlisted: options.privateAndUnlisted, listMyPlaylists: options.listMyPlaylists,
search: options.search search: options.search
} as AvailableForListOptions } as AvailableForListOptions
] ]