aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/request/request-video-event-scheduler.ts
blob: 8a008c51bbae9d3c15bb0bfc5152285c28c6c4e5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import * as Sequelize from 'sequelize'

import { database as db } from '../../initializers/database'
import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import {
  REQUESTS_VIDEO_EVENT_LIMIT_PODS,
  REQUESTS_VIDEO_EVENT_LIMIT_PER_POD,
  REQUEST_VIDEO_EVENT_ENDPOINT
} from '../../initializers'
import { RequestsVideoEventGrouped } from '../../models'
import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType } from '../../../shared'

export type RequestVideoEventSchedulerOptions = {
  type: RequestVideoEventType
  videoId: string
  count?: number
  transaction?: Sequelize.Transaction
}

class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoEventGrouped> {
  constructor () {
    super()

    // We limit the size of the requests
    this.limitPods = REQUESTS_VIDEO_EVENT_LIMIT_PODS
    this.limitPerPod = REQUESTS_VIDEO_EVENT_LIMIT_PER_POD

    this.description = 'video event requests'
  }

  getRequestModel () {
    return db.RequestVideoEvent
  }

  getRequestToPodModel () {
    return db.RequestVideoEvent
  }

  buildRequestsObjects (eventRequests: RequestsVideoEventGrouped) {
    const requestsToMakeGrouped: RequestsObjects<RemoteVideoEventRequest> = {}

    /* Example:
        {
          pod1: {
            video1: { views: 4, likes: 5 },
            video2: { likes: 5 }
          }
        }
    */
    const eventsPerVideoPerPod: {
      [ podId: string ]: {
        [ videoRemoteId: string ]: {
          views?: number
          likes?: number
          dislikes?: number
        }
      }
    } = {}

    // We group video events per video and per pod
    // We add the counts of the same event types
    Object.keys(eventRequests).forEach(toPodId => {
      eventRequests[toPodId].forEach(eventToProcess => {
        if (!eventsPerVideoPerPod[toPodId]) eventsPerVideoPerPod[toPodId] = {}

        if (!requestsToMakeGrouped[toPodId]) {
          requestsToMakeGrouped[toPodId] = {
            toPod: eventToProcess.pod,
            endpoint: REQUEST_VIDEO_EVENT_ENDPOINT,
            ids: [], // request ids, to delete them from the DB in the future
            datas: [] // requests data
          }
        }
        requestsToMakeGrouped[toPodId].ids.push(eventToProcess.id)

        const eventsPerVideo = eventsPerVideoPerPod[toPodId]
        const remoteId = eventToProcess.video.remoteId
        if (!eventsPerVideo[remoteId]) eventsPerVideo[remoteId] = {}

        const events = eventsPerVideo[remoteId]
        if (!events[eventToProcess.type]) events[eventToProcess.type] = 0

        events[eventToProcess.type] += eventToProcess.count
      })
    })

    // Now we build our requests array per pod
    Object.keys(eventsPerVideoPerPod).forEach(toPodId => {
      const eventsForPod = eventsPerVideoPerPod[toPodId]

      Object.keys(eventsForPod).forEach(remoteId => {
        const eventsForVideo = eventsForPod[remoteId]

        Object.keys(eventsForVideo).forEach(eventType => {
          requestsToMakeGrouped[toPodId].datas.push({
            data: {
              remoteId,
              eventType: eventType as RemoteVideoEventType,
              count: +eventsForVideo[eventType]
            }
          })
        })
      })
    })

    return requestsToMakeGrouped
  }

  createRequest ({ type, videoId, count, transaction }: RequestVideoEventSchedulerOptions) {
    if (count === undefined) count = 1

    const dbRequestOptions: Sequelize.CreateOptions = {}
    if (transaction) dbRequestOptions.transaction = transaction

    const createQuery = {
      type,
      count,
      videoId
    }

    return db.RequestVideoEvent.create(createQuery, dbRequestOptions)
  }
}

// ---------------------------------------------------------------------------

export {
  RequestVideoEventScheduler
}