私は、APIコールを実行し、オフセットを介して巨大なデータベースからJSONを順番に要求する関数をコーディングしています。 JSONレスポンスが解析され、その後のデータがCloud Firestoreサーバーにアップロードされます。Nodejs、Cloud Firestoreアップロードタスク - エラー:ソケットがハングアップする
Nodejs(ノード6.11.3)&最新Firebase管理SDK
情報が完全にコンソールに予想されるように解析され、そして印刷されています。
Auth error:Error: socket hang up
(node:846) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: -Number-): Error: Getting metadata from plugin failed with error: socket hang up
と時折::データは、しかし、私たちのFirestoreデータベースにアップロードしようとすると、コンソールにエラーメッセージをスパムされ
Auth error:Error: read ECONNRESET
のforeach関数は、ダウンロードしたJSONやプロセスからアイテムを収集しますFirestoreデータベースにアップロードする前のデータ。各JSONには、forEach関数を通過するための1000項目のデータ(1000ドキュメント分)があります。アップロードセットが終了する前に関数が繰り返されると、これが問題になる可能性があることを理解していますか?
私はコーディング初心者であり、この機能の制御フローが最良ではないことを理解しています。ただし、コンソールが印刷するエラーに関する情報は見つかりません。ソケットのハングアップに関する情報はたくさんありますが、Authエラーのセクションには何も見つかりません。
私は、firebase-adminsdkアカウントを使用するデータベースにアクセスするための認証情報として、生成されたサービスアカウントJSONを使用しています。私たちのデータベースに対する読み書きルールは現在、あらゆるアクセスを可能にするために開かれています(実際のユーザーでは開発されていません)。
ここは私の機能です:
Firebase初期&ゼロ-INGの
HTTPヘッダ実行var runFunction = function runFunction() {
var https = require('https');
var options = {
host: 'website.com',
path: (path including an offset and 1000 row specifier),
method: 'GET',
json: true,
headers: {
'content-type': 'application/json',
'Authorization': 'Basic ' + new Buffer('username' + ':' + 'password').toString('base64')
}
};
を設定する機能&を実行
const admin = require('firebase-admin'); var serviceAccount = require("JSON"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "URL" }); var db = admin.firestore(); var offset = 0; var failed = false;
をオフセット私たちはAPI
if (failed === false) {
var req = https.request(options, function (res) {
var body = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
});
res.on('end',() => {
console.log('Successfully processed HTTPS response');
body = JSON.parse(body);
if (body.hasOwnProperty('errors')) {
console.log('Body ->' + body)
console.log('API Call failed due to server error')
console.log('Function failed at ' + offset)
req.end();
return
} else {
if (body.hasOwnProperty('result')) {
let result = body.result;
if (Object.keys(result).length === 0) {
console.log('Function has completed');
failed = true;
return;
} else {
result.forEach(function (item) {
var docRef = db.collection('collection').doc(name);
console.log(name);
var upload = docRef.set({
thing: data,
thing2: data,
})
});
console.log('Finished offset ' + offset)
offset = offset + 1000;
failed = false;
}
if (failed === false) {
console.log('Function will repeat with new offset');
console.log('offset = ' + offset);
req.end();
runFunction();
} else {
console.log('Function will terminate');
}
}
}
});
});
req.on('error', (err) => {
console.log('Error -> ' + err)
console.log('Function failed at ' + offset)
console.log('Repeat from the given offset value or diagnose further')
req.end();
});
req.end();
} else {
req.end();
}
};
runFunction();
からの応答の終わりに達していない場合はHTTPリクエスト&再実行機能を任意の助けいただければ幸いです!ソケット100までの1000年からの誤差が少ないハングアップ -
UPDATE
私はちょうど私が一度に引くと、その後の機能を使用して、一度にアップロードJSONの行を変更してみました頻繁に、それは間違いなくデータベースの過負荷のためです。
それぞれのfor each配列の反復が前の反復が完了するのを待ってから開始するのが理想的です。
UPDATE#2
私は非同期モジュールをインストールしていると私は現在、一度に1本の文書のアップロードを実行するためにasync.eachSeries機能を使用しています。中途半端にアップロードされたすべてのエラーは表示されなくなりますが、機能には非常に時間がかかります(158,000文書の場合、約9時間)。
(node:16168) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: -Number-): Error: The datastore operation timed out, or the data was temporarily unavailable.
今私の機能が長すぎるを取っているかのように思え:一定期間後にデータベースがこのエラーを返し、また
async.eachSeries(result, function (item, callback) {
// result.forEach(function (item) {
var docRef = db.collection('collection').doc(name);
console.log(name);
var upload = docRef.set({
thing: data,
thing2: data,
}, { merge: true }).then(ref => {
counter = counter + 1
if (counter == result.length) {
console.log('Finished offset ' + offset)
offset = offset + 1000;
console.log('Function will repeat with new offset')
console.log('offset = ' + offset);
failed = false;
counter = 0
req.end();
runFunction();
}
callback()
});
});
:私の更新されたループのコードが実行さカウンターで、これです...長くないのではなく。誰かが明示的なエラーなしでこれをより速く走らせる方法に関する助言を持っていますか?
各Firestore docSetによって返された個別の約束を使用する方がよい場合があります。私は前のチャンクのすべてがアップロードされたときに自分のコードが次のアップロードチャンクに渡るように、これの中で約束を解決します。イテレーションの間の待機の必要性を取り除きます。 – Hendies