Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 110268 111686 get questionnaire order periodically #7153

Merged
1 change: 1 addition & 0 deletions packages/app/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -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_URI="http://host.docker.internal:3003"
# DRAWIO_URI="http://localhost:8080/?offline=1&https=0"
# S2SMSG_PUBSUB_SERVER_TYPE=nchan
# PUBLISH_OPEN_API=true
Expand Down
1 change: 1 addition & 0 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
"next-superjson": "^0.0.4",
"next-themes": "^0.2.0",
"nocache": "^3.0.1",
"node-cron": "^3.0.2",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

node 内の cron job 実行のために追加しました。
LICENSE 的に使って大丈夫だと思っています。

THIRD-PARTY-NOTICES はほぼ武井さんしかいじっていなかったので一旦いじりませんでした。

"nodemailer": "^6.6.2",
"nodemailer-ses-transport": "~1.5.0",
"openid-client": "^5.1.2",
Expand Down
7 changes: 7 additions & 0 deletions packages/app/src/server/crowi/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -105,6 +107,7 @@ Crowi.prototype.init = async function() {
await this.setupModels();
await this.setupConfigManager();
await this.setupSessionConfig();
await this.setupCron();

// setup messaging services
await this.setupS2sMessagingService();
Expand Down Expand Up @@ -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;

Expand Down
18 changes: 18 additions & 0 deletions packages/app/src/server/service/config-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,24 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
type: ValueType.STRING,
default: null,
},
GROWI_QUESTIONNAIRE_URI: {
ns: 'crowi',
key: 'app:growiQuestionnaireUri',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GROWI_QUESTIONNAIRE_SERVER_ORIGIN の方が直接的でいいかなと思います

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,
},
};


Expand Down
52 changes: 52 additions & 0 deletions packages/app/src/server/service/questionnaire-cron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import axios from '~/utils/axios';

const nodeCron = require('node-cron');

const getRandomInt = (min: number, max: number): number => {
const minInt = Math.ceil(min);
const maxInt = Math.floor(max);
return Math.floor(Math.random() * (maxInt - minInt) + minInt);
};

const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

どっかの /utils あたりにファイル作って移動したいです


class QuestionnaireCronService {

growiQuestionnaireUri: string;

cronSchedule: string;

maxHoursUntilRequest: number;

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
constructor(crowi) {
this.growiQuestionnaireUri = crowi.configManager?.getConfig('crowi', 'app:growiQuestionnaireUri');
this.cronSchedule = crowi.configManager?.getConfig('crowi', 'app:questionnaireCronSchedule');
this.maxHoursUntilRequest = crowi.configManager?.getConfig('crowi', 'app:questionnaireCronMaxHoursUntilRequest');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

今回の場合は環境変数でしか設定値を変更しないので大丈夫なのですが、コンストラクタで設定値を初期化してしまうと、設定値を UI 上で変更可能にした場合などに対応できなくなってしまうので、使う時に取得するのがいいかと思います


setUpCron(): void {
const maxSecondsUntilRequest = this.maxHoursUntilRequest * 60 * 60;
this.questionnaireOrderGetCron(this.cronSchedule, maxSecondsUntilRequest);
}

questionnaireOrderGetCron(cronSchedule: string, maxSecondsUntilRequest: number): void {
nodeCron.schedule(cronSchedule, async() => {
const secToSleep = getRandomInt(0, maxSecondsUntilRequest);

await sleep(secToSleep * 1000);

try {
const response = await axios.get(`${this.growiQuestionnaireUri}/questionnaire-order/index`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

axios-retry を使うと簡単にリトライできるので、もし余裕あれば変更お願いします。既に GROWI で使われてます

https://www.npmjs.com/package/axios-retry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

softonic/axios-retry#159
custom axios instance を使おうとするとエラーが起こるみたいで、growi で現在使われている場所と同じく、default の axios を使うようにしました。

const client = require('axios').default;

console.log(response.data);
}
catch (e) {
console.log(e);
}

}).start();
}

}

export default QuestionnaireCronService;
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16025,6 +16025,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"
Expand Down