Fixed unclosed prepared database queries blocking server. Added better error checking and bad request fallbacks to webapp

This commit is contained in:
Daniel Ledda
2020-11-28 09:05:59 +01:00
parent 785e40d0ec
commit 1f2df8b069
3 changed files with 38 additions and 35 deletions

View File

@@ -30,6 +30,10 @@ func writeSnapshotToDb(snapshotSub *SnapshotSubmission) (int64, error) {
queryStr := "INSERT INTO `snapshots` (`temp`, `humidity`, `co2`, `time`, `id`) VALUES (?, ?, ?, ?, NULL);" queryStr := "INSERT INTO `snapshots` (`temp`, `humidity`, `co2`, `time`, `id`) VALUES (?, ?, ?, ?, NULL);"
query, err := ClimateDb.Prepare(queryStr) query, err := ClimateDb.Prepare(queryStr)
if err != nil { if err != nil {
closeErr := query.Close()
if closeErr != nil {
return -1, fmt.Errorf("couldn't prepare snapshot query: %w. (also failed to close: %s)", err, closeErr.Error())
}
return -1, fmt.Errorf("couldn't prepare snapshot query: %w", err) return -1, fmt.Errorf("couldn't prepare snapshot query: %w", err)
} }
result, err := query.Exec( result, err := query.Exec(

2
webapp/dist/main.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,4 @@
import Chart from "chart.js/dist/Chart.bundle.min"; import Chart from "chart.js/dist/Chart.bundle.min";
import type {ChartPoint} from "chart.js";
import {generateClimateChartConfig} from "./climateChartConfig"; import {generateClimateChartConfig} from "./climateChartConfig";
import {config} from "./main"; import {config} from "./main";
@@ -53,48 +52,48 @@ class ClimateChart {
throw new Error(`improper HTML element passed, needed type canvas, got ${canvasElement.tagName}`); throw new Error(`improper HTML element passed, needed type canvas, got ${canvasElement.tagName}`);
} }
this.chart = new Chart(ctx, generateClimateChartConfig({})); this.chart = new Chart(ctx, generateClimateChartConfig({}));
try { setInterval(this.doUpdateInterval, 30 * 1000);
const payload = await this.getInitialDataBlob(); await this.doUpdateInterval();
this.latestSnapshot = payload.snapshots[0]; this.onLoadedCallback();
this.insertSnapshots(...payload.snapshots); }
this.rerender();
setInterval(async () => this.updateFromServer().catch(e => this.logError(e)), 30 * 1000); private async doUpdateInterval() {
this.onLoadedCallback(); await this.updateFromServer().catch(e => this.logError(e));
} }
catch (e) {
new Error(`Server error: ${e}`) private async getNewSnapshots(): Promise<SnapshotRecords> {
const lastTimeInChart = this.latestSnapshot?.time ?? null;
if (!lastTimeInChart) {
const minutesAsDate = (new Date().getTime() - this.minutesDisplayed * 60000);
const dataEndpoint = `${ this.dataEndpointBase }?since=${ new Date(minutesAsDate).toISOString() }`;
return (await fetch(dataEndpoint)).json();
} else {
const url = `${ this.dataEndpointBase }?since=${ new Date(lastTimeInChart + "+00:00").toISOString() }`;
return (await fetch(url)).json();
} }
} }
private async getInitialDataBlob(): Promise<SnapshotRecords> { private async tryGetNewSnapshots(): Promise<SnapshotRecords> {
const minutesAsDate = (new Date().getTime() - this.minutesDisplayed * 60000); try {
const dataEndpoint = `${ this.dataEndpointBase }?since=${ new Date(minutesAsDate).toISOString() }`; return this.getNewSnapshots();
const payload = await (await fetch(dataEndpoint)).json(); } catch (e) {
if (payload.snapshots.length < 0) { this.logError(`Server error: ${e}`);
throw new Error("Bad response - no snapshots found!"); return { snapshots: [] };
} }
return payload;
} }
private async updateFromServer() { private async updateFromServer() {
const lastTimeInChart = this.latestSnapshot.time; const payload = await this.tryGetNewSnapshots();
const url = `${ this.dataEndpointBase }?since=${ new Date(this.latestSnapshot.time + "+00:00").toISOString() }`; if (payload.snapshots.length > 0) {
try { const oldLatestTime = new Date(this.latestSnapshot?.time ?? null).getTime();
const payload: SnapshotRecords = await (await fetch(url)).json(); const newLatestTime = new Date(payload.snapshots[0].time).getTime();
if (payload.snapshots.length > 0) { if (newLatestTime > oldLatestTime) {
const newLatestTime = new Date(payload.snapshots[0].time).getTime(); this.removePointsOlderThan(newLatestTime - this.minutesDisplayed * 60000);
if (newLatestTime > new Date(lastTimeInChart).getTime()) { this.latestSnapshot = payload.snapshots[0];
console.log(payload); this.insertSnapshots(...payload.snapshots);
this.removePointsOlderThan(newLatestTime - this.minutesDisplayed * 60000); this.rerender();
this.latestSnapshot = payload.snapshots[0];
this.insertSnapshots(...payload.snapshots);
this.rerender();
}
} }
} }
catch (e) {
this.logError(`Server error: ${e}`);
}
} }
private rerender() { private rerender() {