ソースを参照

Merge pull request #7153 from arafubeatbox/feat/110268-111686-get-questionnaire-order-periodically

feat: 110268 111686 get questionnaire order periodically
Haku Mizuki 3 年 前
コミット
e981eb4eeb

+ 1 - 0
packages/app/.env.development

@@ -17,6 +17,7 @@ ELASTICSEARCH_REJECT_UNAUTHORIZED=true
 HACKMD_URI="http://localhost:3010"
 HACKMD_URI_FOR_SERVER="http://hackmd:3000"
 OGP_URI="http://ogp:8088"
+GROWI_QUESTIONNAIRE_SERVER_ORIGIN="http://host.docker.internal:3003"
 # DRAWIO_URI="http://localhost:8080/?offline=1&https=0"
 # S2SMSG_PUBSUB_SERVER_TYPE=nchan
 # PUBLISH_OPEN_API=true

+ 1 - 0
packages/app/package.json

@@ -137,6 +137,7 @@
     "next-superjson": "^0.0.4",
     "next-themes": "^0.2.0",
     "nocache": "^3.0.1",
+    "node-cron": "^3.0.2",
     "nodemailer": "^6.6.2",
     "nodemailer-ses-transport": "~1.5.0",
     "openid-client": "^5.1.2",

+ 7 - 0
packages/app/src/server/crowi/index.js

@@ -29,11 +29,13 @@ import PageGrantService from '../service/page-grant';
 import PageOperationService from '../service/page-operation';
 // eslint-disable-next-line import/no-cycle
 import { PluginService } from '../service/plugin';
+import QuestionnaireCronService from '../service/questionnaire-cron';
 import SearchService from '../service/search';
 import { SlackIntegrationService } from '../service/slack-integration';
 import { UserNotificationService } from '../service/user-notification';
 import { initMongooseGlobalSettings, getMongoUri, mongoOptions } from '../util/mongoose-utils';
 
+
 const logger = loggerFactory('growi:crowi');
 const httpErrorHandler = require('../middlewares/http-error-handler');
 const models = require('../models');
@@ -105,6 +107,7 @@ Crowi.prototype.init = async function() {
   await this.setupModels();
   await this.setupConfigManager();
   await this.setupSessionConfig();
+  this.setupCron();
 
   // setup messaging services
   await this.setupS2sMessagingService();
@@ -304,6 +307,10 @@ Crowi.prototype.setupModels = async function() {
   });
 };
 
+Crowi.prototype.setupCron = function() {
+  new QuestionnaireCronService(this).setUpCron();
+};
+
 Crowi.prototype.scanRuntimeVersions = async function() {
   const self = this;
 

+ 18 - 0
packages/app/src/server/service/config-loader.ts

@@ -646,6 +646,24 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
     type: ValueType.STRING,
     default: null,
   },
+  GROWI_QUESTIONNAIRE_SERVER_ORIGIN: {
+    ns: 'crowi',
+    key: 'app:growiQuestionnaireServerOrigin',
+    type: ValueType.STRING,
+    default: null,
+  },
+  QUESTIONNAIRE_CRON_SCHEDULE: {
+    ns: 'crowi',
+    key: 'app:questionnaireCronSchedule',
+    type: ValueType.STRING,
+    default: '0 22 * * *',
+  },
+  QUESTIONNAIRE_CRON_MAX_HOURS_UNTIL_REQUEST: {
+    ns: 'crowi',
+    key: 'app:questionnaireCronMaxHoursUntilRequest',
+    type: ValueType.NUMBER,
+    default: 4,
+  },
 };
 
 

+ 48 - 0
packages/app/src/server/service/questionnaire-cron.ts

@@ -0,0 +1,48 @@
+import axiosRetry from 'axios-retry';
+
+import { getRandomIntInRange } from '~/utils/rand';
+import { sleep } from '~/utils/sleep';
+
+const axios = require('axios').default;
+const nodeCron = require('node-cron');
+
+axiosRetry(axios, { retries: 3 });
+
+class QuestionnaireCronService {
+
+  crowi: any;
+
+  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+  constructor(crowi) {
+    this.crowi = crowi;
+  }
+
+  setUpCron(): void {
+    const cronSchedule = this.crowi.configManager?.getConfig('crowi', 'app:questionnaireCronSchedule');
+    const maxHoursUntilRequest = this.crowi.configManager?.getConfig('crowi', 'app:questionnaireCronMaxHoursUntilRequest');
+
+    const maxSecondsUntilRequest = maxHoursUntilRequest * 60 * 60;
+    this.questionnaireOrderGetCron(cronSchedule, maxSecondsUntilRequest);
+  }
+
+  questionnaireOrderGetCron(cronSchedule: string, maxSecondsUntilRequest: number): void {
+    const growiQuestionnaireServerOrigin = this.crowi.configManager?.getConfig('crowi', 'app:growiQuestionnaireServerOrigin');
+    nodeCron.schedule(cronSchedule, async() => {
+      const secToSleep = getRandomIntInRange(0, maxSecondsUntilRequest);
+
+      await sleep(secToSleep * 1000);
+
+      try {
+        const response = await axios.get(`${growiQuestionnaireServerOrigin}/questionnaire-order/index`);
+        console.log(response.data);
+      }
+      catch (e) {
+        console.log(e);
+      }
+
+    }).start();
+  }
+
+}
+
+export default QuestionnaireCronService;

+ 5 - 0
packages/app/src/utils/rand.ts

@@ -0,0 +1,5 @@
+export const getRandomIntInRange = (min: number, max: number): number => {
+  const minInt = Math.ceil(min);
+  const maxInt = Math.floor(max);
+  return Math.floor(Math.random() * (maxInt - minInt) + minInt);
+};

+ 1 - 0
packages/app/src/utils/sleep.ts

@@ -0,0 +1 @@
+export const sleep = (msec: number): Promise<void> => new Promise(resolve => setTimeout(resolve, msec));

+ 7 - 0
yarn.lock

@@ -15954,6 +15954,13 @@ nocache@^3.0.1:
   resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.1.tgz#54d8b53a7e0a0aa1a288cfceab8a3cefbcde67d4"
   integrity sha512-Gh39xwJwBKy0OvFmWfBs/vDO4Nl7JhnJtkqNP76OUinQz7BiMoszHYrIDHHAaqVl/QKVxCEy4ZxC/XZninu7nQ==
 
+node-cron@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/node-cron/-/node-cron-3.0.2.tgz#bb0681342bd2dfb568f28e464031280e7f06bd01"
+  integrity sha512-iP8l0yGlNpE0e6q1o185yOApANRe47UPbLf4YxfbiNHt/RU5eBcGB/e0oudruheSf+LQeDMezqC5BVAb5wwRcQ==
+  dependencies:
+    uuid "8.3.2"
+
 node-emoji@^1.11.0:
   version "1.11.0"
   resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c"