Sails の便利な機能や自分が作った Model を使ってバッチ処理を定期的にやりたいとかありますよね。
同じことを考えた人たちが既に何人かいて、Issue に投稿してたりしてるんですが、本家に採り入れられるまでには至ってません。
(「誰か Pull Request 送ってくれれば採用するよ」と言ってますが、今のところ誰もやってない。残念)
色々書き方はあるようですが、できるだけ Sails の素直なスタイルで最小限に書ける方法をここでは紹介します。
必要な NPM パッケージをインストール
定時実行と言えば UNIX システムの cron が思い浮かびますが、OS の機能に依存するのはイケてません。Node のサーバは常に起動されているはずなので、Node に実行してもらいましょう。
node-cron という NPM パッケージを使います。タイムゾーン指定に node-time も必要なので、併せてインストールします。
$ npm install cron --save
$ npm install time --save
config/crontab.js を作成
config/
ディレクトリに crontab.js
というファイルを作成して、そこにタイムテーブルと実行したい処理を JSON 形式で記述します。
module.exports.crontab = {
"*/10 * * * *": function hoge() {
// 10分ごとに /tmp/hoge-{NOW}.txt ファイルを作成する
var fs = require('fs');
var file = '/tmp/hoge-' + Date.now() + '.txt';
fs.writeFile(file, Date.now(), function(err) {
if (err) {
sails.log.error("Hoge file writing error occured.");
throw err;
} else {
sails.log("Hoge file has been wrote successfully.");
}
});
},
"0,15,30,45 * * * *": function piyo() {
// 15分ごとに /tmp/piyo-{NOW}.txt ファイルを作成する
var fs = require('fs');
var file = '/tmp/piyo-' + Date.now() + '.txt';
fs.writeFile(file, Date.now(), function(err) {
if (err) {
sails.log.error("Piyo file writing error occured.");
throw err;
} else {
sails.log("Piyo file has been wrote successfully.");
}
});
}
}
タイムテーブルの書式は UNIX システムの cron と同じで以下の通り。
分|時|日|月|曜日
---|---|---|---|---|---
|0-59|0-23|1-31|1-12|0-7|
詳しくは crontab の man 等を参照のこと。
config/bootstrap.js で登録
config/bootstrap.js
は Sails 起動時に実行したい処理を書いておくためのファイルですが、ここで crontab.js
に記述されたジョブを登録するようにします。
module.exports.bootstrap = function(cb) {
cb();
// Register cron jobs
var CronJob = require('cron').CronJob;
var jobs = sails.config.crontab;
for (table in jobs) {
if (typeof table === 'string') {
new CronJob(table, jobs[table], null, true, 'Asia/Tokyo');
}
}
これで、sails lift
すると、config/crontab.js
に記述された処理が定時実行されます。
なお注意点として、タイムテーブルの文字列を JSON のキーにしているため、同じタイムテーブルの処理を config/crontab.js
に並べて記述すると、先に書いたものが上書きされてしまいます。同じタイムテーブルで実行したい処理がある場合は、まとめて書いておきましょう。
module.exports.crontab = {
"0 9 * * *": function hoge() { /** hogeの処理 **/ }, // 上書きされる
"0 9 * * *": function piyo() { /** piyoの処理 **/ }
}
もうちょっと整理して書くには
上の例では crontab.js
に処理を直書きしてますが、もうちょっと整理して書きたい場合は、処理そのものは api/services/
に書いて、crontab.js
ではそれをコールするだけというようにすると、すっきりした構造になります。