Cache AP video route for 5 seconds
authorChocobozzz <me@florianbigard.com>
Fri, 11 May 2018 07:44:04 +0000 (09:44 +0200)
committerChocobozzz <me@florianbigard.com>
Fri, 11 May 2018 13:24:17 +0000 (15:24 +0200)
server/controllers/activitypub/client.ts
server/controllers/feeds.ts
server/initializers/constants.ts
server/lib/redis.ts
server/middlewares/cache.ts

index f5ac9c4661904de8247afe26450e6ab1f54cafa0..5199b3f8107990352e4710bfff65db49b79c3e8a 100644 (file)
@@ -3,7 +3,7 @@ import * as express from 'express'
 import { VideoPrivacy } from '../../../shared/models/videos'
 import { activityPubCollectionPagination, activityPubContextify } from '../../helpers/activitypub'
 import { pageToStartAndCount } from '../../helpers/core-utils'
-import { ACTIVITY_PUB, CONFIG } from '../../initializers'
+import { ACTIVITY_PUB, CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers'
 import { buildVideoAnnounce } from '../../lib/activitypub/send'
 import { audiencify, getAudience } from '../../lib/activitypub/send/misc'
 import { createActivityData } from '../../lib/activitypub/send/send-create'
@@ -17,6 +17,7 @@ import { VideoModel } from '../../models/video/video'
 import { VideoChannelModel } from '../../models/video/video-channel'
 import { VideoCommentModel } from '../../models/video/video-comment'
 import { VideoShareModel } from '../../models/video/video-share'
+import { cacheRoute } from '../../middlewares/cache'
 
 const activityPubClientRouter = express.Router()
 
@@ -34,6 +35,7 @@ activityPubClientRouter.get('/accounts?/:name/following',
 )
 
 activityPubClientRouter.get('/videos/watch/:id',
+  executeIfActivityPub(asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS))),
   executeIfActivityPub(asyncMiddleware(videosGetValidator)),
   executeIfActivityPub(asyncMiddleware(videoController))
 )
index 08f179509e1747bcfb83207e2fa3f0a515747799..92cf85050da42cbf52e34a28613ab6b639c4ce7b 100644 (file)
@@ -1,5 +1,5 @@
 import * as express from 'express'
-import { CONFIG, FEEDS } from '../initializers/constants'
+import { CONFIG, FEEDS, ROUTE_CACHE_LIFETIME } from '../initializers/constants'
 import { asyncMiddleware, feedsValidator, setDefaultSort, videosSortValidator } from '../middlewares'
 import { VideoModel } from '../models/video/video'
 import * as Feed from 'pfeed'
@@ -12,8 +12,8 @@ const feedsRouter = express.Router()
 feedsRouter.get('/feeds/videos.:format',
   videosSortValidator,
   setDefaultSort,
+  asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.FEEDS)),
   asyncMiddleware(feedsValidator),
-  asyncMiddleware(cacheRoute),
   asyncMiddleware(generateFeed)
 )
 
index c4e8522c297ad7ceca1d6711299eb4e576d65d5e..cfa0203d231adcdc1b25d6d52014f47e8c3c48f6 100644 (file)
@@ -42,6 +42,13 @@ const OAUTH_LIFETIME = {
   REFRESH_TOKEN: 1209600 // 2 weeks
 }
 
+const ROUTE_CACHE_LIFETIME = {
+  FEEDS: 1000 * 60 * 15, // 15 minutes
+  ACTIVITY_PUB: {
+    VIDEOS: 1000 * 5 // 5 seconds
+  }
+}
+
 // ---------------------------------------------------------------------------
 
 // Number of points we add/remove after a successful/bad request
@@ -413,8 +420,7 @@ const OPENGRAPH_AND_OEMBED_COMMENT = '<!-- open graph and oembed tags -->'
 // ---------------------------------------------------------------------------
 
 const FEEDS = {
-  COUNT: 20,
-  CACHE_LIFETIME: 1000 * 60 * 15 // 15 minutes
+  COUNT: 20
 }
 
 // ---------------------------------------------------------------------------
