Use global uuid instead of remoteId for videos
[oweals/peertube.git] / server / lib / request / request-video-event-scheduler.ts
1 import * as Sequelize from 'sequelize'
2
3 import { database as db } from '../../initializers/database'
4 import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
5 import {
6   REQUESTS_VIDEO_EVENT_LIMIT_PODS,
7   REQUESTS_VIDEO_EVENT_LIMIT_PER_POD,
8   REQUEST_VIDEO_EVENT_ENDPOINT
9 } from '../../initializers'
10 import { RequestsVideoEventGrouped } from '../../models'
11 import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType } from '../../../shared'
12
13 export type RequestVideoEventSchedulerOptions = {
14   type: RequestVideoEventType
15   videoId: number
16   count?: number
17   transaction?: Sequelize.Transaction
18 }
19
20 class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoEventGrouped> {
21   constructor () {
22     super()
23
24     // We limit the size of the requests
25     this.limitPods = REQUESTS_VIDEO_EVENT_LIMIT_PODS
26     this.limitPerPod = REQUESTS_VIDEO_EVENT_LIMIT_PER_POD
27
28     this.description = 'video event requests'
29   }
30
31   getRequestModel () {
32     return db.RequestVideoEvent
33   }
34
35   getRequestToPodModel () {
36     return db.RequestVideoEvent
37   }
38
39   buildRequestsObjects (eventRequests: RequestsVideoEventGrouped) {
40     const requestsToMakeGrouped: RequestsObjects<RemoteVideoEventRequest> = {}
41
42     /* Example:
43         {
44           pod1: {
45             video1: { views: 4, likes: 5 },
46             video2: { likes: 5 }
47           }
48         }
49     */
50     const eventsPerVideoPerPod: {
51       [ podId: string ]: {
52         [ videoUUID: string ]: {
53           views?: number
54           likes?: number
55           dislikes?: number
56         }
57       }
58     } = {}
59
60     // We group video events per video and per pod
61     // We add the counts of the same event types
62     Object.keys(eventRequests).forEach(toPodId => {
63       eventRequests[toPodId].forEach(eventToProcess => {
64         if (!eventsPerVideoPerPod[toPodId]) eventsPerVideoPerPod[toPodId] = {}
65
66         if (!requestsToMakeGrouped[toPodId]) {
67           requestsToMakeGrouped[toPodId] = {
68             toPod: eventToProcess.pod,
69             endpoint: REQUEST_VIDEO_EVENT_ENDPOINT,
70             ids: [], // request ids, to delete them from the DB in the future
71             datas: [] // requests data
72           }
73         }
74         requestsToMakeGrouped[toPodId].ids.push(eventToProcess.id)
75
76         const eventsPerVideo = eventsPerVideoPerPod[toPodId]
77         const uuid = eventToProcess.video.uuid
78         if (!eventsPerVideo[uuid]) eventsPerVideo[uuid] = {}
79
80         const events = eventsPerVideo[uuid]
81         if (!events[eventToProcess.type]) events[eventToProcess.type] = 0
82
83         events[eventToProcess.type] += eventToProcess.count
84       })
85     })
86
87     // Now we build our requests array per pod
88     Object.keys(eventsPerVideoPerPod).forEach(toPodId => {
89       const eventsForPod = eventsPerVideoPerPod[toPodId]
90
91       Object.keys(eventsForPod).forEach(uuid => {
92         const eventsForVideo = eventsForPod[uuid]
93
94         Object.keys(eventsForVideo).forEach(eventType => {
95           requestsToMakeGrouped[toPodId].datas.push({
96             data: {
97               uuid,
98               eventType: eventType as RemoteVideoEventType,
99               count: +eventsForVideo[eventType]
100             }
101           })
102         })
103       })
104     })
105
106     return requestsToMakeGrouped
107   }
108
109   createRequest ({ type, videoId, count, transaction }: RequestVideoEventSchedulerOptions) {
110     if (count === undefined) count = 1
111
112     const dbRequestOptions: Sequelize.CreateOptions = {}
113     if (transaction) dbRequestOptions.transaction = transaction
114
115     const createQuery = {
116       type,
117       count,
118       videoId
119     }
120
121     return db.RequestVideoEvent.create(createQuery, dbRequestOptions)
122   }
123 }
124
125 // ---------------------------------------------------------------------------
126
127 export {
128   RequestVideoEventScheduler
129 }