Ich bin eine Funktion, die API-Aufrufe und JSON von einer riesigen Datenbank in Folge über Offsets anfordert codiert. Die JSON-Antwort wird analysiert und anschließend werden die nachfolgenden Daten auf unseren Cloud Firestore-Server hochgeladen.Nodejs, Cloud Firestore Hochladen Aufgaben - Auth Fehler: Fehler: Socket auflegen
NodeJS (Node 6.11.3) & Neueste Firebase Admin SDK
Die Informationen analysiert wird, wie erwartet, und druckt die perfekt Konsole.
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
und gelegentlich: Wenn die Daten versucht jedoch zu unserer Firestore-Datenbank zu laden, wird die Konsole mit der Fehlermeldung spammed
Auth error:Error: read ECONNRESET
Die forEach Funktion die Elemente aus dem heruntergeladenen JSON sammelt und Prozesse die Daten vor dem Hochladen in die Firestore-Datenbank. Jeder JSON enthält bis zu 1000 Datenelemente (1000 Dokumente), die die ForEach-Funktion durchlaufen. Ich verstehe, dass dies ein Problem sein könnte, wenn die Funktion wiederholt wird, bevor der Upload-Satz fertig ist?
Ich bin ein Codierungsneuling und verstehe, dass der Kontrollfluss dieser Funktion nicht der beste ist. Ich kann jedoch keine Informationen zu dem Fehler finden, den die Konsole druckt. Ich kann viele Informationen über Sockets aufhängen, aber keine auf der Auth-Fehler-Abschnitt.
Ich verwende ein generiertes Service-Konto JSON als Berechtigungsnachweis für den Zugriff auf unsere Datenbank, die das firebase-adminsdk-Konto verwendet. Unsere Lese-/Schreibregeln für die Datenbank sind derzeit offen, um jeglichen Zugriff zu erlauben (da wir uns in der Entwicklung befinden, ohne echte Benutzer).
Hier ist meine Funktion:
Firebase Initialisierung & Offset-Null-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;
die Funktion & Lauf Einstellung HTTP-Header
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')
}
};
das Laufen HTTP Request & Wieder läuft die Funktion, wenn wir nicht das Ende der Antwort von der API erreicht
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();
Jede Hilfe wäre sehr dankbar!
UPDATE
Ich habe versucht, nur die Zeilen von JSON zu ändern, die ich zu einer Zeit ziehen und anschließend zu einem Zeitpunkt laden mit der Funktion - weniger von 1000 bis 100. Der Sockel aufzulegen Fehler häufig, so ist es definitiv wegen Überlastung der Datenbank.
Idealerweise wäre es perfekt, wenn jede ForAtach-Array-Iteration auf den Abschluss der vorherigen Iteration wartet, bevor sie beginnt.
UPDATE # 2
ich das Asynchron-Modul installiert haben, und ich bin derzeit die async.eachSeries Funktion zu einem Zeitpunkt ein Dokument Upload auszuführen. Alle Fehler in der Mitte des Uploads verschwinden - die Funktion wird jedoch unglaublich lange dauern (ungefähr 9 Stunden für 158.000 Dokumente). Meine aktualisiert Schleife Code ist dies mit einem Zähler implementiert:
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()
});
});
Auch nach einer gewissen Zeit gibt die Datenbank diesen Fehler:
(node:16168) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: -Number-): Error: The datastore operation timed out, or the data was temporarily unavailable.
Es scheint, als ob jetzt meine Funktion dauert zu lange ... statt nicht lang genug. Hat jemand einen Ratschlag, wie man diesen Lauf ohne angegebene Fehler schneller machen kann?
Sie könnten die einzelnen Versprechen, die von jedem firestore docSet zurückgegeben werden, besser verwenden. Ich löse Versprechungen auf, so dass mein Code nur auf den nächsten Upload-Chunk übergeht, wenn alle vorherigen Chunks hochgeladen wurden. Entfernt Wartezeiten zwischen Iterationen. – Hendies