Optimize SQL query that fetch actor outbox

This commit is contained in:
Chocobozzz 2018-01-18 15:22:36 +01:00
parent 54e740594b
commit 2c897999fe
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
4 changed files with 77 additions and 27 deletions

View File

@ -212,7 +212,13 @@ function saveActorAndServerAndModelIfNotExist (
// Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists // Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists
// (which could be false in a retried query) // (which could be false in a retried query)
const actorCreated = await ActorModel.create(actor.toJSON(), { transaction: t }) const [ actorCreated ] = await ActorModel.findOrCreate({
defaults: actor.toJSON(),
where: {
url: actor.url
},
transaction: t
})
if (actorCreated.type === 'Person' || actorCreated.type === 'Application') { if (actorCreated.type === 'Person' || actorCreated.type === 'Application') {
const account = await saveAccount(actorCreated, result, t) const account = await saveAccount(actorCreated, result, t)
@ -284,24 +290,36 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu
} }
} }
function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) { async function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) {
const account = new AccountModel({ const [ accountCreated ] = await AccountModel.findOrCreate({
name: result.name, defaults: {
actorId: actor.id name: result.name,
actorId: actor.id
},
where: {
actorId: actor.id
},
transaction: t
}) })
return account.save({ transaction: t }) return accountCreated
} }
async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResult, ownerActor: ActorModel, t: Transaction) { async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResult, ownerActor: ActorModel, t: Transaction) {
const videoChannel = new VideoChannelModel({ const [ videoChannelCreated ] = await VideoChannelModel.findOrCreate({
name: result.name, defaults: {
description: result.summary, name: result.name,
actorId: actor.id, description: result.summary,
accountId: ownerActor.Account.id actorId: actor.id,
accountId: ownerActor.Account.id
},
where: {
actorId: actor.id
},
transaction: t
}) })
return videoChannel.save({ transaction: t }) return videoChannelCreated
} }
async function refreshActorIfNeeded (actor: ActorModel) { async function refreshActorIfNeeded (actor: ActorModel) {

View File

@ -459,7 +459,8 @@ export class VideoModel extends Model<VideoModel> {
}, },
include: [ include: [
{ {
model: VideoShareModel, attributes: [ 'id' ],
model: VideoShareModel.unscoped(),
required: false, required: false,
where: { where: {
[Sequelize.Op.and]: [ [Sequelize.Op.and]: [
@ -475,28 +476,65 @@ export class VideoModel extends Model<VideoModel> {
}, },
include: [ include: [
{ {
model: ActorModel, attributes: [ 'id', 'url' ],
required: true model: ActorModel.unscoped()
} }
] ]
}, },
{ {
model: VideoChannelModel, model: VideoChannelModel.unscoped(),
required: true, required: true,
include: [ include: [
{ {
model: AccountModel, attributes: [ 'name' ],
model: AccountModel.unscoped(),
required: true,
include: [
{
attributes: [ 'id', 'url' ],
model: ActorModel.unscoped(),
required: true
}
]
},
{
attributes: [ 'id', 'url' ],
model: ActorModel.unscoped(),
required: true required: true
} }
] ]
}, },
{ {
attributes: [ 'type' ],
model: AccountVideoRateModel, model: AccountVideoRateModel,
include: [ AccountModel ] required: false,
include: [
{
attributes: [ 'id' ],
model: AccountModel.unscoped(),
include: [
{
attributes: [ 'url' ],
model: ActorModel.unscoped(),
include: [
{
attributes: [ 'host' ],
model: ServerModel,
required: false
}
]
}
]
}
]
},
{
attributes: [ 'url' ],
model: VideoCommentModel,
required: false
}, },
VideoFileModel, VideoFileModel,
TagModel, TagModel
VideoCommentModel
] ]
} }

View File

@ -4,7 +4,7 @@ import * as chai from 'chai'
import 'mocha' import 'mocha'
import { Video, VideoPrivacy } from '../../../../shared/models/videos' import { Video, VideoPrivacy } from '../../../../shared/models/videos'
import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
import { checkVideoFilesWereRemoved, completeVideoCheck } from '../../utils' import { completeVideoCheck } from '../../utils'
import { import {
flushAndRunMultipleServers, flushTests, getVideosList, killallServers, ServerInfo, setAccessTokensToServers, uploadVideo, flushAndRunMultipleServers, flushTests, getVideosList, killallServers, ServerInfo, setAccessTokensToServers, uploadVideo,
@ -353,8 +353,6 @@ describe('Test follows', function () {
let res = await getVideosList(servers[ 0 ].url) let res = await getVideosList(servers[ 0 ].url)
expect(res.body.total).to.equal(1) expect(res.body.total).to.equal(1)
await checkVideoFilesWereRemoved(video4.uuid, servers[0].serverNumber)
}) })
}) })

View File

@ -187,10 +187,6 @@ describe('Test handle downs', function () {
await wait(5000) await wait(5000)
const res = await getVideosList(servers[1].url)
expect(res.body.data).to.be.an('array')
expect(res.body.data).to.have.lengthOf(2)
const resVideo = await getVideo(servers[1].url, videos[0].uuid) const resVideo = await getVideo(servers[1].url, videos[0].uuid)
expect(resVideo.body).not.to.be.undefined expect(resVideo.body).not.to.be.undefined