From 6850dd1a5359c00256461021748fb6fde4ee8254 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 15 Dec 2017 15:49:56 -0600 Subject: [PATCH] redis optim - removes call for comment count when we already have totalCommentCount - removes job processor cleaner on non-processing nodes - fixed some template issues --- .../coral-embed-stream/src/graphql/utils.js | 4 ++-- .../src/tabs/stream/containers/Stream.js | 2 -- config.js | 4 ++++ routes/index.js | 4 ++-- services/kue.js | 19 +++++++++++++++---- services/settings.js | 3 ++- views/graphiql.ejs | 2 +- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index f4be867dd..dbe39933e 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -38,7 +38,7 @@ function applyToCommentsOrigin(root, callback) { function findAndInsertComment(parent, comment) { const isAsset = parent.__typename === 'Asset'; const [connectionField, countField, action] = isAsset - ? ['comments', 'commentCount', '$unshift'] + ? ['comments', 'totalCommentCount', '$unshift'] : ['replies', 'replyCount', '$push']; if ( @@ -79,7 +79,7 @@ export function insertCommentIntoEmbedQuery(root, comment) { function findAndRemoveComment(parent, id) { const [connectionField, countField] = parent.__typename === 'Asset' - ? ['comments', 'commentCount'] + ? ['comments', 'totalCommentCount'] : ['replies', 'replyCount']; const connection = parent[connectionField]; diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index e132ab954..1f80fe326 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -324,7 +324,6 @@ const fragments = { charCount requireEmailConfirmation } - commentCount @skip(if: $hasComment) totalCommentCount @skip(if: $hasComment) comments(query: {limit: 10, excludeIgnored: $excludeIgnored, sortOrder: $sortOrder, sortBy: $sortBy}) @skip(if: $hasComment) { nodes { @@ -345,7 +344,6 @@ const fragments = { const mapStateToProps = (state) => ({ auth: state.auth, refetching: state.embed.refetching, - commentCountCache: state.stream.commentCountCache, activeReplyBox: state.stream.activeReplyBox, commentId: state.stream.commentId, assetId: state.stream.assetId, diff --git a/config.js b/config.js index 76d488a0d..497573ab2 100644 --- a/config.js +++ b/config.js @@ -24,6 +24,10 @@ const CONFIG = { // indexes. CREATE_MONGO_INDEXES: process.env.DISABLE_CREATE_MONGO_INDEXES !== 'TRUE', + // SETTINGS_CACHE_TIME is the time that we'll cache the settings in redis before + // fetching again. + SETTINGS_CACHE_TIME: ms(process.env.TALK_SETTINGS_CACHE_TIME || '1hr'), + //------------------------------------------------------------------------------ // JWT based configuration //------------------------------------------------------------------------------ diff --git a/routes/index.js b/routes/index.js index 0ee012a79..8fc9e8f3f 100644 --- a/routes/index.js +++ b/routes/index.js @@ -110,9 +110,9 @@ router.use('/api/v1/graph/ql', apollo.graphqlExpress(createGraphOptions)); if (process.env.NODE_ENV !== 'production') { // Interactive graphiql interface. - router.use('/api/v1/graph/iql', (req, res) => { + router.use('/api/v1/graph/iql', staticTemplate, (req, res) => { res.render('graphiql', { - endpointURL: `${req.app.locals.BASE_URL}api/v1/graph/ql` + endpointURL: 'api/v1/graph/ql' }); }); diff --git a/services/kue.js b/services/kue.js index 01806632e..a3eb6d985 100644 --- a/services/kue.js +++ b/services/kue.js @@ -9,7 +9,8 @@ const kue = require('kue'); // singleton Queue instance. So you can configure and use only a single Queue // object within your node.js process. let queue = null; -const getQueue = () => { +let isManaging = false; +const getQueue = ({managed = false} = {}) => { if (queue) { return queue; } @@ -21,8 +22,16 @@ const getQueue = () => { } }); - // Watch for stuck jobs to manage. - queue.watchStuckJobs(1000); + // If this is a managed queue, and we aren't managing yet, then start the + // management. + if (managed && !isManaging) { + + // Watch for stuck jobs to manage. + queue.watchStuckJobs(60000); + + // Mark that we've now started management routines. + isManaging = true; + } return queue; }; @@ -67,7 +76,9 @@ class Task { * Process jobs for the queue. */ process(callback) { - return getQueue().process(this.name, callback); + + // Get the queue in managed mode. + return getQueue({managed: true}).process(this.name, callback); } /** diff --git a/services/settings.js b/services/settings.js index e8537c9c9..72915f43b 100644 --- a/services/settings.js +++ b/services/settings.js @@ -2,6 +2,7 @@ const SettingModel = require('../models/setting'); const cache = require('./cache'); const errors = require('../errors'); const {dotize} = require('./utils'); +const {SETTINGS_CACHE_TIME} = require('../config'); /** * The selector used to uniquely identify the settings document. @@ -35,7 +36,7 @@ module.exports = class SettingsService { if (process.env.NODE_ENV === 'production') { // When in production, wrap the settings retrieval with a cache. - const settings = await cache.h.wrap('settings', fields, 60, () => retrieve(fields)); + const settings = await cache.h.wrap('settings', fields, SETTINGS_CACHE_TIME / 1000, () => retrieve(fields)); return new SettingModel(settings); } diff --git a/views/graphiql.ejs b/views/graphiql.ejs index 5f1759c0d..b6d609de6 100644 --- a/views/graphiql.ejs +++ b/views/graphiql.ejs @@ -50,7 +50,7 @@ } } // We don't use safe-serialize for location, because it's not client input. - var fetchURL = locationQuery(otherParams, '<%= endpointURL %>'); + var fetchURL = locationQuery(otherParams, '<%= BASE_URL %><%= endpointURL %>'); // Defines a GraphQL fetcher using the fetch API. function graphQLFetcher(graphQLParams) {