diff options
Diffstat (limited to 'server/lib/redis.ts')
-rw-r--r-- | server/lib/redis.ts | 112 |
1 files changed, 80 insertions, 32 deletions
diff --git a/server/lib/redis.ts b/server/lib/redis.ts index 46617b07e..76b7868e8 100644 --- a/server/lib/redis.ts +++ b/server/lib/redis.ts | |||
@@ -13,6 +13,7 @@ import { | |||
13 | RESUMABLE_UPLOAD_SESSION_LIFETIME | 13 | RESUMABLE_UPLOAD_SESSION_LIFETIME |
14 | } from '../initializers/constants' | 14 | } from '../initializers/constants' |
15 | import { CONFIG } from '../initializers/config' | 15 | import { CONFIG } from '../initializers/config' |
16 | import { exists } from '@server/helpers/custom-validators/misc' | ||
16 | 17 | ||
17 | type CachedRoute = { | 18 | type CachedRoute = { |
18 | body: string | 19 | body: string |
@@ -119,16 +120,20 @@ class Redis { | |||
119 | 120 | ||
120 | /* ************ Views per IP ************ */ | 121 | /* ************ Views per IP ************ */ |
121 | 122 | ||
122 | setIPVideoView (ip: string, videoUUID: string, isLive: boolean) { | 123 | setIPVideoView (ip: string, videoUUID: string) { |
123 | const lifetime = isLive | 124 | return this.setValue(this.generateIPViewKey(ip, videoUUID), '1', VIEW_LIFETIME.VIEW) |
124 | ? VIEW_LIFETIME.LIVE | 125 | } |
125 | : VIEW_LIFETIME.VIDEO | ||
126 | 126 | ||
127 | return this.setValue(this.generateViewKey(ip, videoUUID), '1', lifetime) | 127 | setIPVideoViewer (ip: string, videoUUID: string) { |
128 | return this.setValue(this.generateIPViewerKey(ip, videoUUID), '1', VIEW_LIFETIME.VIEWER) | ||
128 | } | 129 | } |
129 | 130 | ||
130 | async doesVideoIPViewExist (ip: string, videoUUID: string) { | 131 | async doesVideoIPViewExist (ip: string, videoUUID: string) { |
131 | return this.exists(this.generateViewKey(ip, videoUUID)) | 132 | return this.exists(this.generateIPViewKey(ip, videoUUID)) |
133 | } | ||
134 | |||
135 | async doesVideoIPViewerExist (ip: string, videoUUID: string) { | ||
136 | return this.exists(this.generateIPViewerKey(ip, videoUUID)) | ||
132 | } | 137 | } |
133 | 138 | ||
134 | /* ************ Tracker IP block ************ */ | 139 | /* ************ Tracker IP block ************ */ |
@@ -160,46 +165,85 @@ class Redis { | |||
160 | return this.setObject(this.generateCachedRouteKey(req), cached, lifetime) | 165 | return this.setObject(this.generateCachedRouteKey(req), cached, lifetime) |
161 | } | 166 | } |
162 | 167 | ||
163 | /* ************ Video views ************ */ | 168 | /* ************ Video views stats ************ */ |
164 | 169 | ||
165 | addVideoView (videoId: number) { | 170 | addVideoViewStats (videoId: number) { |
166 | const keyIncr = this.generateVideoViewKey(videoId) | 171 | const { videoKey, setKey } = this.generateVideoViewStatsKeys({ videoId }) |
167 | const keySet = this.generateVideosViewKey() | ||
168 | 172 | ||
169 | return Promise.all([ | 173 | return Promise.all([ |
170 | this.addToSet(keySet, videoId.toString()), | 174 | this.addToSet(setKey, videoId.toString()), |
171 | this.increment(keyIncr) | 175 | this.increment(videoKey) |
172 | ]) | 176 | ]) |
173 | } | 177 | } |
174 | 178 | ||
175 | async getVideoViews (videoId: number, hour: number) { | 179 | async getVideoViewsStats (videoId: number, hour: number) { |
176 | const key = this.generateVideoViewKey(videoId, hour) | 180 | const { videoKey } = this.generateVideoViewStatsKeys({ videoId, hour }) |
177 | 181 | ||
178 | const valueString = await this.getValue(key) | 182 | const valueString = await this.getValue(videoKey) |
179 | const valueInt = parseInt(valueString, 10) | 183 | const valueInt = parseInt(valueString, 10) |
180 | 184 | ||
181 | if (isNaN(valueInt)) { | 185 | if (isNaN(valueInt)) { |
182 | logger.error('Cannot get videos views of video %d in hour %d: views number is NaN (%s).', videoId, hour, valueString) | 186 | logger.error('Cannot get videos views stats of video %d in hour %d: views number is NaN (%s).', videoId, hour, valueString) |
183 | return undefined | 187 | return undefined |
184 | } | 188 | } |
185 | 189 | ||
186 | return valueInt | 190 | return valueInt |
187 | } | 191 | } |
188 | 192 | ||
189 | async getVideosIdViewed (hour: number) { | 193 | async listVideosViewedForStats (hour: number) { |
190 | const key = this.generateVideosViewKey(hour) | 194 | const { setKey } = this.generateVideoViewStatsKeys({ hour }) |
191 | 195 | ||
192 | const stringIds = await this.getSet(key) | 196 | const stringIds = await this.getSet(setKey) |
193 | return stringIds.map(s => parseInt(s, 10)) | 197 | return stringIds.map(s => parseInt(s, 10)) |
194 | } | 198 | } |
195 | 199 | ||
196 | deleteVideoViews (videoId: number, hour: number) { | 200 | deleteVideoViewsStats (videoId: number, hour: number) { |
197 | const keySet = this.generateVideosViewKey(hour) | 201 | const { setKey, videoKey } = this.generateVideoViewStatsKeys({ videoId, hour }) |
198 | const keyIncr = this.generateVideoViewKey(videoId, hour) | 202 | |
203 | return Promise.all([ | ||
204 | this.deleteFromSet(setKey, videoId.toString()), | ||
205 | this.deleteKey(videoKey) | ||
206 | ]) | ||
207 | } | ||
208 | |||
209 | /* ************ Local video views buffer ************ */ | ||
210 | |||
211 | addLocalVideoView (videoId: number) { | ||
212 | const { videoKey, setKey } = this.generateLocalVideoViewsKeys(videoId) | ||
199 | 213 | ||
200 | return Promise.all([ | 214 | return Promise.all([ |
201 | this.deleteFromSet(keySet, videoId.toString()), | 215 | this.addToSet(setKey, videoId.toString()), |
202 | this.deleteKey(keyIncr) | 216 | this.increment(videoKey) |
217 | ]) | ||
218 | } | ||
219 | |||
220 | async getLocalVideoViews (videoId: number) { | ||
221 | const { videoKey } = this.generateLocalVideoViewsKeys(videoId) | ||
222 | |||
223 | const valueString = await this.getValue(videoKey) | ||
224 | const valueInt = parseInt(valueString, 10) | ||
225 | |||
226 | if (isNaN(valueInt)) { | ||
227 | logger.error('Cannot get videos views of video %d: views number is NaN (%s).', videoId, valueString) | ||
228 | return undefined | ||
229 | } | ||
230 | |||
231 | return valueInt | ||
232 | } | ||
233 | |||
234 | async listLocalVideosViewed () { | ||
235 | const { setKey } = this.generateLocalVideoViewsKeys() | ||
236 | |||
237 | const stringIds = await this.getSet(setKey) | ||
238 | return stringIds.map(s => parseInt(s, 10)) | ||
239 | } | ||
240 | |||
241 | deleteLocalVideoViews (videoId: number) { | ||
242 | const { setKey, videoKey } = this.generateLocalVideoViewsKeys(videoId) | ||
243 | |||
244 | return Promise.all([ | ||
245 | this.deleteFromSet(setKey, videoId.toString()), | ||
246 | this.deleteKey(videoKey) | ||
203 | ]) | 247 | ]) |
204 | } | 248 | } |
205 | 249 | ||
@@ -233,16 +277,16 @@ class Redis { | |||
233 | return req.method + '-' + req.originalUrl | 277 | return req.method + '-' + req.originalUrl |
234 | } | 278 | } |
235 | 279 | ||
236 | private generateVideosViewKey (hour?: number) { | 280 | private generateLocalVideoViewsKeys (videoId?: Number) { |
237 | if (!hour) hour = new Date().getHours() | 281 | return { setKey: `local-video-views-buffer`, videoKey: `local-video-views-buffer-${videoId}` } |
238 | |||
239 | return `videos-view-h${hour}` | ||
240 | } | 282 | } |
241 | 283 | ||
242 | private generateVideoViewKey (videoId: number, hour?: number) { | 284 | private generateVideoViewStatsKeys (options: { videoId?: number, hour?: number }) { |
243 | if (hour === undefined || hour === null) hour = new Date().getHours() | 285 | const hour = exists(options.hour) |
286 | ? options.hour | ||
287 | : new Date().getHours() | ||
244 | 288 | ||
245 | return `video-view-${videoId}-h${hour}` | 289 | return { setKey: `videos-view-h${hour}`, videoKey: `video-view-${options.videoId}-h${hour}` } |
246 | } | 290 | } |
247 | 291 | ||
248 | private generateResetPasswordKey (userId: number) { | 292 | private generateResetPasswordKey (userId: number) { |
@@ -253,10 +297,14 @@ class Redis { | |||
253 | return 'verify-email-' + userId | 297 | return 'verify-email-' + userId |
254 | } | 298 | } |
255 | 299 | ||
256 | private generateViewKey (ip: string, videoUUID: string) { | 300 | private generateIPViewKey (ip: string, videoUUID: string) { |
257 | return `views-${videoUUID}-${ip}` | 301 | return `views-${videoUUID}-${ip}` |
258 | } | 302 | } |
259 | 303 | ||
304 | private generateIPViewerKey (ip: string, videoUUID: string) { | ||
305 | return `viewer-${videoUUID}-${ip}` | ||
306 | } | ||
307 | |||
260 | private generateTrackerBlockIPKey (ip: string) { | 308 | private generateTrackerBlockIPKey (ip: string) { |
261 | return `tracker-block-ip-${ip}` | 309 | return `tracker-block-ip-${ip}` |
262 | } | 310 | } |