]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/request.js
ca616d1303776026f113773a49e77d3a62512bef
[github/Chocobozzz/PeerTube.git] / server / models / request.js
1 'use strict'
2
3 const each = require('async/each')
4 const waterfall = require('async/waterfall')
5 const values = require('lodash/values')
6
7 const constants = require('../initializers/constants')
8 const logger = require('../helpers/logger')
9
10 // ---------------------------------------------------------------------------
11
12 module.exports = function (sequelize, DataTypes) {
13 const Request = sequelize.define('Request',
14 {
15 request: {
16 type: DataTypes.JSON,
17 allowNull: false
18 },
19 endpoint: {
20 type: DataTypes.ENUM(values(constants.REQUEST_ENDPOINTS)),
21 allowNull: false
22 }
23 },
24 {
25 classMethods: {
26 associate,
27
28 listWithLimitAndRandom,
29
30 countTotalRequests,
31 removeBadPods,
32 updatePodsScore,
33 removeAll,
34 removeWithEmptyTo
35 }
36 }
37 )
38
39 return Request
40 }
41
42 // ------------------------------ STATICS ------------------------------
43
44 function associate (models) {
45 this.belongsToMany(models.Pod, {
46 foreignKey: {
47 name: 'requestId',
48 allowNull: false
49 },
50 through: models.RequestToPod,
51 onDelete: 'CASCADE'
52 })
53 }
54
55 function countTotalRequests (callback) {
56 const query = {
57 include: [ this.sequelize.models.Pod ]
58 }
59
60 return this.count(query).asCallback(callback)
61 }
62
63 // Remove pods with a score of 0 (too many requests where they were unreachable)
64 function removeBadPods () {
65 const self = this
66
67 waterfall([
68 function findBadPods (callback) {
69 self.sequelize.models.Pod.listBadPods(function (err, pods) {
70 if (err) {
71 logger.error('Cannot find bad pods.', { error: err })
72 return callback(err)
73 }
74
75 return callback(null, pods)
76 })
77 },
78
79 function removeTheseBadPods (pods, callback) {
80 each(pods, function (pod, callbackEach) {
81 pod.destroy().asCallback(callbackEach)
82 }, function (err) {
83 return callback(err, pods.length)
84 })
85 }
86 ], function (err, numberOfPodsRemoved) {
87 if (err) {
88 logger.error('Cannot remove bad pods.', { error: err })
89 } else if (numberOfPodsRemoved) {
90 logger.info('Removed %d pods.', numberOfPodsRemoved)
91 } else {
92 logger.info('No need to remove bad pods.')
93 }
94 })
95 }
96
97 function updatePodsScore (goodPods, badPods) {
98 const self = this
99 const Pod = this.sequelize.models.Pod
100
101 logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
102
103 if (goodPods.length !== 0) {
104 Pod.incrementScores(goodPods, constants.PODS_SCORE.BONUS, function (err) {
105 if (err) logger.error('Cannot increment scores of good pods.', { error: err })
106 })
107 }
108
109 if (badPods.length !== 0) {
110 Pod.incrementScores(badPods, constants.PODS_SCORE.MALUS, function (err) {
111 if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
112 removeBadPods.call(self)
113 })
114 }
115 }
116
117 function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
118 const self = this
119 const Pod = this.sequelize.models.Pod
120
121 Pod.listRandomPodIdsWithRequest(limitPods, function (err, podIds) {
122 if (err) return callback(err)
123
124 // We don't have friends that have requests
125 if (podIds.length === 0) return callback(null, [])
126
127 // The the first x requests of these pods
128 // It is very important to sort by id ASC to keep the requests order!
129 const query = {
130 order: [
131 [ 'id', 'ASC' ]
132 ],
133 include: [
134 {
135 model: self.sequelize.models.Pod,
136 where: {
137 id: {
138 $in: podIds
139 }
140 }
141 }
142 ]
143 }
144
145 self.findAll(query).asCallback(function (err, requests) {
146 if (err) return callback(err)
147
148 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
149 return callback(err, requestsGrouped)
150 })
151 })
152 }
153
154 function removeAll (callback) {
155 // Delete all requests
156 this.truncate({ cascade: true }).asCallback(callback)
157 }
158
159 function removeWithEmptyTo (callback) {
160 if (!callback) callback = function () {}
161
162 const query = {
163 where: {
164 id: {
165 $notIn: [
166 this.sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
167 ]
168 }
169 }
170 }
171
172 this.destroy(query).asCallback(callback)
173 }
174
175 // ---------------------------------------------------------------------------
176
177 function groupAndTruncateRequests (requests, limitRequestsPerPod) {
178 const requestsGrouped = {}
179
180 requests.forEach(function (request) {
181 request.Pods.forEach(function (pod) {
182 if (!requestsGrouped[pod.id]) requestsGrouped[pod.id] = []
183
184 if (requestsGrouped[pod.id].length < limitRequestsPerPod) {
185 requestsGrouped[pod.id].push({
186 request,
187 pod
188 })
189 }
190 })
191 })
192
193 return requestsGrouped
194 }