improved event layout, added db indicies

This commit is contained in:
Wyatt Johnson
2017-08-17 11:56:58 -06:00
parent d4536cb1a2
commit 165d07cae9
6 changed files with 108 additions and 49 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ AssetSchema.index({
subsection: 'text',
author: 'text'
}, {
background: true
background: true,
});
/**
+17
View File
@@ -102,6 +102,23 @@ CommentSchema.index({
background: false
});
// Add an index that is optimized for sorting based on the action count data.
CommentSchema.index({
'created_at': 1,
'action_counts': 1,
}, {
background: true,
});
// Add an index that is optimized for sorting based on the created_at timestamp
// but also good at locating comments that have a specific asset id.
CommentSchema.index({
'asset_id': 1,
'created_at': 1,
}, {
background: true,
});
CommentSchema.virtual('edited').get(function() {
return this.body_history.length > 1;
});
+33 -6
View File
@@ -2,8 +2,21 @@ const ActionModel = require('../models/action');
const _ = require('lodash');
const errors = require('../errors');
const events = require('./events');
const {
ACTIONS_NEW,
ACTIONS_DELETE,
} = require('./events/constants');
const findOneAndUpdate = async (query, update, options = {}) => new Promise((resolve, reject) => {
/**
* findOnlyOneAndUpdate will perform a fondOneAndUpdate on the mongo collection
* and ensure that the found record wasn't already found. This is essentially
* a "findOneOrUpsert".
*
* @param {object} query the query operation for the mongo findOneAndUpdate op
* @param {object} update the update operation for the mongo findOneAndUpdate op
* @param {object} options the options operation for the mongo findOneAndUpdate op
*/
const findOnlyOneAndUpdate = async (query, update, options = {}) => new Promise((resolve, reject) => {
ActionModel.findOneAndUpdate(query, update, Object.assign({}, options, {
// Use raw result to get `updatedExisting`.
@@ -30,6 +43,7 @@ module.exports = class ActionsService {
/**
* Finds an action by the id.
*
* @param {String} id identifier of the action (uuid)
*/
static findById(id) {
@@ -38,6 +52,7 @@ module.exports = class ActionsService {
/**
* Inserts an action.
*
* @param {String} item_id identifier of the item (uuid)
* @param {String} user_id user id of the action (uuid)
* @param {String} action the new action to the item
@@ -47,7 +62,7 @@ module.exports = class ActionsService {
// Actions are made unique by using a query that can be reproducable, i.e.,
// not containing user inputable values.
let foundAction = await findOneAndUpdate({
let foundAction = await findOnlyOneAndUpdate({
action_type: action.action_type,
item_type: action.item_type,
item_id: action.item_id,
@@ -60,13 +75,14 @@ module.exports = class ActionsService {
});
// Emit that there was a new action created.
events.emitAsync('actions.new', foundAction);
events.emitAsync(ACTIONS_NEW, foundAction);
return foundAction;
}
/**
* Finds actions in an array of ids.
*
* @param {String} ids array of user identifiers (uuid)
*/
static async findByItemIdArray(item_ids) {
@@ -84,6 +100,7 @@ module.exports = class ActionsService {
/**
* Fetches the action summaries for the given asset, and comments around the
* given user id.
*
* @param {[type]} asset_id [description]
* @param {[type]} comments [description]
* @param {String} [current_user_id=''] [description]
@@ -110,7 +127,8 @@ module.exports = class ActionsService {
}
/**
* Returns summaries of actions for an array of ids
* Returns summaries of actions for an array of ids.
*
* @param {String} ids array of user identifiers (uuid)
*/
static getActionSummaries(item_ids, current_user_id = '') {
@@ -182,8 +200,9 @@ module.exports = class ActionsService {
]);
}
/*
/**
* Finds all comments for a specific action.
*
* @param {String} action_type type of action
* @param {String} item_type type of item the action is on
*/
@@ -194,6 +213,13 @@ module.exports = class ActionsService {
});
}
/**
* delete will remove the record from the collection if it exists. Otherwise
* it will do nothing. This will then return the deleted action.
*
* @param {object} param the action to use as the query source, for which we
* only look at the id, user_id.
*/
static async delete({id, user_id}) {
let action = await ActionModel.findOneAndRemove({
id,
@@ -204,13 +230,14 @@ module.exports = class ActionsService {
}
// Emit that the action was deleted.
events.emitAsync('actions.delete', action);
events.emitAsync(ACTIONS_DELETE, action);
return action;
}
/**
* Finds all comments ids for a specific action.
*
* @param {String} action_type type of action
* @param {String} item_type type of item the action is on
*/
+50 -42
View File
@@ -6,48 +6,10 @@ const SettingsService = require('./settings');
const errors = require('../errors');
const events = require('./events');
// When a new action is created, modify the comment.
events.on('actions.new', async (action) => {
if (!action || action.item_type !== 'COMMENTS') {
return;
}
const ACTION_TYPE = action.action_type.toLowerCase();
try {
await CommentModel.update({
id: action.item_id,
}, {
$inc: {
[`action_counts.${ACTION_TYPE}`]: 1,
}
});
} catch (err) {
console.error(`Can't increment the action_counts.${ACTION_TYPE}:`, err);
}
});
// When an action is deleted, modify the comment.
events.on('actions.delete', async (action) => {
if (!action || action.item_type !== 'COMMENTS') {
return;
}
const ACTION_TYPE = action.action_type.toLowerCase();
try {
await CommentModel.update({
id: action.item_id,
}, {
$inc: {
[`action_counts.${ACTION_TYPE}`]: -1,
}
});
} catch (err) {
console.error(`Can't decrement the action_counts.${ACTION_TYPE}:`, err);
}
});
const {
ACTIONS_NEW,
ACTIONS_DELETE,
} = require('./events/constants');
module.exports = class CommentsService {
@@ -333,3 +295,49 @@ module.exports = class CommentsService {
return CommentModel.find(query);
}
};
//==============================================================================
// Event Hooks
//==============================================================================
// When a new action is created, modify the comment.
events.on(ACTIONS_NEW, async (action) => {
if (!action || action.item_type !== 'COMMENTS') {
return;
}
const ACTION_TYPE = action.action_type.toLowerCase();
try {
await CommentModel.update({
id: action.item_id,
}, {
$inc: {
[`action_counts.${ACTION_TYPE}`]: 1,
}
});
} catch (err) {
console.error(`Can't increment the action_counts.${ACTION_TYPE}:`, err);
}
});
// When an action is deleted, modify the comment.
events.on(ACTIONS_DELETE, async (action) => {
if (!action || action.item_type !== 'COMMENTS') {
return;
}
const ACTION_TYPE = action.action_type.toLowerCase();
try {
await CommentModel.update({
id: action.item_id,
}, {
$inc: {
[`action_counts.${ACTION_TYPE}`]: -1,
}
});
} catch (err) {
console.error(`Can't decrement the action_counts.${ACTION_TYPE}:`, err);
}
});
+2
View File
@@ -0,0 +1,2 @@
module.exports.ACTIONS_DELETE = 'actions.delete';
module.exports.ACTIONS_NEW = 'actions.new';
@@ -14,4 +14,9 @@ if (enabled) {
});
}
// The default error handler.
events.on('error', (err) => {
console.error('events error:', err);
});
module.exports = events;