questionnaire-cron.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import axiosRetry from 'axios-retry';
  2. import { StatusType } from '~/interfaces/questionnaire/questionnaire-answer-status';
  3. import { IQuestionnaireOrder } from '~/interfaces/questionnaire/questionnaire-order';
  4. import loggerFactory from '~/utils/logger';
  5. import { getRandomIntInRange } from '~/utils/rand';
  6. import { sleep } from '~/utils/sleep';
  7. import QuestionnaireAnswerStatus from '../models/questionnaire/questionnaire-answer-status';
  8. import QuestionnaireOrder from '../models/questionnaire/questionnaire-order';
  9. const logger = loggerFactory('growi:service:questionnaire-cron');
  10. const axios = require('axios').default;
  11. const nodeCron = require('node-cron');
  12. axiosRetry(axios, { retries: 3 });
  13. class QuestionnaireCronService {
  14. crowi: any;
  15. cronJob: any;
  16. // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  17. constructor(crowi) {
  18. this.crowi = crowi;
  19. }
  20. startCron(): void {
  21. const cronSchedule = this.crowi.configManager?.getConfig('crowi', 'app:questionnaireCronSchedule');
  22. const maxHoursUntilRequest = this.crowi.configManager?.getConfig('crowi', 'app:questionnaireCronMaxHoursUntilRequest');
  23. const maxSecondsUntilRequest = maxHoursUntilRequest * 60 * 60;
  24. this.cronJob = this.questionnaireOrderGetCron(cronSchedule, maxSecondsUntilRequest);
  25. this.cronJob.start();
  26. }
  27. stopCron(): void {
  28. this.cronJob.stop();
  29. }
  30. private questionnaireOrderGetCron(cronSchedule: string, maxSecondsUntilRequest: number) {
  31. const growiQuestionnaireServerOrigin = this.crowi.configManager?.getConfig('crowi', 'app:growiQuestionnaireServerOrigin');
  32. const saveOrders = async(questionnaireOrders: IQuestionnaireOrder[]) => {
  33. const currentDate = new Date(Date.now());
  34. // save questionnaires that are not finished (doesn't have to be started)
  35. const nonFinishedOrders = questionnaireOrders.filter(order => new Date(order.showUntil) > currentDate);
  36. await QuestionnaireOrder.insertMany(nonFinishedOrders);
  37. };
  38. return nodeCron.schedule(cronSchedule, async() => {
  39. // sleep for a random amount to scatter request time from GROWI apps to questionnaire server
  40. const secToSleep = getRandomIntInRange(0, maxSecondsUntilRequest);
  41. await sleep(secToSleep * 1000);
  42. try {
  43. const response = await axios.get(`${growiQuestionnaireServerOrigin}/questionnaire-order/index`);
  44. const questionnaireOrders: IQuestionnaireOrder[] = response.data.questionnaireOrders;
  45. // Reset status (denied => not_answered)
  46. await QuestionnaireAnswerStatus.updateMany(
  47. { status: StatusType.denied },
  48. { status: StatusType.not_answered },
  49. );
  50. // Cleanup
  51. await QuestionnaireOrder.deleteMany();
  52. await saveOrders(questionnaireOrders);
  53. }
  54. catch (e) {
  55. logger.error(e);
  56. }
  57. });
  58. }
  59. }
  60. export default QuestionnaireCronService;