activity.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { getModelSafely } from '@growi/core';
  2. import mongoose from 'mongoose';
  3. import { IActivity } from '~/interfaces/activity';
  4. import { IPage } from '~/interfaces/page';
  5. import Activity from '~/server/models/activity';
  6. import loggerFactory from '../../utils/logger';
  7. import Crowi from '../crowi';
  8. const logger = loggerFactory('growi:service:ActivityService');
  9. type ParameterType = Omit<IActivity, 'createdAt'>
  10. class ActivityService {
  11. crowi!: Crowi;
  12. activityEvent: any;
  13. constructor(crowi: Crowi) {
  14. this.crowi = crowi;
  15. this.activityEvent = crowi.event('activity');
  16. this.updateByParameters = this.updateByParameters.bind(this);
  17. this.createTtlIndex();
  18. this.initActivityEventListeners();
  19. }
  20. initActivityEventListeners(): void {
  21. this.activityEvent.on('update', async(activityId: string, parameters: ParameterType, target?: IPage) => {
  22. // update activity
  23. let activity: IActivity;
  24. try {
  25. activity = await this.updateByParameters(activityId, parameters);
  26. }
  27. catch (err) {
  28. logger.error('Update activity failed', err);
  29. return;
  30. }
  31. this.activityEvent.emit('updated', activity, target);
  32. });
  33. }
  34. createTtlIndex = async function() {
  35. if (this.crowi.configManager == null) {
  36. return;
  37. }
  38. const activityExpirationSeconds = this.crowi.configManager.getConfig('crowi', 'app:activityExpirationSeconds');
  39. if (activityExpirationSeconds == null) {
  40. return;
  41. }
  42. const collection = mongoose.connection.collection('activities');
  43. try {
  44. const targetField = 'createdAt_1';
  45. const indexes = await collection.getIndexes();
  46. const isExistTargetField = Object.keys(indexes).includes(targetField);
  47. if (isExistTargetField) {
  48. await collection.dropIndex(targetField);
  49. }
  50. }
  51. catch (err) {
  52. logger.error('Failed to drop target index', err);
  53. return;
  54. }
  55. try {
  56. // Set retention period only if activityExpirationSeconds is not null
  57. await collection.createIndex({ createdAt: 1 }, { expireAfterSeconds: activityExpirationSeconds });
  58. }
  59. catch (err) {
  60. logger.error('Failed to create TTL indexes', err);
  61. }
  62. };
  63. /**
  64. * @param {object} parameters
  65. * @return {Promise}
  66. */
  67. createByParameters = function(parameters) {
  68. const Activity = getModelSafely('Activity') || require('../models/activity')(this.crowi);
  69. return Activity.create(parameters);
  70. };
  71. updateByParameters = async function(activityId: string, parameters: ParameterType): Promise<IActivity> {
  72. const activity = await Activity.findOneAndUpdate({ _id: activityId }, parameters, { new: true }) as unknown as IActivity;
  73. return activity;
  74. };
  75. /**
  76. * @param {User} user
  77. * @return {Promise}
  78. */
  79. findByUser = function(user) {
  80. return this.find({ user }).sort({ createdAt: -1 }).exec();
  81. };
  82. }
  83. module.exports = ActivityService;