diff options
Diffstat (limited to 'server/models')
-rw-r--r-- | server/models/pod.js | 63 | ||||
-rw-r--r-- | server/models/request-to-pod.js | 4 | ||||
-rw-r--r-- | server/models/request-video-qadu.js | 154 | ||||
-rw-r--r-- | server/models/request.js | 63 | ||||
-rw-r--r-- | server/models/video.js | 13 |
5 files changed, 232 insertions, 65 deletions
diff --git a/server/models/pod.js b/server/models/pod.js index 79afb737a..14814708e 100644 --- a/server/models/pod.js +++ b/server/models/pod.js | |||
@@ -1,8 +1,11 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const each = require('async/each') | ||
3 | const map = require('lodash/map') | 4 | const map = require('lodash/map') |
5 | const waterfall = require('async/waterfall') | ||
4 | 6 | ||
5 | const constants = require('../initializers/constants') | 7 | const constants = require('../initializers/constants') |
8 | const logger = require('../helpers/logger') | ||
6 | const customPodsValidators = require('../helpers/custom-validators').pods | 9 | const customPodsValidators = require('../helpers/custom-validators').pods |
7 | 10 | ||
8 | // --------------------------------------------------------------------------- | 11 | // --------------------------------------------------------------------------- |
@@ -62,6 +65,7 @@ module.exports = function (sequelize, DataTypes) { | |||
62 | listBadPods, | 65 | listBadPods, |
63 | load, | 66 | load, |
64 | loadByHost, | 67 | loadByHost, |
68 | updatePodsScore, | ||
65 | removeAll | 69 | removeAll |
66 | }, | 70 | }, |
67 | instanceMethods: { | 71 | instanceMethods: { |
@@ -144,7 +148,7 @@ function listAllIds (transaction, callback) { | |||
144 | }) | 148 | }) |
145 | } | 149 | } |
146 | 150 | ||
147 | function listRandomPodIdsWithRequest (limit, callback) { | 151 | function listRandomPodIdsWithRequest (limit, tableRequestPod, callback) { |
148 | const self = this | 152 | const self = this |
149 | 153 | ||
150 | self.count().asCallback(function (err, count) { | 154 | self.count().asCallback(function (err, count) { |
@@ -166,7 +170,7 @@ function listRandomPodIdsWithRequest (limit, callback) { | |||
166 | where: { | 170 | where: { |
167 | id: { | 171 | id: { |
168 | $in: [ | 172 | $in: [ |
169 | this.sequelize.literal('SELECT "podId" FROM "RequestToPods"') | 173 | this.sequelize.literal('SELECT "podId" FROM "' + tableRequestPod + '"') |
170 | ] | 174 | ] |
171 | } | 175 | } |
172 | } | 176 | } |
@@ -207,3 +211,58 @@ function loadByHost (host, callback) { | |||
207 | function removeAll (callback) { | 211 | function removeAll (callback) { |
208 | return this.destroy().asCallback(callback) | 212 | return this.destroy().asCallback(callback) |
209 | } | 213 | } |
214 | |||
215 | function updatePodsScore (goodPods, badPods) { | ||
216 | const self = this | ||
217 | |||
218 | logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length) | ||
219 | |||
220 | if (goodPods.length !== 0) { | ||
221 | this.incrementScores(goodPods, constants.PODS_SCORE.BONUS, function (err) { | ||
222 | if (err) logger.error('Cannot increment scores of good pods.', { error: err }) | ||
223 | }) | ||
224 | } | ||
225 | |||
226 | if (badPods.length !== 0) { | ||
227 | this.incrementScores(badPods, constants.PODS_SCORE.MALUS, function (err) { | ||
228 | if (err) logger.error('Cannot decrement scores of bad pods.', { error: err }) | ||
229 | removeBadPods.call(self) | ||
230 | }) | ||
231 | } | ||
232 | } | ||
233 | |||
234 | // --------------------------------------------------------------------------- | ||
235 | |||
236 | // Remove pods with a score of 0 (too many requests where they were unreachable) | ||
237 | function removeBadPods () { | ||
238 | const self = this | ||
239 | |||
240 | waterfall([ | ||
241 | function findBadPods (callback) { | ||
242 | self.sequelize.models.Pod.listBadPods(function (err, pods) { | ||
243 | if (err) { | ||
244 | logger.error('Cannot find bad pods.', { error: err }) | ||
245 | return callback(err) | ||
246 | } | ||
247 | |||
248 | return callback(null, pods) | ||
249 | }) | ||
250 | }, | ||
251 | |||
252 | function removeTheseBadPods (pods, callback) { | ||
253 | each(pods, function (pod, callbackEach) { | ||
254 | pod.destroy().asCallback(callbackEach) | ||
255 | }, function (err) { | ||
256 | return callback(err, pods.length) | ||
257 | }) | ||
258 | } | ||
259 | ], function (err, numberOfPodsRemoved) { | ||
260 | if (err) { | ||
261 | logger.error('Cannot remove bad pods.', { error: err }) | ||
262 | } else if (numberOfPodsRemoved) { | ||
263 | logger.info('Removed %d pods.', numberOfPodsRemoved) | ||
264 | } else { | ||
265 | logger.info('No need to remove bad pods.') | ||
266 | } | ||
267 | }) | ||
268 | } | ||
diff --git a/server/models/request-to-pod.js b/server/models/request-to-pod.js index f42a53458..0e01a842e 100644 --- a/server/models/request-to-pod.js +++ b/server/models/request-to-pod.js | |||
@@ -17,7 +17,7 @@ module.exports = function (sequelize, DataTypes) { | |||
17 | } | 17 | } |
18 | ], | 18 | ], |
19 | classMethods: { | 19 | classMethods: { |
20 | removePodOf | 20 | removeByRequestIdsAndPod |
21 | } | 21 | } |
22 | }) | 22 | }) |
23 | 23 | ||
@@ -26,7 +26,7 @@ module.exports = function (sequelize, DataTypes) { | |||
26 | 26 | ||
27 | // --------------------------------------------------------------------------- | 27 | // --------------------------------------------------------------------------- |
28 | 28 | ||
29 | function removePodOf (requestsIds, podId, callback) { | 29 | function removeByRequestIdsAndPod (requestsIds, podId, callback) { |
30 | if (!callback) callback = function () {} | 30 | if (!callback) callback = function () {} |
31 | 31 | ||
32 | const query = { | 32 | const query = { |
diff --git a/server/models/request-video-qadu.js b/server/models/request-video-qadu.js new file mode 100644 index 000000000..7010fc992 --- /dev/null +++ b/server/models/request-video-qadu.js | |||
@@ -0,0 +1,154 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | /* | ||
4 | Request Video for Quick And Dirty Updates like: | ||
5 | - views | ||
6 | - likes | ||
7 | - dislikes | ||
8 | |||
9 | We can't put it in the same system than basic requests for efficiency. | ||
10 | Moreover we don't want to slow down the basic requests with a lot of views/likes/dislikes requests. | ||
11 | So we put it an independant request scheduler. | ||
12 | */ | ||
13 | |||
14 | const values = require('lodash/values') | ||
15 | |||
16 | const constants = require('../initializers/constants') | ||
17 | |||
18 | // --------------------------------------------------------------------------- | ||
19 | |||
20 | module.exports = function (sequelize, DataTypes) { | ||
21 | const RequestVideoQadu = sequelize.define('RequestVideoQadu', | ||
22 | { | ||
23 | type: { | ||
24 | type: DataTypes.ENUM(values(constants.REQUEST_VIDEO_QADU_TYPES)), | ||
25 | allowNull: false | ||
26 | } | ||
27 | }, | ||
28 | { | ||
29 | timestamps: false, | ||
30 | indexes: [ | ||
31 | { | ||
32 | fields: [ 'podId' ] | ||
33 | }, | ||
34 | { | ||
35 | fields: [ 'videoId' ] | ||
36 | } | ||
37 | ], | ||
38 | classMethods: { | ||
39 | associate, | ||
40 | |||
41 | listWithLimitAndRandom, | ||
42 | |||
43 | countTotalRequests, | ||
44 | removeAll, | ||
45 | removeByRequestIdsAndPod | ||
46 | } | ||
47 | } | ||
48 | ) | ||
49 | |||
50 | return RequestVideoQadu | ||
51 | } | ||
52 | |||
53 | // ------------------------------ STATICS ------------------------------ | ||
54 | |||
55 | function associate (models) { | ||
56 | this.belongsTo(models.Pod, { | ||
57 | foreignKey: { | ||
58 | name: 'podId', | ||
59 | allowNull: false | ||
60 | }, | ||
61 | onDelete: 'CASCADE' | ||
62 | }) | ||
63 | |||
64 | this.belongsTo(models.Video, { | ||
65 | foreignKey: { | ||
66 | name: 'videoId', | ||
67 | allowNull: false | ||
68 | }, | ||
69 | onDelete: 'CASCADE' | ||
70 | }) | ||
71 | } | ||
72 | |||
73 | function countTotalRequests (callback) { | ||
74 | const query = { | ||
75 | include: [ this.sequelize.models.Pod ] | ||
76 | } | ||
77 | |||
78 | return this.count(query).asCallback(callback) | ||
79 | } | ||
80 | |||
81 | function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) { | ||
82 | const self = this | ||
83 | const Pod = this.sequelize.models.Pod | ||
84 | |||
85 | Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) { | ||
86 | if (err) return callback(err) | ||
87 | |||
88 | // We don't have friends that have requests | ||
89 | if (podIds.length === 0) return callback(null, []) | ||
90 | |||
91 | const query = { | ||
92 | include: [ | ||
93 | { | ||
94 | model: self.sequelize.models.Pod, | ||
95 | where: { | ||
96 | id: { | ||
97 | $in: podIds | ||
98 | } | ||
99 | } | ||
100 | }, | ||
101 | { | ||
102 | model: self.sequelize.models.Video | ||
103 | } | ||
104 | ] | ||
105 | } | ||
106 | |||
107 | self.findAll(query).asCallback(function (err, requests) { | ||
108 | if (err) return callback(err) | ||
109 | |||
110 | const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) | ||
111 | return callback(err, requestsGrouped) | ||
112 | }) | ||
113 | }) | ||
114 | } | ||
115 | |||
116 | function removeByRequestIdsAndPod (ids, podId, callback) { | ||
117 | const query = { | ||
118 | where: { | ||
119 | id: { | ||
120 | $in: ids | ||
121 | }, | ||
122 | podId | ||
123 | } | ||
124 | } | ||
125 | |||
126 | this.destroy(query).asCallback(callback) | ||
127 | } | ||
128 | |||
129 | function removeAll (callback) { | ||
130 | // Delete all requests | ||
131 | this.truncate({ cascade: true }).asCallback(callback) | ||
132 | } | ||
133 | |||
134 | // --------------------------------------------------------------------------- | ||
135 | |||
136 | function groupAndTruncateRequests (requests, limitRequestsPerPod) { | ||
137 | const requestsGrouped = {} | ||
138 | |||
139 | requests.forEach(function (request) { | ||
140 | const pod = request.Pod | ||
141 | |||
142 | if (!requestsGrouped[pod.id]) requestsGrouped[pod.id] = [] | ||
143 | |||
144 | if (requestsGrouped[pod.id].length < limitRequestsPerPod) { | ||
145 | requestsGrouped[pod.id].push({ | ||
146 | request: request, | ||
147 | video: request.Video, | ||
148 | pod | ||
149 | }) | ||
150 | } | ||
151 | }) | ||
152 | |||
153 | return requestsGrouped | ||
154 | } | ||
diff --git a/server/models/request.js b/server/models/request.js index ca616d130..de73501fc 100644 --- a/server/models/request.js +++ b/server/models/request.js | |||
@@ -1,11 +1,8 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const each = require('async/each') | ||
4 | const waterfall = require('async/waterfall') | ||
5 | const values = require('lodash/values') | 3 | const values = require('lodash/values') |
6 | 4 | ||
7 | const constants = require('../initializers/constants') | 5 | const constants = require('../initializers/constants') |
8 | const logger = require('../helpers/logger') | ||
9 | 6 | ||
10 | // --------------------------------------------------------------------------- | 7 | // --------------------------------------------------------------------------- |
11 | 8 | ||
@@ -28,8 +25,6 @@ module.exports = function (sequelize, DataTypes) { | |||
28 | listWithLimitAndRandom, | 25 | listWithLimitAndRandom, |
29 | 26 | ||
30 | countTotalRequests, | 27 | countTotalRequests, |
31 | removeBadPods, | ||
32 | updatePodsScore, | ||
33 | removeAll, | 28 | removeAll, |
34 | removeWithEmptyTo | 29 | removeWithEmptyTo |
35 | } | 30 | } |
@@ -60,71 +55,17 @@ function countTotalRequests (callback) { | |||
60 | return this.count(query).asCallback(callback) | 55 | return this.count(query).asCallback(callback) |
61 | } | 56 | } |
62 | 57 | ||
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) { | 58 | function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) { |
118 | const self = this | 59 | const self = this |
119 | const Pod = this.sequelize.models.Pod | 60 | const Pod = this.sequelize.models.Pod |
120 | 61 | ||
121 | Pod.listRandomPodIdsWithRequest(limitPods, function (err, podIds) { | 62 | Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) { |
122 | if (err) return callback(err) | 63 | if (err) return callback(err) |
123 | 64 | ||
124 | // We don't have friends that have requests | 65 | // We don't have friends that have requests |
125 | if (podIds.length === 0) return callback(null, []) | 66 | if (podIds.length === 0) return callback(null, []) |
126 | 67 | ||
127 | // The the first x requests of these pods | 68 | // The first x requests of these pods |
128 | // It is very important to sort by id ASC to keep the requests order! | 69 | // It is very important to sort by id ASC to keep the requests order! |
129 | const query = { | 70 | const query = { |
130 | order: [ | 71 | order: [ |
diff --git a/server/models/video.js b/server/models/video.js index d0fd61eb4..daa273845 100644 --- a/server/models/video.js +++ b/server/models/video.js | |||
@@ -80,6 +80,15 @@ module.exports = function (sequelize, DataTypes) { | |||
80 | if (res === false) throw new Error('Video duration is not valid.') | 80 | if (res === false) throw new Error('Video duration is not valid.') |
81 | } | 81 | } |
82 | } | 82 | } |
83 | }, | ||
84 | views: { | ||
85 | type: DataTypes.INTEGER, | ||
86 | allowNull: false, | ||
87 | defaultValue: 0, | ||
88 | validate: { | ||
89 | min: 0, | ||
90 | isInt: true | ||
91 | } | ||
83 | } | 92 | } |
84 | }, | 93 | }, |
85 | { | 94 | { |
@@ -101,6 +110,9 @@ module.exports = function (sequelize, DataTypes) { | |||
101 | }, | 110 | }, |
102 | { | 111 | { |
103 | fields: [ 'infoHash' ] | 112 | fields: [ 'infoHash' ] |
113 | }, | ||
114 | { | ||
115 | fields: [ 'views' ] | ||
104 | } | 116 | } |
105 | ], | 117 | ], |
106 | classMethods: { | 118 | classMethods: { |
@@ -336,6 +348,7 @@ function toFormatedJSON () { | |||
336 | magnetUri: this.generateMagnetUri(), | 348 | magnetUri: this.generateMagnetUri(), |
337 | author: this.Author.name, | 349 | author: this.Author.name, |
338 | duration: this.duration, | 350 | duration: this.duration, |
351 | views: this.views, | ||
339 | tags: map(this.Tags, 'name'), | 352 | tags: map(this.Tags, 'name'), |
340 | thumbnailPath: pathUtils.join(constants.STATIC_PATHS.THUMBNAILS, this.getThumbnailName()), | 353 | thumbnailPath: pathUtils.join(constants.STATIC_PATHS.THUMBNAILS, this.getThumbnailName()), |
341 | createdAt: this.createdAt, | 354 | createdAt: this.createdAt, |