NEWS
Skript läuft ab und zu in Timeout bei InfluxDB-Abfrage
-
Hi, ich habe seit dem Update auf den Skript-Engine 8.8.2 folgenden Fehler in einem meiner Skripts, die Abfrage dauert wohl solange, dass es zu einem TImeout kommt.
Das kann durchaus sein, weil es sich um sehr viele Daten handelt.
Ich lasse es 4h/laufen und 2h läuft es ohne TImeout und 2x kommt es zu einem Timeout (wahrscheinlich weil in dem Moment noch andere Sachen passieren und zu viel Last auf dem System ist oder so).
Kann ich das Timeout-Limit irgendwo erhöhen oder verstehe ich die Fehlermeldung grundsätzlich falsch?at process.processTimers (node:internal/timers:512:7) javascript.0 2024-08-10 11:30:34.229 error at listOnTimeout (node:internal/timers:569:17) j.avascript.0 2024-08-10 11:30:34.229 error at Timeout._onTimeout (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:3078:38)
-
@cedric
Zeig mal Dein Script.https://forum.iobroker.net/topic/51555/hinweise-für-gute-forenbeiträge
-
// returns device id of state, device or channel-id function getDeviceId(id) { return id.match(/(.+[a-zA-Z0-9]{24})/g)[0]; } // return group if auf state, device or channel-id function getGroupId(id) { return id.match(/(.+[a-zA-Z0-9-]{36})/g)[0]; } // fenster auf, temparatur falsch var devices = $('state[id=hmip.*.devices.*.channels.1.windowOpen]'); // hmip.1.devices.3014F711A000155F298D9D3B console.log("Anzahl (gesamt) devices window open, wrong temperature: " + devices.length); var cnt = 0; devices.each(function (id_fk, i){ sendTo('influxdb.0', 'getHistory', { id: id_fk, options: { end: Date.now(), count: 10, aggregate: 'none' // or 'none' to get raw values } }, function (result) { //console.log("RESULTSET 1 LENGTH: " + result.result.length); var window_open_currently = (i == 9 && result.result[i].val); //console.log("FENSTER IST CURRENTLY OPEN: " + window_open_currently); var window_open_from = null; var window_open_to = null; for (var i = result.result.length-1; i >= 0 ; i--) { //console.log("RESULT" +i + ": " + result.result[i].val + ' ' + new Date(result.result[i].ts).toISOString()); // TO: is not set, current is FALSE and next is TRUE if( window_open_to == null && !result.result[i].val && (i-1 >= 0) && result.result[i-1].val) { window_open_to = result.result[i].ts } // FROM: TO has to be set, current value has to be TRUE and next FALSE if( window_open_to != null && window_open_from == null && result.result[i].val && (i-1 >= 0) && !result.result[i-1].val) { window_open_from = result.result[i].ts } } // check if resultset is big enough if( window_open_from == null || window_open_to == null) { return; } // get thermostat var name_fk = getObject(getDeviceId(id_fk)).common.name; var name_room = name_fk.substring(0, name_fk.lastIndexOf("_")); var name_t = name_room + "_T"; //console.log("namen des fenstersensors: " + name_fk); //console.log("namen des thermos: " + name_t); //console.log("window_open_from: " + new Date(window_open_from).toISOString()); //console.log("window_open_to: " + new Date(window_open_to).toISOString()); // thermo zu fk finden var thermos = $('state[id=hmip.*.devices.*.channels.1.setPointTemperature]'); thermos.each(function (id, i){ if( getObject(getDeviceId(id)).common.name.includes(name_t)){ //console.log("thermostat zu fenstersensor gefunden: " + getObject(getDeviceId(id)).common.name + " zu " + name_fk); // in db gucken nach temps sendTo('influxdb.0', 'getHistory', { id: id, options: { end: new Date(window_open_to), //.setMilliseconds(new Date(window_open_to).getMilliseconds() - 3000), start: new Date(window_open_from), //.setMilliseconds(new Date(window_open_to).getMilliseconds() + 3000), //count: 1, //limit: 1, aggregate: 'none' // or 'none' to get raw values } }, function (result) { var temp_avg = 0; //console.log("RESULTS ALS FENSTER AUF WAR LENGTH: " + result.result.length); for (var i = 0; i < result.result.length; i++) { temp_avg = temp_avg + result.result[i].val; //console.log(getObject(getDeviceId(id)).common.name +' von ' + new Date(window_open_from).toISOString()+ ' bis ' + new Date(window_open_to).toISOString()+ ' set temp: ' + result.result[i].val ); //console.log(getObject(getDeviceId(id)).common.name + ' (' + name_fk + '): ' + new Date(result.result[i].ts).toISOString()+ ' set temp: ' + result.result[i].val ); } if( result.result.length > 0) { temp_avg = temp_avg / result.result.length; // check if window-open-temp is > 5°C if( temp_avg > 5) { // console.log(getObject(getDeviceId(id)).common.name + ' (' + name_fk + '): ' + temp_avg); //devices_error_status[getObject(getDeviceId(id)).common.name] = "window open, wrong temperature (" + temp_avg.toFixed(1) + "°C)"; cnt++; } } }); } }); // thermos }); // db abfrage fk }); // fensterkontakte
Timeout resultiert darin, dass im inneren getHistory result.result undefiniert wird.
-
Kann ich irgendwo definieren, wann ein Timeout erfolgen soll?
Für mich sieht es so aus, als wäre es immer nach 30sek innerhalb der sendTo-Methode (an verschiedenen stellen im Skript.
Das kann auch durchaus sein, dass es länger als 30sek dauert, kann ich den Timeout-Wert irgendwo auf 60sek erhöhen? -
@cedric sagte in Skript läuft ab und zu in Timeout bei InfluxDB-Abfrage:
Kann ich irgendwo definieren, wann ein Timeout erfolgen soll?
Bitte teile mal den Link zur der Doku, welche diese Frage nicht beantwortet.
Gibt doch sogar ein Beispiel mit dem Timeout...
-
@cedric
Dass es sich um einen Timeout der Datenbank handelt, hättest Du ruhig erwähnen dürfen.
Bei Influx bin ich raus. -
@codierknecht sagte in Skript läuft ab und zu in Timeout bei InfluxDB-Abfrage:
Dass es sich um einen Timeout der Datenbank handelt, hättest Du ruhig erwähnen dürfen.
Der Timeout funktioniert bei jedem sendTo gleich. Egal auf was gewartet wird. Das heißt einfach nur, dass die andere Instanz x Millisekunden Zeit hat, auf die Anfrage zu antworten. Ansonsten wird ein Timeout-Error generiert. Das ist nötig, da sonst die Logik ewig hängen bleiben könnte. z.B. wenn man mit
await sendToAsync(...)
arbeitet.https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#sendto
Beispiel:
sendTo('telegram.0', { user: 'UserName', text: 'Test message' }, { timeout: 2000 }, (res) => { log(`Sent to ${res} users`); });
-
@haus-automatisierung sagte in Skript läuft ab und zu in Timeout bei InfluxDB-Abfrage:
Der Timeout funktioniert bei jedem sendTo gleich. Egal auf was gewartet wird. Das heißt einfach nur, dass die andere Instanz x Millisekunden Zeit hat, auf die Anfrage zu antworten
Soweit klar. Aber bei einer Interaktion mit 'ner Datenbank ist ein Timeout ganz schnell mal zu kurz.
Vor allem wennes sich um sehr viele Daten handelt
-
@codierknecht sagte in Skript läuft ab und zu in Timeout bei InfluxDB-Abfrage:
bei einer Interaktion mit 'ner Datenbank ist ein Timeout ganz schnell mal zu kurz.
Klar, deswegen kann man den ja konfigurieren. Das Problem am Script von @cedric ist aber auch, dass alle
getHistory
Befehle praktisch parallel laufen und damit natürlich noch einmal die Last auf die Datenbank steigt.Wäre also besser mit Promises zu arbeiten und die Abfragen nacheinander abzuarbeiten.
-
@haus-automatisierung tausend Dank! Ich habe in der Dokumentation vom Influxdb geguckt und in den globalen Einstellungen vom Javaskript-Adapter, bin allerdings nicht darauf gekommen, dass es in der sendTo-Methode sein könnte.
Läuft jetzt wieder alles: