我正在編寫一個函數,該函數運行API調用並通過偏移量從大型數據庫按順序請求JSON。解析JSON響應,然後將其中的後續數據上傳到我們的Cloud Firestore服務器。Nodejs,雲Firestore上傳任務 - 身份驗證錯誤:錯誤:套接字掛斷
的NodeJS(節點6.11.3)&最新火力地堡聯繫SDK
預期的信息進行解析,並打印到控制檯完美。當數據試圖但是上傳到我們公司的FireStore數據庫,控制檯垃圾郵件與錯誤信息:
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
偶爾:
Auth error:Error: read ECONNRESET
在foreach功能收集來自下載JSON和流程的項目上傳到Firestore數據庫之前的數據。每個JSON最多可以有1000個數據項(1000個文檔值)通過forEach函數。我知道,如果在上傳設置完成之前重複該功能,這可能是一個問題?
我是一個編碼新手,並且明白這個函數的控制流並不是最好的。但是,我無法找到有關控制檯打印錯誤的任何信息。我可以找到有關套接字掛起的大量信息,但沒有在驗證錯誤部分中找到。
我使用生成的服務帳戶JSON作爲憑據訪問我們的數據庫,該數據庫使用firebase-adminsdk帳戶。我們對數據庫的讀/寫規則目前是開放的,以允許任何訪問(因爲我們正在開發沒有真正的用戶)。
這裏是我的功能:
火力地堡初始化&零偏移-ING
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;
運行功能&設置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')
}
};
運行HTTP請求&重新運行該功能,如果我們沒有從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();
任何幫助將不勝感激達到響應的結束!
UPDATE
我只是試圖改變JSON的,我拉的時間和使用功能,在隨後的時間上傳行 - 從1000下降到100座掛斷誤差不頻繁出現,所以肯定是由於數據庫超載。
理想情況下,如果每個forEach數組迭代在開始之前等待先前的迭代完成,那將是完美的。
更新#2
我已經安裝了異步模塊和我目前使用的async.eachSeries功能在每次執行一個文件上傳。上傳中的所有錯誤消失 - 但是該功能將花費大量時間完成(對於158,000個文檔,大約需要9小時)。我更新的循環代碼是這樣的,以實現一個計數器:
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()
});
});
而且,一段時間後,數據庫返回此錯誤:
(node:16168) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: -Number-): Error: The datastore operation timed out, or the data was temporarily unavailable.
看來,如果現在我的作用時間過長...而不是不夠長。有沒有人有任何建議如何使這個運行更快,沒有錯誤?
你可能會更好地使用每個firestore docSet返回的個體承諾。我解決了這個問題中的承諾,以便當所有前面的塊已經上傳時,我的代碼只傳遞到下一個上傳塊。消除了在迭代之間等待的需要。 – Hendies