Fixed unclosed prepared database queries blocking server. Added better error checking and bad request fallbacks to webapp
This commit is contained in:
@@ -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
2
webapp/dist/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user