diff options
author | Chocobozzz <me@florianbigard.com> | 2021-11-09 10:11:20 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2021-11-09 15:00:31 +0100 |
commit | 51353d9a035fb6b81f903a8b5f391292841649fd (patch) | |
tree | 75acb6eea5e043bf2e15a6a5a92e9a3c5967b156 /server/controllers/api | |
parent | 221ee1adc916684d4881d2a9c4c01954dcde986e (diff) | |
download | PeerTube-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.ts | 44 |
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' | |||
2 | import toInt from 'validator/lib/toInt' | 2 | import toInt from 'validator/lib/toInt' |
3 | import { pickCommonVideoQuery } from '@server/helpers/query' | 3 | import { pickCommonVideoQuery } from '@server/helpers/query' |
4 | import { doJSONRequest } from '@server/helpers/requests' | 4 | import { doJSONRequest } from '@server/helpers/requests' |
5 | import { LiveManager } from '@server/lib/live' | 5 | import { VideoViews } from '@server/lib/video-views' |
6 | import { openapiOperationDoc } from '@server/middlewares/doc' | 6 | import { openapiOperationDoc } from '@server/middlewares/doc' |
7 | import { getServerActor } from '@server/models/application/application' | 7 | import { getServerActor } from '@server/models/application/application' |
8 | import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils' | 8 | import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils' |
@@ -17,7 +17,6 @@ import { sequelizeTypescript } from '../../../initializers/database' | |||
17 | import { sendView } from '../../../lib/activitypub/send/send-view' | 17 | import { sendView } from '../../../lib/activitypub/send/send-view' |
18 | import { JobQueue } from '../../../lib/job-queue' | 18 | import { JobQueue } from '../../../lib/job-queue' |
19 | import { Hooks } from '../../../lib/plugins/hooks' | 19 | import { Hooks } from '../../../lib/plugins/hooks' |
20 | import { Redis } from '../../../lib/redis' | ||
21 | import { | 20 | import { |
22 | asyncMiddleware, | 21 | asyncMiddleware, |
23 | asyncRetryTransactionMiddleware, | 22 | asyncRetryTransactionMiddleware, |
@@ -107,7 +106,7 @@ videosRouter.get('/:id', | |||
107 | ) | 106 | ) |
108 | videosRouter.post('/:id/views', | 107 | videosRouter.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 | ||
155 | async function viewVideo (req: express.Request, res: express.Response) { | 154 | async 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 | } |