mirror of https://github.com/Chocobozzz/PeerTube
Optimize views per day in video channels
parent
e74bda21d1
commit
5a61ffbb7c
|
@ -1,20 +1,20 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { body, param, query } from 'express-validator'
|
import { body, param, query } from 'express-validator'
|
||||||
|
import { VIDEO_CHANNELS } from '@server/initializers/constants'
|
||||||
|
import { MChannelAccountDefault, MUser } from '@server/typings/models'
|
||||||
import { UserRight } from '../../../../shared'
|
import { UserRight } from '../../../../shared'
|
||||||
|
import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor'
|
||||||
|
import { isBooleanValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
|
||||||
import {
|
import {
|
||||||
isVideoChannelDescriptionValid,
|
isVideoChannelDescriptionValid,
|
||||||
isVideoChannelNameValid,
|
isVideoChannelNameValid,
|
||||||
isVideoChannelSupportValid
|
isVideoChannelSupportValid
|
||||||
} from '../../../helpers/custom-validators/video-channels'
|
} from '../../../helpers/custom-validators/video-channels'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
|
import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../../../helpers/middlewares'
|
||||||
|
import { ActorModel } from '../../../models/activitypub/actor'
|
||||||
import { VideoChannelModel } from '../../../models/video/video-channel'
|
import { VideoChannelModel } from '../../../models/video/video-channel'
|
||||||
import { areValidationErrors } from '../utils'
|
import { areValidationErrors } from '../utils'
|
||||||
import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor'
|
|
||||||
import { ActorModel } from '../../../models/activitypub/actor'
|
|
||||||
import { isBooleanValid } from '../../../helpers/custom-validators/misc'
|
|
||||||
import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../../../helpers/middlewares'
|
|
||||||
import { MChannelAccountDefault, MUser } from '@server/typings/models'
|
|
||||||
import { VIDEO_CHANNELS } from '@server/initializers/constants'
|
|
||||||
|
|
||||||
const videoChannelsAddValidator = [
|
const videoChannelsAddValidator = [
|
||||||
body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'),
|
body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'),
|
||||||
|
@ -129,7 +129,10 @@ const localVideoChannelValidator = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const videoChannelStatsValidator = [
|
const videoChannelStatsValidator = [
|
||||||
query('withStats').optional().isBoolean().withMessage('Should have a valid stats flag'),
|
query('withStats')
|
||||||
|
.optional()
|
||||||
|
.customSanitizer(toBooleanOrNull)
|
||||||
|
.custom(isBooleanValid).withMessage('Should have a valid stats flag'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
|
@ -181,20 +181,16 @@ export type SummaryOptions = {
|
||||||
'days AS ( ' +
|
'days AS ( ' +
|
||||||
`SELECT generate_series(date_trunc('day', now()) - '${daysPrior} day'::interval, ` +
|
`SELECT generate_series(date_trunc('day', now()) - '${daysPrior} day'::interval, ` +
|
||||||
`date_trunc('day', now()), '1 day'::interval) AS day ` +
|
`date_trunc('day', now()), '1 day'::interval) AS day ` +
|
||||||
'), ' +
|
|
||||||
'views AS ( ' +
|
|
||||||
'SELECT v.* ' +
|
|
||||||
'FROM "videoView" AS v ' +
|
|
||||||
'INNER JOIN "video" ON "video"."id" = v."videoId" ' +
|
|
||||||
'WHERE "video"."channelId" = "VideoChannelModel"."id" ' +
|
|
||||||
') ' +
|
') ' +
|
||||||
'SELECT days.day AS day, ' +
|
'SELECT days.day AS day, COALESCE(SUM("videoView".views), 0) AS views ' +
|
||||||
'COALESCE(SUM(views.views), 0) AS views ' +
|
'FROM days ' +
|
||||||
'FROM days ' +
|
'LEFT JOIN (' +
|
||||||
`LEFT JOIN views ON date_trunc('day', "views"."startDate") = date_trunc('day', days.day) ` +
|
'"videoView" INNER JOIN "video" ON "videoView"."videoId" = "video"."id" ' +
|
||||||
'GROUP BY day ' +
|
'AND "video"."channelId" = "VideoChannelModel"."id"' +
|
||||||
'ORDER BY day ' +
|
`) ON date_trunc('day', "videoView"."startDate") = date_trunc('day', days.day) ` +
|
||||||
') t' +
|
'GROUP BY day ' +
|
||||||
|
'ORDER BY day ' +
|
||||||
|
') t' +
|
||||||
')'
|
')'
|
||||||
),
|
),
|
||||||
'viewsPerDay'
|
'viewsPerDay'
|
||||||
|
@ -413,7 +409,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
||||||
|
|
||||||
const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ]
|
const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ]
|
||||||
|
|
||||||
if (options.withStats) {
|
if (options.withStats === true) {
|
||||||
scopes.push({
|
scopes.push({
|
||||||
method: [ ScopeNames.WITH_STATS, { daysPrior: 30 } as AvailableWithStatsOptions ]
|
method: [ ScopeNames.WITH_STATS, { daysPrior: 30 } as AvailableWithStatsOptions ]
|
||||||
})
|
})
|
||||||
|
@ -560,7 +556,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
||||||
createdAt: this.createdAt,
|
createdAt: this.createdAt,
|
||||||
updatedAt: this.updatedAt,
|
updatedAt: this.updatedAt,
|
||||||
ownerAccount: undefined,
|
ownerAccount: undefined,
|
||||||
viewsPerDay: viewsPerDay !== undefined
|
viewsPerDay: viewsPerDay
|
||||||
? viewsPerDay.split(',').map(v => {
|
? viewsPerDay.split(',').map(v => {
|
||||||
const o = v.split('|')
|
const o = v.split('|')
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -366,6 +366,7 @@ describe('Test video channels', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should report correct channel statistics', async function () {
|
it('Should report correct channel statistics', async function () {
|
||||||
|
this.timeout(10000)
|
||||||
|
|
||||||
{
|
{
|
||||||
const res = await getAccountVideoChannelsList({
|
const res = await getAccountVideoChannelsList({
|
||||||
|
|
Loading…
Reference in New Issue