aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api/videos/rate.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api/videos/rate.ts')
-rw-r--r--server/controllers/api/videos/rate.ts207
1 files changed, 87 insertions, 120 deletions
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index afdd099f8..3d119d98b 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -1,14 +1,9 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Sequelize from 'sequelize'
3import { waterfall } from 'async'
4 2
5import { database as db } from '../../../initializers/database' 3import { database as db } from '../../../initializers/database'
6import { 4import {
7 logger, 5 logger,
8 retryTransactionWrapper, 6 retryTransactionWrapper
9 startSerializableTransaction,
10 commitTransaction,
11 rollbackTransaction
12} from '../../../helpers' 7} from '../../../helpers'
13import { 8import {
14 VIDEO_RATE_TYPES, 9 VIDEO_RATE_TYPES,
@@ -46,137 +41,109 @@ function rateVideoRetryWrapper (req: express.Request, res: express.Response, nex
46 errorMessage: 'Cannot update the user video rate.' 41 errorMessage: 'Cannot update the user video rate.'
47 } 42 }
48 43
49 retryTransactionWrapper(rateVideo, options, function (err) { 44 retryTransactionWrapper(rateVideo, options)
50 if (err) return next(err) 45 .then(() => res.type('json').status(204).end())
51 46 .catch(err => next(err))
52 return res.type('json').status(204).end()
53 })
54} 47}
55 48
56function rateVideo (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) { 49function rateVideo (req: express.Request, res: express.Response) {
57 const rateType = req.body.rating 50 const rateType = req.body.rating
58 const videoInstance = res.locals.video 51 const videoInstance = res.locals.video
59 const userInstance = res.locals.oauth.token.User 52 const userInstance = res.locals.oauth.token.User
60 53
61 waterfall([ 54 return db.sequelize.transaction(t => {
62 startSerializableTransaction, 55 return db.UserVideoRate.load(userInstance.id, videoInstance.id, t)
63 56 .then(previousRate => {
64 function findPreviousRate (t, callback) { 57 const options = { transaction: t }
65 db.UserVideoRate.load(userInstance.id, videoInstance.id, t, function (err, previousRate) {
66 return callback(err, t, previousRate)
67 })
68 },
69 58
70 function insertUserRateIntoDB (t, previousRate, callback) { 59 let likesToIncrement = 0
71 const options = { transaction: t } 60 let dislikesToIncrement = 0
72 61
73 let likesToIncrement = 0 62 if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++
74 let dislikesToIncrement = 0 63 else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
75 64
76 if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ 65 // There was a previous rate, update it
77 else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ 66 if (previousRate) {
67 // We will remove the previous rate, so we will need to remove it from the video attribute
68 if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
69 else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
78 70
79 // There was a previous rate, update it 71 previousRate.type = rateType
80 if (previousRate) {
81 // We will remove the previous rate, so we will need to remove it from the video attribute
82 if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
83 else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
84 72
85 previousRate.type = rateType 73 return previousRate.save(options).then(() => ({ t, likesToIncrement, dislikesToIncrement }))
74 } else { // There was not a previous rate, insert a new one
75 const query = {
76 userId: userInstance.id,
77 videoId: videoInstance.id,
78 type: rateType
79 }
86 80
87 previousRate.save(options).asCallback(function (err) { 81 return db.UserVideoRate.create(query, options).then(() => ({ likesToIncrement, dislikesToIncrement }))
88 return callback(err, t, likesToIncrement, dislikesToIncrement)
89 })
90 } else { // There was not a previous rate, insert a new one
91 const query = {
92 userId: userInstance.id,
93 videoId: videoInstance.id,
94 type: rateType
95 } 82 }
96
97 db.UserVideoRate.create(query, options).asCallback(function (err) {
98 return callback(err, t, likesToIncrement, dislikesToIncrement)
99 })
100 }
101 },
102
103 function updateVideoAttributeDB (t, likesToIncrement, dislikesToIncrement, callback) {
104 const options = { transaction: t }
105 const incrementQuery = {
106 likes: likesToIncrement,
107 dislikes: dislikesToIncrement
108 }
109
110 // Even if we do not own the video we increment the attributes
111 // It is usefull for the user to have a feedback
112 videoInstance.increment(incrementQuery, options).asCallback(function (err) {
113 return callback(err, t, likesToIncrement, dislikesToIncrement)
114 })
115 },
116
117 function sendEventsToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) {
118 // No need for an event type, we own the video
119 if (videoInstance.isOwned()) return callback(null, t, likesToIncrement, dislikesToIncrement)
120
121 const eventsParams = []
122
123 if (likesToIncrement !== 0) {
124 eventsParams.push({
125 videoId: videoInstance.id,
126 type: REQUEST_VIDEO_EVENT_TYPES.LIKES,
127 count: likesToIncrement
128 })
129 }
130
131 if (dislikesToIncrement !== 0) {
132 eventsParams.push({
133 videoId: videoInstance.id,
134 type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
135 count: dislikesToIncrement
136 })
137 }
138
139 addEventsToRemoteVideo(eventsParams, t, function (err) {
140 return callback(err, t, likesToIncrement, dislikesToIncrement)
141 }) 83 })
142 }, 84 .then(({ likesToIncrement, dislikesToIncrement }) => {
143 85 const options = { transaction: t }
144 function sendQaduToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) { 86 const incrementQuery = {
145 // We do not own the video, there is no need to send a quick and dirty update to friends 87 likes: likesToIncrement,
146 // Our rate was already sent by the addEvent function 88 dislikes: dislikesToIncrement
147 if (videoInstance.isOwned() === false) return callback(null, t) 89 }
148 90
149 const qadusParams = [] 91 // Even if we do not own the video we increment the attributes
150 92 // It is usefull for the user to have a feedback
151 if (likesToIncrement !== 0) { 93 return videoInstance.increment(incrementQuery, options).then(() => ({ likesToIncrement, dislikesToIncrement }))
152 qadusParams.push({
153 videoId: videoInstance.id,
154 type: REQUEST_VIDEO_QADU_TYPES.LIKES
155 })
156 }
157
158 if (dislikesToIncrement !== 0) {
159 qadusParams.push({
160 videoId: videoInstance.id,
161 type: REQUEST_VIDEO_QADU_TYPES.DISLIKES
162 })
163 }
164
165 quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
166 return callback(err, t)
167 }) 94 })
168 }, 95 .then(({ likesToIncrement, dislikesToIncrement }) => {
96 // No need for an event type, we own the video
97 if (videoInstance.isOwned()) return { likesToIncrement, dislikesToIncrement }
98
99 const eventsParams = []
100
101 if (likesToIncrement !== 0) {
102 eventsParams.push({
103 videoId: videoInstance.id,
104 type: REQUEST_VIDEO_EVENT_TYPES.LIKES,
105 count: likesToIncrement
106 })
107 }
108
109 if (dislikesToIncrement !== 0) {
110 eventsParams.push({
111 videoId: videoInstance.id,
112 type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
113 count: dislikesToIncrement
114 })
115 }
169 116
170 commitTransaction 117 return addEventsToRemoteVideo(eventsParams, t).then(() => ({ likesToIncrement, dislikesToIncrement }))
118 })
119 .then(({ likesToIncrement, dislikesToIncrement }) => {
120 // We do not own the video, there is no need to send a quick and dirty update to friends
121 // Our rate was already sent by the addEvent function
122 if (videoInstance.isOwned() === false) return undefined
123
124 const qadusParams = []
125
126 if (likesToIncrement !== 0) {
127 qadusParams.push({
128 videoId: videoInstance.id,
129 type: REQUEST_VIDEO_QADU_TYPES.LIKES
130 })
131 }
171 132
172 ], function (err: Error, t: Sequelize.Transaction) { 133 if (dislikesToIncrement !== 0) {
173 if (err) { 134 qadusParams.push({
174 // This is just a debug because we will retry the insert 135 videoId: videoInstance.id,
175 logger.debug('Cannot add the user video rate.', { error: err }) 136 type: REQUEST_VIDEO_QADU_TYPES.DISLIKES
176 return rollbackTransaction(err, t, finalCallback) 137 })
177 } 138 }
178 139
179 logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username) 140 return quickAndDirtyUpdatesVideoToFriends(qadusParams, t)
180 return finalCallback(null) 141 })
142 })
143 .then(() => logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username))
144 .catch(err => {
145 // This is just a debug because we will retry the insert
146 logger.debug('Cannot add the user video rate.', { error: err })
147 throw err
181 }) 148 })
182} 149}