aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-06-17 14:34:37 +0200
committerChocobozzz <me@florianbigard.com>2022-06-17 14:56:16 +0200
commitaa2ce188d102ab38452df316d06286040b5d9075 (patch)
tree100e639f21e9798d811639aa2e20abfa4c8d2bbf /server/lib
parentfba911e2c89708a166636e3a93fcd8fcbc3de7e1 (diff)
downloadPeerTube-aa2ce188d102ab38452df316d06286040b5d9075.tar.gz
PeerTube-aa2ce188d102ab38452df316d06286040b5d9075.tar.zst
PeerTube-aa2ce188d102ab38452df316d06286040b5d9075.zip
Optimize view endpoint
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/video.ts24
-rw-r--r--server/lib/views/shared/video-viewer-counters.ts8
-rw-r--r--server/lib/views/shared/video-viewer-stats.ts6
-rw-r--r--server/lib/views/shared/video-views.ts17
-rw-r--r--server/lib/views/video-views-manager.ts4
5 files changed, 41 insertions, 18 deletions
diff --git a/server/lib/video.ts b/server/lib/video.ts
index a98e45c60..86718abbe 100644
--- a/server/lib/video.ts
+++ b/server/lib/video.ts
@@ -1,6 +1,6 @@
1import { UploadFiles } from 'express' 1import { UploadFiles } from 'express'
2import { Transaction } from 'sequelize/types' 2import { Transaction } from 'sequelize/types'
3import { DEFAULT_AUDIO_RESOLUTION, JOB_PRIORITY } from '@server/initializers/constants' 3import { DEFAULT_AUDIO_RESOLUTION, JOB_PRIORITY, MEMOIZE_LENGTH, MEMOIZE_TTL } from '@server/initializers/constants'
4import { TagModel } from '@server/models/video/tag' 4import { TagModel } from '@server/models/video/tag'
5import { VideoModel } from '@server/models/video/video' 5import { VideoModel } from '@server/models/video/video'
6import { VideoJobInfoModel } from '@server/models/video/video-job-info' 6import { VideoJobInfoModel } from '@server/models/video/video-job-info'
@@ -10,6 +10,7 @@ import { ThumbnailType, VideoCreate, VideoPrivacy, VideoState, VideoTranscodingP
10import { CreateJobOptions, JobQueue } from './job-queue/job-queue' 10import { CreateJobOptions, JobQueue } from './job-queue/job-queue'
11import { updateVideoMiniatureFromExisting } from './thumbnail' 11import { updateVideoMiniatureFromExisting } from './thumbnail'
12import { CONFIG } from '@server/initializers/config' 12import { CONFIG } from '@server/initializers/config'
13import memoizee from 'memoizee'
13 14
14function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): FilteredModelAttributes<VideoModel> { 15function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): FilteredModelAttributes<VideoModel> {
15 return { 16 return {
@@ -150,6 +151,24 @@ async function addMoveToObjectStorageJob (options: {
150 151
151// --------------------------------------------------------------------------- 152// ---------------------------------------------------------------------------
152 153
154async function getVideoDuration (videoId: number | string) {
155 const video = await VideoModel.load(videoId)
156
157 const duration = video.isLive
158 ? undefined
159 : video.duration
160
161 return { duration, isLive: video.isLive }
162}
163
164const getCachedVideoDuration = memoizee(getVideoDuration, {
165 promise: true,
166 max: MEMOIZE_LENGTH.VIDEO_DURATION,
167 maxAge: MEMOIZE_TTL.VIDEO_DURATION
168})
169
170// ---------------------------------------------------------------------------
171
153export { 172export {
154 buildLocalVideoFromReq, 173 buildLocalVideoFromReq,
155 buildVideoThumbnailsFromReq, 174 buildVideoThumbnailsFromReq,
@@ -157,5 +176,6 @@ export {
157 addOptimizeOrMergeAudioJob, 176 addOptimizeOrMergeAudioJob,
158 addTranscodingJob, 177 addTranscodingJob,
159 addMoveToObjectStorageJob, 178 addMoveToObjectStorageJob,
160 getTranscodingJobPriority 179 getTranscodingJobPriority,
180 getCachedVideoDuration
161} 181}
diff --git a/server/lib/views/shared/video-viewer-counters.ts b/server/lib/views/shared/video-viewer-counters.ts
index 999ab7d8d..587621320 100644
--- a/server/lib/views/shared/video-viewer-counters.ts
+++ b/server/lib/views/shared/video-viewer-counters.ts
@@ -5,7 +5,7 @@ import { sendView } from '@server/lib/activitypub/send/send-view'
5import { PeerTubeSocket } from '@server/lib/peertube-socket' 5import { PeerTubeSocket } from '@server/lib/peertube-socket'
6import { getServerActor } from '@server/models/application/application' 6import { getServerActor } from '@server/models/application/application'
7import { VideoModel } from '@server/models/video/video' 7import { VideoModel } from '@server/models/video/video'
8import { MVideo } from '@server/types/models' 8import { MVideo, MVideoImmutable } from '@server/types/models'
9import { buildUUID, sha256 } from '@shared/extra-utils' 9import { buildUUID, sha256 } from '@shared/extra-utils'
10 10
11const lTags = loggerTagsFactory('views') 11const lTags = loggerTagsFactory('views')
@@ -33,7 +33,7 @@ export class VideoViewerCounters {
33 // --------------------------------------------------------------------------- 33 // ---------------------------------------------------------------------------
34 34
35 async addLocalViewer (options: { 35 async addLocalViewer (options: {
36 video: MVideo 36 video: MVideoImmutable
37 ip: string 37 ip: string
38 }) { 38 }) {
39 const { video, ip } = options 39 const { video, ip } = options
@@ -86,7 +86,7 @@ export class VideoViewerCounters {
86 // --------------------------------------------------------------------------- 86 // ---------------------------------------------------------------------------
87 87
88 private async addViewerToVideo (options: { 88 private async addViewerToVideo (options: {
89 video: MVideo 89 video: MVideoImmutable
90 viewerId: string 90 viewerId: string
91 viewerExpires?: Date 91 viewerExpires?: Date
92 }) { 92 }) {
@@ -162,7 +162,7 @@ export class VideoViewerCounters {
162 return sha256(this.salt + '-' + ip + '-' + videoUUID) 162 return sha256(this.salt + '-' + ip + '-' + videoUUID)
163 } 163 }
164 164
165 private async federateViewerIfNeeded (video: MVideo, viewer: Viewer) { 165 private async federateViewerIfNeeded (video: MVideoImmutable, viewer: Viewer) {
166 // Federate the viewer if it's been a "long" time we did not 166 // Federate the viewer if it's been a "long" time we did not
167 const now = new Date().getTime() 167 const now = new Date().getTime()
168 const federationLimit = now - (VIEW_LIFETIME.VIEWER_COUNTER / 2) 168 const federationLimit = now - (VIEW_LIFETIME.VIEWER_COUNTER / 2)
diff --git a/server/lib/views/shared/video-viewer-stats.ts b/server/lib/views/shared/video-viewer-stats.ts
index a9ba25b47..a56c20559 100644
--- a/server/lib/views/shared/video-viewer-stats.ts
+++ b/server/lib/views/shared/video-viewer-stats.ts
@@ -10,7 +10,7 @@ import { Redis } from '@server/lib/redis'
10import { VideoModel } from '@server/models/video/video' 10import { VideoModel } from '@server/models/video/video'
11import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer' 11import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer'
12import { LocalVideoViewerWatchSectionModel } from '@server/models/view/local-video-viewer-watch-section' 12import { LocalVideoViewerWatchSectionModel } from '@server/models/view/local-video-viewer-watch-section'
13import { MVideo } from '@server/types/models' 13import { MVideo, MVideoImmutable } from '@server/types/models'
14import { VideoViewEvent } from '@shared/models' 14import { VideoViewEvent } from '@shared/models'
15 15
16const lTags = loggerTagsFactory('views') 16const lTags = loggerTagsFactory('views')
@@ -41,7 +41,7 @@ export class VideoViewerStats {
41 // --------------------------------------------------------------------------- 41 // ---------------------------------------------------------------------------
42 42
43 async addLocalViewer (options: { 43 async addLocalViewer (options: {
44 video: MVideo 44 video: MVideoImmutable
45 currentTime: number 45 currentTime: number
46 ip: string 46 ip: string
47 viewEvent?: VideoViewEvent 47 viewEvent?: VideoViewEvent
@@ -64,7 +64,7 @@ export class VideoViewerStats {
64 // --------------------------------------------------------------------------- 64 // ---------------------------------------------------------------------------
65 65
66 private async updateLocalViewerStats (options: { 66 private async updateLocalViewerStats (options: {
67 video: MVideo 67 video: MVideoImmutable
68 ip: string 68 ip: string
69 currentTime: number 69 currentTime: number
70 viewEvent?: VideoViewEvent 70 viewEvent?: VideoViewEvent
diff --git a/server/lib/views/shared/video-views.ts b/server/lib/views/shared/video-views.ts
index 275f7a014..e563287e1 100644
--- a/server/lib/views/shared/video-views.ts
+++ b/server/lib/views/shared/video-views.ts
@@ -1,7 +1,8 @@
1import { logger, loggerTagsFactory } from '@server/helpers/logger' 1import { logger, loggerTagsFactory } from '@server/helpers/logger'
2import { sendView } from '@server/lib/activitypub/send/send-view' 2import { sendView } from '@server/lib/activitypub/send/send-view'
3import { getCachedVideoDuration } from '@server/lib/video'
3import { getServerActor } from '@server/models/application/application' 4import { getServerActor } from '@server/models/application/application'
4import { MVideo } from '@server/types/models' 5import { MVideo, MVideoImmutable } from '@server/types/models'
5import { buildUUID } from '@shared/extra-utils' 6import { buildUUID } from '@shared/extra-utils'
6import { Redis } from '../../redis' 7import { Redis } from '../../redis'
7 8
@@ -10,7 +11,7 @@ const lTags = loggerTagsFactory('views')
10export class VideoViews { 11export class VideoViews {
11 12
12 async addLocalView (options: { 13 async addLocalView (options: {
13 video: MVideo 14 video: MVideoImmutable
14 ip: string 15 ip: string
15 watchTime: number 16 watchTime: number
16 }) { 17 }) {
@@ -18,7 +19,7 @@ export class VideoViews {
18 19
19 logger.debug('Adding local view to video %s.', video.uuid, { watchTime, ...lTags(video.uuid) }) 20 logger.debug('Adding local view to video %s.', video.uuid, { watchTime, ...lTags(video.uuid) })
20 21
21 if (!this.hasEnoughWatchTime(video, watchTime)) return false 22 if (!await this.hasEnoughWatchTime(video, watchTime)) return false
22 23
23 const viewExists = await Redis.Instance.doesVideoIPViewExist(ip, video.uuid) 24 const viewExists = await Redis.Instance.doesVideoIPViewExist(ip, video.uuid)
24 if (viewExists) return false 25 if (viewExists) return false
@@ -46,7 +47,7 @@ export class VideoViews {
46 47
47 // --------------------------------------------------------------------------- 48 // ---------------------------------------------------------------------------
48 49
49 private async addView (video: MVideo) { 50 private async addView (video: MVideoImmutable) {
50 const promises: Promise<any>[] = [] 51 const promises: Promise<any>[] = []
51 52
52 if (video.isOwned()) { 53 if (video.isOwned()) {
@@ -58,10 +59,12 @@ export class VideoViews {
58 await Promise.all(promises) 59 await Promise.all(promises)
59 } 60 }
60 61
61 private hasEnoughWatchTime (video: MVideo, watchTime: number) { 62 private async hasEnoughWatchTime (video: MVideoImmutable, watchTime: number) {
62 if (video.isLive || video.duration >= 30) return watchTime >= 30 63 const { duration, isLive } = await getCachedVideoDuration(video.id)
64
65 if (isLive || duration >= 30) return watchTime >= 30
63 66
64 // Check more than 50% of the video is watched 67 // Check more than 50% of the video is watched
65 return video.duration / watchTime < 2 68 return duration / watchTime < 2
66 } 69 }
67} 70}
diff --git a/server/lib/views/video-views-manager.ts b/server/lib/views/video-views-manager.ts
index ea3b35c6c..86758e8d8 100644
--- a/server/lib/views/video-views-manager.ts
+++ b/server/lib/views/video-views-manager.ts
@@ -1,5 +1,5 @@
1import { logger, loggerTagsFactory } from '@server/helpers/logger' 1import { logger, loggerTagsFactory } from '@server/helpers/logger'
2import { MVideo } from '@server/types/models' 2import { MVideo, MVideoImmutable } from '@server/types/models'
3import { VideoViewEvent } from '@shared/models' 3import { VideoViewEvent } from '@shared/models'
4import { VideoViewerCounters, VideoViewerStats, VideoViews } from './shared' 4import { VideoViewerCounters, VideoViewerStats, VideoViews } from './shared'
5 5
@@ -41,7 +41,7 @@ export class VideoViewsManager {
41 } 41 }
42 42
43 async processLocalView (options: { 43 async processLocalView (options: {
44 video: MVideo 44 video: MVideoImmutable
45 currentTime: number 45 currentTime: number
46 ip: string | null 46 ip: string | null
47 viewEvent?: VideoViewEvent 47 viewEvent?: VideoViewEvent