@@ -458,6 +464,7 @@ export {
   FOLLOW_STATES,
   SERVER_ACTOR_NAME,
   PRIVATE_RSA_KEY_SIZE,
+  ROUTE_CACHE_LIFETIME,
   SORTABLE_COLUMNS,
   FEEDS,
   NSFW_POLICY_TYPES,
index 1e7c0a8211ebe791b1a1e27cdca0f2e2d7e87407..0acb9ff0e4438864041a450e7b5e8afcd8403864 100644 (file)
@@ -2,7 +2,7 @@ import * as express from 'express'
 import { createClient, RedisClient } from 'redis'
 import { logger } from '../helpers/logger'
 import { generateRandomString } from '../helpers/utils'
-import { CONFIG, FEEDS, USER_PASSWORD_RESET_LIFETIME, VIDEO_VIEW_LIFETIME } from '../initializers'
+import { CONFIG, USER_PASSWORD_RESET_LIFETIME, VIDEO_VIEW_LIFETIME } from '../initializers'
 
 type CachedRoute = {
   body: string,
@@ -67,14 +67,14 @@ class Redis {
     return cached as CachedRoute
   }
 
-  setCachedRoute (req: express.Request, body: any, contentType?: string, statusCode?: number) {
+  setCachedRoute (req: express.Request, body: any, lifetime: number, contentType?: string, statusCode?: number) {
     const cached: CachedRoute = {
       body: body.toString(),
       contentType,
       statusCode: statusCode.toString()
     }
 
-    return this.setObject(this.buildCachedRouteKey(req), cached, FEEDS.CACHE_LIFETIME)
+    return this.setObject(this.buildCachedRouteKey(req), cached, lifetime)
   }
 
   listJobs (jobsPrefix: string, state: string, mode: 'alpha', order: 'ASC' | 'DESC', offset: number, count: number) {
index a2c7f7cbdb68b59677def0bae83bcb1bed39aa2d..c589ef683c1b1d64e4b04d4f28bb3bb7380f5993 100644 (file)
@@ -2,36 +2,39 @@ import * as express from 'express'
 import { Redis } from '../lib/redis'
 import { logger } from '../helpers/logger'
 
-async function cacheRoute (req: express.Request, res: express.Response, next: express.NextFunction) {
-  const cached = await Redis.Instance.getCachedRoute(req)
+function cacheRoute (lifetime: number) {
+  return async function (req: express.Request, res: express.Response, next: express.NextFunction) {
+    const cached = await Redis.Instance.getCachedRoute(req)
 
-  // Not cached
-  if (!cached) {
-    logger.debug('Not cached result for route %s.', req.originalUrl)
+    // Not cached
+    if (!cached) {
+      logger.debug('Not cached result for route %s.', req.originalUrl)
 
-    const sendSave = res.send.bind(res)
+      const sendSave = res.send.bind(res)
 
-    res.send = (body) => {
-      if (res.statusCode >= 200 && res.statusCode < 400) {
-        Redis.Instance.setCachedRoute(req, body, res.getHeader('content-type').toString(), res.statusCode)
-             .catch(err => logger.error('Cannot cache route.', { err }))
+      res.send = (body) => {
+        if (res.statusCode >= 200 && res.statusCode < 400) {
+          const contentType = res.getHeader('content-type').toString()
+          Redis.Instance.setCachedRoute(req, body, lifetime, contentType, res.statusCode)
+               .catch(err => logger.error('Cannot cache route.', { err }))
+        }
+
+        return sendSave(body)
       }
 
-      return sendSave(body)
+      return next()
     }
 
-    return next()
-  }
+    if (cached.contentType) res.contentType(cached.contentType)
 
-  if (cached.contentType) res.contentType(cached.contentType)
+    if (cached.statusCode) {
+      const statusCode = parseInt(cached.statusCode, 10)
+      if (!isNaN(statusCode)) res.status(statusCode)
+    }
 
-  if (cached.statusCode) {
-    const statusCode = parseInt(cached.statusCode, 10)
-    if (!isNaN(statusCode)) res.status(statusCode)
+    logger.debug('Use cached result for %s.', req.originalUrl)
+    return res.send(cached.body).end()
   }
-
-  logger.debug('Use cached result for %s.', req.originalUrl)
-  return res.send(cached.body).end()
 }
 
 // ---------------------------------------------------------------------------