mirror of
https://github.com/wassname/talk.git
synced 2026-07-09 13:45:13 +08:00
initial impl of cached action counts using ee
This commit is contained in:
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"eslint.autoFixOnSave": true,
|
||||
"editor.tabSize": 2,
|
||||
"editor.rulers": [
|
||||
80
|
||||
],
|
||||
"files.trimTrailingWhitespace": true
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
const ActionModel = require('../../models/action');
|
||||
const ActionsService = require('../../services/actions');
|
||||
const UsersService = require('../../services/users');
|
||||
const errors = require('../../errors');
|
||||
@@ -52,10 +51,7 @@ const createAction = async ({user = {}, pubsub, loaders: {Comments}}, {item_id,
|
||||
* @return {Promise} resolves to the deleted action, or null if not found.
|
||||
*/
|
||||
const deleteAction = ({user}, {id}) => {
|
||||
return ActionModel.findOneAndRemove({
|
||||
id,
|
||||
user_id: user.id
|
||||
});
|
||||
return ActionsService.delete({id, user_id: user.id});
|
||||
};
|
||||
|
||||
module.exports = (context) => {
|
||||
|
||||
+9
-1
@@ -66,15 +66,23 @@ const CommentSchema = new Schema({
|
||||
enum: COMMENT_STATUS,
|
||||
default: 'NONE'
|
||||
},
|
||||
|
||||
// parent_id is the id of the parent comment (null if there is none).
|
||||
parent_id: String,
|
||||
|
||||
// Counts to store related to actions taken on the given comment.
|
||||
action_counts: {
|
||||
default: {},
|
||||
type: Object,
|
||||
},
|
||||
|
||||
// Tags are added by the self or by administrators.
|
||||
tags: [TagLinkSchema],
|
||||
|
||||
// Additional metadata stored on the field.
|
||||
metadata: {
|
||||
default: {},
|
||||
type: Object
|
||||
type: Object,
|
||||
}
|
||||
}, {
|
||||
timestamps: {
|
||||
|
||||
+50
-31
@@ -1,6 +1,30 @@
|
||||
const ActionModel = require('../models/action');
|
||||
const _ = require('lodash');
|
||||
const errors = require('../errors');
|
||||
const events = require('./events');
|
||||
|
||||
const findOneAndUpdate = async (query, update, options = {}) => new Promise((resolve, reject) => {
|
||||
ActionModel.findOneAndUpdate(query, update, Object.assign({}, options, {
|
||||
|
||||
// Use raw result to get `updatedExisting`.
|
||||
passRawResult: true,
|
||||
|
||||
// Ensure that if it's new, we return the new object created.
|
||||
new: true,
|
||||
|
||||
// Perform an upsert in the event that this doesn't exist.
|
||||
upsert: true,
|
||||
|
||||
// Set the default values if not provided based on the mongoose models.
|
||||
setDefaultsOnInsert: true
|
||||
}), (err, doc, raw) => {
|
||||
if (err) { return reject(err); }
|
||||
if (raw.lastErrorObject.updatedExisting) {
|
||||
return reject(new errors.ErrAlreadyExists(raw.value));
|
||||
}
|
||||
return resolve(raw.value);
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = class ActionsService {
|
||||
|
||||
@@ -19,46 +43,26 @@ module.exports = class ActionsService {
|
||||
* @param {String} action the new action to the item
|
||||
* @return {Promise}
|
||||
*/
|
||||
static insertUserAction(action) {
|
||||
static async insertUserAction(action) {
|
||||
|
||||
// Actions are made unique by using a query that can be reproducable, i.e.,
|
||||
// not containing user inputable values.
|
||||
let query = {
|
||||
let foundAction = await findOneAndUpdate({
|
||||
action_type: action.action_type,
|
||||
item_type: action.item_type,
|
||||
item_id: action.item_id,
|
||||
user_id: action.user_id,
|
||||
group_id: action.group_id
|
||||
};
|
||||
group_id: action.group_id,
|
||||
}, {
|
||||
|
||||
// Create/Update the action.
|
||||
return new Promise((resolve, reject) => {
|
||||
ActionModel.findOneAndUpdate(
|
||||
query, {
|
||||
|
||||
// Only set when not existing.
|
||||
$setOnInsert: action,
|
||||
}, {
|
||||
|
||||
// Ensure that if it's new, we return the new object created.
|
||||
new: true,
|
||||
|
||||
// Use raw result to get `updatedExisting`.
|
||||
passRawResult: true,
|
||||
|
||||
// Perform an upsert in the event that this doesn't exist.
|
||||
upsert: true,
|
||||
|
||||
// Set the default values if not provided based on the mongoose models.
|
||||
setDefaultsOnInsert: true
|
||||
}, (err, doc, raw) => {
|
||||
if (err) { return reject(err); }
|
||||
if (raw.lastErrorObject.updatedExisting) {
|
||||
return reject(new errors.ErrAlreadyExists(raw.value));
|
||||
}
|
||||
return resolve(raw.value);
|
||||
});
|
||||
// Only set when not existing.
|
||||
$setOnInsert: action,
|
||||
});
|
||||
|
||||
// Emit that there was a new action created.
|
||||
events.emit('actions.new', foundAction);
|
||||
|
||||
return foundAction;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,6 +194,21 @@ module.exports = class ActionsService {
|
||||
});
|
||||
}
|
||||
|
||||
static async delete({id, user_id}) {
|
||||
let action = await ActionModel.findOneAndRemove({
|
||||
id,
|
||||
user_id,
|
||||
});
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit that the action was deleted.
|
||||
events.emit('actions.delete', action);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all comments ids for a specific action.
|
||||
* @param {String} action_type type of action
|
||||
|
||||
@@ -5,6 +5,49 @@ const ActionsService = require('./actions');
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = class CommentsService {
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
const {EventEmitter2} = require('eventemitter2');
|
||||
const debug = require('debug')('talk:services:events');
|
||||
const enabled = require('debug').enabled('talk:services:events');
|
||||
|
||||
const events = new EventEmitter2({
|
||||
wildcard: true,
|
||||
});
|
||||
|
||||
// If event debugging is enabled, bind the debugger to all events being emitted
|
||||
// and log a debug message.
|
||||
if (enabled) {
|
||||
events.onAny(function(event) {
|
||||
debug(`[${event}] ${arguments.length - 1} argument${arguments.length - 1 === 1 ? '' : 's'}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = events;
|
||||
Reference in New Issue
Block a user