前提・実現したいこと
サーバーでファイルを受付けてファイル内のデータを計算・DBに登録するプログラムが既に動いています。
それに対して端末内のファイルを送信するバッチを作りたいです。
送信対象は2000以上あり、ファイルがある端末は14台あります。
CSVは1日1ファイルあり、ファイル名が日付になっています。
1台の端末内のファイルは日付が古い順にアップロードする必要があります。
古い順にアップロードする理由は、サーバー側の計算処理に前日のデータが必要なためです。
この処理は経常的に動かすものではなく、過去データを収集するのが目的です。
処理は
0. その端末内の送信対象ファイルのパスリストを作る(日付順)
0. リストをループさせながら、送信⇒レスポンスが返ってくるまで待つ
0. 次のファイルを送信する
という順で書いて、レスポンスを待つ部分はasync
とawait
を使いました。
試しに5ファイルを対象にサーバー側のCPUを監視しながら実行してみたのですが、開始・終了のログが5ファイル分一瞬で出力され、とてもレスポンスを待っているように見えません。
(サーバー側の処理は1ファイル辺り5秒ぐらいかかります)
それでも日付順に処理されるならいいかなと思ったのですが、サーバー側でもログを出してみると、バッチ側では日付順に送っているのに、その順番で処理されていませんでした。
どうやったら前のリクエストのレスポンスが返ってきてから次のリクエストを送信できるでしょうか?
該当のソースコード
サーバー側(抜粋)
入力チェックや計算処理など関係なさそうなところは省略しています。
javascript
1router.post('/upload', upload.single('file'), async (req, res)=>{ 2 const { file } = req; 3 let client; 4 try{ 5 client = await MongoClient.connect(DB_URL, {useNewUrlParser: true}); 6 const db = client.db("DB名"); 7 8 // ★デバッグ用のログ 9 console.log("処理開始:"+ file.originalname); 10 11 // DB登録処理(省略) 12 // 計算処理(省略) 13 // 計算結果の登録処理(省略) 14 15 } catch (err) { 16 console.log(err); 17 } finally { 18 if (client) client.close(); 19 } 20 res.status(200).send("OK"); 21})
バッチ側
javascriptですが、.bat
ファイルに書いて実行してます。
javascript
1//&cls&node %0 %1&pause > nul&exit 2 3const fs = require('fs') 4const path = require('path'); 5const axios = require('axios'); 6const FormData = require('form-data'); 7 8const URL = "アップロード先"; 9const FOLDER_PATH = "過去データのファイルパス"; 10 11const uploadfnc = async(path) =>{ 12 let ary = path.split("/"); 13 ary = ary.slice(-4); 14 let form = new FormData(); 15 form.append('key1', ary[0]); 16 form.append('key2', ary[1]); 17 form.append('key3', ary[2]); 18 form.append('file', fs.createReadStream(path)); 19 const result = await form.submit(URL); 20 21} 22// 対象のファイルパスの取得(listFilesの中身は省略してます) 23const pathList = listFiles(IKO_FOLDER_PATH); 24 25pathList.forEach( path => { 26 console.log('開始'+path); 27 uploadfnc(ary, path); 28 console.log('終了'+path); 29}, function(err) { 30 console.log(err); 31});
試しに5ファイル程で実行してみた結果が、
■バッチ側
※ファイル名が日付です。
開始:C:(パス)\key1\key2\key3\20190108.csv 終了:C:(パス)\key1\key2\key3\20190108.csv 開始:C:(パス)\key1\key2\key3\20190109.csv 終了:C:(パス)\key1\key2\key3\20190109.csv 開始:C:(パス)\key1\key2\key3\20190110.csv 終了:C:(パス)\key1\key2\key3\20190110.csv 開始:C:(パス)\key1\key2\key3\20190111.csv 終了:C:(パス)\key1\key2\key3\20190111.csv 開始:C:(パス)\key1\key2\key3\20190112.csv 終了:C:(パス)\key1\key2\key3\20190112.csv
開始と終了のログが間隔をあけずに出力されていて、レスポンスを待ってくれていないようです。
■サーバー側
処理開始:20190108.csv 処理開始:20190110.csv 処理開始:20190112.csv 処理開始:20190109.csv 処理開始:20190111.csv
ログの出力間隔を見ていると、ちゃんと前の処理が終わってから次の処理が行われていますが、処理順が送信順ではなくメチャクチャです。。。
試したこと
■バッチ側でsleepを入れてみる
javascript
1function sleep(time) { 2 const d1 = new Date(); 3 while (true) { 4 const d2 = new Date(); 5 if (d2 - d1 > time) { 6 return; 7 } 8 } 9} 10 11const pathList = listFiles(IKO_FOLDER_PATH); 12pathList.forEach( path => { 13 let ary = path.split("/"); 14 ary = ary.slice(-4); 15 console.log('開始'+path); 16 let form = new FormData(); 17 form.append('key1', ary[0]); 18 form.append('key2', ary[1]); 19 form.append('key3', ary[2]); 20 form.append('file', fs.createReadStream(path)); 21 22 form.submit(URL, function(err, res) { 23 console.log('終了'+path); 24 }); 25 26 sleep(10000); 27 28}, function(err) { 29 console.log("Receive err:" + err); 30});
結果のログはこうなってしまいました。(※3ファイルでテストしました)
開始:C:(パス)\key1\key2\key3\20190108.csv 開始:C:(パス)\key1\key2\key3\20190109.csv 開始:C:(パス)\key1\key2\key3\20190110.csv 終了:C:(パス)\key1\key2\key3\20190108.csv 終了:C:(パス)\key1\key2\key3\20190110.csv // ⇐9日と10日が逆に処理されている? 終了:C:(パス)\key1\key2\key3\20190109.csv
「開始:~」のログはちゃんと10秒間隔をあけて出力されていますが、その間サーバー側のCPUは上がらず、3行目が出た後で初めてサーバー側の処理が動き始めました。
「終了:~」のログも約5秒間隔(サーバーでの処理時間)に出ていて、私が期待する「リクエスト⇒レスポンス⇒リクエスト⇒レスポンス…」という処理順になってくれない上に、リクエストした順に処理してくれていないようです…。
補足情報(FW/ツールのバージョンなど)
■ローカル
Windows10
Node.js 10.15.1
■サーバー
CentOS 7
Apache 2.4
Node.js 10.15.1
(該当の処理はNuxt.js上のExpressで動いてます)
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/05/22 09:44
2019/05/22 11:09
2019/05/23 00:56
2019/05/23 07:16
2019/05/23 23:48