aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-11-09 10:11:20 +0100
committerChocobozzz <chocobozzz@cpy.re>2021-11-09 15:00:31 +0100
commit51353d9a035fb6b81f903a8b5f391292841649fd (patch)
tree75acb6eea5e043bf2e15a6a5a92e9a3c5967b156 /server/controllers/api
parent221ee1adc916684d4881d2a9c4c01954dcde986e (diff)
downloadPeerTube-51353d9a035fb6b81f903a8b5f391292841649fd.tar.gz
PeerTube-51353d9a035fb6b81f903a8b5f391292841649fd.tar.zst
PeerTube-51353d9a035fb6b81f903a8b5f391292841649fd.zip
Refactor video views
Introduce viewers attribute for live videos Count views for live videos Reduce delay to see the viewer update for lives Add ability to configure video views buffer interval and view ip expiration
Diffstat (limited to 'server/controllers/api')
-rw-r--r--server/controllers/api/videos/index.ts44
1 files changed, 8 insertions, 36 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 821161c64..72b382595 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -2,7 +2,7 @@ import express from 'express'
2import toInt from 'validator/lib/toInt' 2import toInt from 'validator/lib/toInt'
3import { pickCommonVideoQuery } from '@server/helpers/query' 3import { pickCommonVideoQuery } from '@server/helpers/query'
4import { doJSONRequest } from '@server/helpers/requests' 4import { doJSONRequest } from '@server/helpers/requests'
5import { LiveManager } from '@server/lib/live' 5import { VideoViews } from '@server/lib/video-views'
6import { openapiOperationDoc } from '@server/middlewares/doc' 6import { openapiOperationDoc } from '@server/middlewares/doc'
7import { getServerActor } from '@server/models/application/application' 7import { getServerActor } from '@server/models/application/application'
8import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils' 8import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils'
@@ -17,7 +17,6 @@ import { sequelizeTypescript } from '../../../initializers/database'
17import { sendView } from '../../../lib/activitypub/send/send-view' 17import { sendView } from '../../../lib/activitypub/send/send-view'
18import { JobQueue } from '../../../lib/job-queue' 18import { JobQueue } from '../../../lib/job-queue'
19import { Hooks } from '../../../lib/plugins/hooks' 19import { Hooks } from '../../../lib/plugins/hooks'
20import { Redis } from '../../../lib/redis'
21import { 20import {
22 asyncMiddleware, 21 asyncMiddleware,
23 asyncRetryTransactionMiddleware, 22 asyncRetryTransactionMiddleware,
@@ -107,7 +106,7 @@ videosRouter.get('/:id',
107) 106)
108videosRouter.post('/:id/views', 107videosRouter.post('/:id/views',
109 openapiOperationDoc({ operationId: 'addView' }), 108 openapiOperationDoc({ operationId: 'addView' }),
110 asyncMiddleware(videosCustomGetValidator('only-immutable-attributes')), 109 asyncMiddleware(videosCustomGetValidator('only-video')),
111 asyncMiddleware(viewVideo) 110 asyncMiddleware(viewVideo)
112) 111)
113 112
@@ -153,44 +152,17 @@ function getVideo (_req: express.Request, res: express.Response) {
153} 152}
154 153
155async function viewVideo (req: express.Request, res: express.Response) { 154async function viewVideo (req: express.Request, res: express.Response) {
156 const immutableVideoAttrs = res.locals.onlyImmutableVideo 155 const video = res.locals.onlyVideo
157 156
158 const ip = req.ip 157 const ip = req.ip
159 const exists = await Redis.Instance.doesVideoIPViewExist(ip, immutableVideoAttrs.uuid) 158 const success = await VideoViews.Instance.processView({ video, ip })
160 if (exists) {
161 logger.debug('View for ip %s and video %s already exists.', ip, immutableVideoAttrs.uuid)
162 return res.status(HttpStatusCode.NO_CONTENT_204).end()
163 }
164
165 const video = await VideoModel.load(immutableVideoAttrs.id)
166
167 const promises: Promise<any>[] = [
168 Redis.Instance.setIPVideoView(ip, video.uuid, video.isLive)
169 ]
170
171 let federateView = true
172
173 // Increment our live manager
174 if (video.isLive && video.isOwned()) {
175 LiveManager.Instance.addViewTo(video.id)
176
177 // Views of our local live will be sent by our live manager
178 federateView = false
179 }
180
181 // Increment our video views cache counter
182 if (!video.isLive) {
183 promises.push(Redis.Instance.addVideoView(video.id))
184 }
185 159
186 if (federateView) { 160 if (success) {
187 const serverActor = await getServerActor() 161 const serverActor = await getServerActor()
188 promises.push(sendView(serverActor, video, undefined)) 162 await sendView(serverActor, video, undefined)
189 }
190
191 await Promise.all(promises)
192 163
193 Hooks.runAction('action:api.video.viewed', { video, ip }) 164 Hooks.runAction('action:api.video.viewed', { video: video, ip })
165 }
194 166
195 return res.status(HttpStatusCode.NO_CONTENT_204).end() 167 return res.status(HttpStatusCode.NO_CONTENT_204).end()
196} 168}