aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/redis.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-03-24 13:36:47 +0100
committerChocobozzz <chocobozzz@cpy.re>2022-04-15 09:49:35 +0200
commitb211106695bb82f6c32e53306081b5262c3d109d (patch)
treefa187de1c33b0956665f5362e29af6b0f6d8bb57 /server/lib/redis.ts
parent69d48ee30c9d47cddf0c3c047dc99a99dcb6e894 (diff)
downloadPeerTube-b211106695bb82f6c32e53306081b5262c3d109d.tar.gz
PeerTube-b211106695bb82f6c32e53306081b5262c3d109d.tar.zst
PeerTube-b211106695bb82f6c32e53306081b5262c3d109d.zip
Support video views/viewers stats in server
* Add "currentTime" and "event" body params to view endpoint * Merge watching and view endpoints * Introduce WatchAction AP activity * Add tables to store viewer information of local videos * Add endpoints to fetch video views/viewers stats of local videos * Refactor views/viewers handlers * Support "views" and "viewers" counters for both VOD and live videos
Diffstat (limited to 'server/lib/redis.ts')
-rw-r--r--server/lib/redis.ts68
1 files changed, 65 insertions, 3 deletions
diff --git a/server/lib/redis.ts b/server/lib/redis.ts
index c4c1fa443..b86aefa0e 100644
--- a/server/lib/redis.ts
+++ b/server/lib/redis.ts
@@ -249,6 +249,45 @@ class Redis {
249 ]) 249 ])
250 } 250 }
251 251
252 /* ************ Video viewers stats ************ */
253
254 getLocalVideoViewer (options: {
255 key?: string
256 // Or
257 ip?: string
258 videoId?: number
259 }) {
260 if (options.key) return this.getObject(options.key)
261
262 const { viewerKey } = this.generateLocalVideoViewerKeys(options.ip, options.videoId)
263
264 return this.getObject(viewerKey)
265 }
266
267 setLocalVideoViewer (ip: string, videoId: number, object: any) {
268 const { setKey, viewerKey } = this.generateLocalVideoViewerKeys(ip, videoId)
269
270 return Promise.all([
271 this.addToSet(setKey, viewerKey),
272 this.setObject(viewerKey, object)
273 ])
274 }
275
276 listLocalVideoViewerKeys () {
277 const { setKey } = this.generateLocalVideoViewerKeys()
278
279 return this.getSet(setKey)
280 }
281
282 deleteLocalVideoViewersKeys (key: string) {
283 const { setKey } = this.generateLocalVideoViewerKeys()
284
285 return Promise.all([
286 this.deleteFromSet(setKey, key),
287 this.deleteKey(key)
288 ])
289 }
290
252 /* ************ Resumable uploads final responses ************ */ 291 /* ************ Resumable uploads final responses ************ */
253 292
254 setUploadSession (uploadId: string, response?: { video: { id: number, shortUUID: string, uuid: string } }) { 293 setUploadSession (uploadId: string, response?: { video: { id: number, shortUUID: string, uuid: string } }) {
@@ -290,10 +329,18 @@ class Redis {
290 329
291 /* ************ Keys generation ************ */ 330 /* ************ Keys generation ************ */
292 331
293 private generateLocalVideoViewsKeys (videoId?: Number) { 332 private generateLocalVideoViewsKeys (videoId: number): { setKey: string, videoKey: string }
333 private generateLocalVideoViewsKeys (): { setKey: string }
334 private generateLocalVideoViewsKeys (videoId?: number) {
294 return { setKey: `local-video-views-buffer`, videoKey: `local-video-views-buffer-${videoId}` } 335 return { setKey: `local-video-views-buffer`, videoKey: `local-video-views-buffer-${videoId}` }
295 } 336 }
296 337
338 private generateLocalVideoViewerKeys (ip: string, videoId: number): { setKey: string, viewerKey: string }
339 private generateLocalVideoViewerKeys (): { setKey: string }
340 private generateLocalVideoViewerKeys (ip?: string, videoId?: number) {
341 return { setKey: `local-video-viewer-stats-keys`, viewerKey: `local-video-viewer-stats-${ip}-${videoId}` }
342 }
343
297 private generateVideoViewStatsKeys (options: { videoId?: number, hour?: number }) { 344 private generateVideoViewStatsKeys (options: { videoId?: number, hour?: number }) {
298 const hour = exists(options.hour) 345 const hour = exists(options.hour)
299 ? options.hour 346 ? options.hour
@@ -352,8 +399,23 @@ class Redis {
352 return this.client.del(this.prefix + key) 399 return this.client.del(this.prefix + key)
353 } 400 }
354 401
355 private async setValue (key: string, value: string, expirationMilliseconds: number) { 402 private async getObject (key: string) {
356 const result = await this.client.set(this.prefix + key, value, { PX: expirationMilliseconds }) 403 const value = await this.getValue(key)
404 if (!value) return null
405
406 return JSON.parse(value)
407 }
408
409 private setObject (key: string, value: { [ id: string ]: number | string }) {
410 return this.setValue(key, JSON.stringify(value))
411 }
412
413 private async setValue (key: string, value: string, expirationMilliseconds?: number) {
414 const options = expirationMilliseconds
415 ? { PX: expirationMilliseconds }
416 : {}
417
418 const result = await this.client.set(this.prefix + key, value, options)
357 419
358 if (result !== 'OK') throw new Error('Redis set result is not OK.') 420 if (result !== 'OK') throw new Error('Redis set result is not OK.')
359 } 421 }