mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
Fix some bugginess with how expired alerts and alert max_duration were handled. Closes #34
This commit is contained in:
@@ -35,11 +35,8 @@ class AlertProvider:
|
|||||||
for alert in alerts:
|
for alert in alerts:
|
||||||
# Fill in any blanks
|
# Fill in any blanks
|
||||||
alert.infer_missing()
|
alert.infer_missing()
|
||||||
# Add to the list, provided it meets the semsible date test. If alerts have an end time, it must be in the
|
# Add to the list, provided it heas not already expired.
|
||||||
# future, or if not, then the start date must be at least in the last 24 hours.
|
if not alert.expired():
|
||||||
if (alert.end_time and alert.end_time > datetime.now(pytz.UTC).timestamp()) or (
|
|
||||||
not alert.end_time and alert.start_time > (datetime.now(
|
|
||||||
pytz.UTC) - timedelta(days=1)).timestamp()):
|
|
||||||
self.alerts.add(alert.id, alert, expire=MAX_ALERT_AGE)
|
self.alerts.add(alert.id, alert, expire=MAX_ALERT_AGE)
|
||||||
|
|
||||||
# Stop any threads and prepare for application shutdown
|
# Stop any threads and prepare for application shutdown
|
||||||
|
|||||||
@@ -34,13 +34,10 @@ class CleanupTimer:
|
|||||||
self.alerts.expire()
|
self.alerts.expire()
|
||||||
|
|
||||||
# Alerts can persist in the system for a while, so we want to explicitly clean up any alerts that have
|
# Alerts can persist in the system for a while, so we want to explicitly clean up any alerts that have
|
||||||
# definitively ended, or if they have no definite end time, then if the start time was more than 24 hours
|
# expired
|
||||||
# ago.
|
|
||||||
for id in list(self.alerts.iterkeys()):
|
for id in list(self.alerts.iterkeys()):
|
||||||
alert = self.alerts[id]
|
alert = self.alerts[id]
|
||||||
if (alert.end_time and alert.end_time < datetime.now(pytz.UTC).timestamp()) or (
|
if alert.expired():
|
||||||
not alert.end_time and alert.start_time < (datetime.now(
|
|
||||||
pytz.UTC) - timedelta(days=1)).timestamp()):
|
|
||||||
self.alerts.evict(id)
|
self.alerts.evict(id)
|
||||||
|
|
||||||
self.status = "OK"
|
self.status = "OK"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import copy
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import copy
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.constants import DXCC_FLAGS
|
from core.constants import DXCC_FLAGS
|
||||||
@@ -117,4 +117,12 @@ class Alert:
|
|||||||
|
|
||||||
# JSON serialise
|
# JSON serialise
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)
|
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)
|
||||||
|
|
||||||
|
# Decide if this alert has expired (in which case it should not be added to the system in the first place, and not
|
||||||
|
# returned by the web server if later requested, and removed by the cleanup functions. "Expired" is defined as
|
||||||
|
# either having an end_time in the past, or if it only has a start_time, then that start time was more than 3 hours
|
||||||
|
# ago. If it somehow doesn't have a start_time either, it is considered to be expired.
|
||||||
|
def expired(self):
|
||||||
|
return not self.start_time or (self.end_time and self.end_time < datetime.now(pytz.UTC).timestamp()) or (
|
||||||
|
not self.end_time and self.start_time < (datetime.now(pytz.UTC) - timedelta(hours=3)).timestamp())
|
||||||
|
|||||||
@@ -187,6 +187,8 @@ class WebServer:
|
|||||||
alerts = []
|
alerts = []
|
||||||
for k in alert_ids:
|
for k in alert_ids:
|
||||||
alerts.append(self.alerts.get(k))
|
alerts.append(self.alerts.get(k))
|
||||||
|
# We never want alerts that seem to be in the past
|
||||||
|
alerts = list(filter(lambda alert: not alert.expired(), alerts))
|
||||||
alerts = sorted(alerts, key=lambda alert: (alert.start_time if alert and alert.start_time else 0))
|
alerts = sorted(alerts, key=lambda alert: (alert.start_time if alert and alert.start_time else 0))
|
||||||
for k in query.keys():
|
for k in query.keys():
|
||||||
match k:
|
match k:
|
||||||
@@ -195,8 +197,10 @@ class WebServer:
|
|||||||
alerts = [a for a in alerts if a.received_time > since]
|
alerts = [a for a in alerts if a.received_time > since]
|
||||||
case "max_duration":
|
case "max_duration":
|
||||||
max_duration = int(query.get(k))
|
max_duration = int(query.get(k))
|
||||||
alerts = [a for a in alerts if (a.end_time and a.end_time - a.start_time <= max_duration) or (
|
# Check the duration if end_time is provided. If end_time is not provided, assume the activation is
|
||||||
not a.end_time and datetime.now(pytz.UTC).timestamp() - a.start_time <= max_duration)]
|
# "short", i.e. it always passes this check.
|
||||||
|
alerts = [a for a in alerts if (a.end_time and a.end_time - a.start_time <= max_duration) or
|
||||||
|
not a.end_time]
|
||||||
case "source":
|
case "source":
|
||||||
sources = query.get(k).split(",")
|
sources = query.get(k).split(",")
|
||||||
alerts = [a for a in alerts if a.source in sources]
|
alerts = [a for a in alerts if a.source in sources]
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ class GMA(HTTPSpotProvider):
|
|||||||
sig_refs_names=[source_spot["NAME"]],
|
sig_refs_names=[source_spot["NAME"]],
|
||||||
time=datetime.strptime(source_spot["DATE"] + source_spot["TIME"], "%Y%m%d%H%M").replace(
|
time=datetime.strptime(source_spot["DATE"] + source_spot["TIME"], "%Y%m%d%H%M").replace(
|
||||||
tzinfo=pytz.UTC).timestamp(),
|
tzinfo=pytz.UTC).timestamp(),
|
||||||
latitude=float(source_spot["LAT"]) if (source_spot["LAT"] != "") else None,
|
latitude=float(source_spot["LAT"]) if (source_spot["LAT"] and source_spot["LAT"] != "") else None,
|
||||||
# Seen GMA spots with no lat/lon
|
# Seen GMA spots with no (or empty) lat/lon
|
||||||
longitude=float(source_spot["LON"]) if (source_spot["LON"] != "") else None)
|
longitude=float(source_spot["LON"]) if (source_spot["LON"] and source_spot["LON"] != "") else None)
|
||||||
|
|
||||||
# GMA doesn't give what programme (SIG) the reference is for until we separately look it up.
|
# GMA doesn't give what programme (SIG) the reference is for until we separately look it up.
|
||||||
ref_response = self.REF_INFO_CACHE.get(self.REF_INFO_URL_ROOT + source_spot["REF"],
|
ref_response = self.REF_INFO_CACHE.get(self.REF_INFO_URL_ROOT + source_spot["REF"],
|
||||||
|
|||||||
@@ -48,11 +48,17 @@ function updateTable() {
|
|||||||
// Split alerts into three types, each of which will get its own table header: On now, next 24h, and later. "On now"
|
// Split alerts into three types, each of which will get its own table header: On now, next 24h, and later. "On now"
|
||||||
// is considered to be events with an end_time where start<now<end, or events with no end time that started in the
|
// is considered to be events with an end_time where start<now<end, or events with no end time that started in the
|
||||||
// last hour.
|
// last hour.
|
||||||
onNow = alerts.filter(a => (a["end_time"] != null && moment.unix(a["end_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore())
|
onNow = alerts.filter(a => (a["end_time"] != null && a["end_time"] != 0 && moment.unix(a["end_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore())
|
||||||
|| (a["end_time"] == null && moment.unix(a["start_time"]).utc().add(1, 'hours').isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore()));
|
|| ((a["end_time"] == null || a["end_time"] == 0) && moment.unix(a["start_time"]).utc().add(1, 'hours').isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore()));
|
||||||
next24h = alerts.filter(a => moment.unix(a["start_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().subtract(24, 'hours').isBefore());
|
next24h = alerts.filter(a => moment.unix(a["start_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().subtract(24, 'hours').isBefore());
|
||||||
later = alerts.filter(a => moment.unix(a["start_time"]).utc().subtract(24, 'hours').isSameOrAfter());
|
later = alerts.filter(a => moment.unix(a["start_time"]).utc().subtract(24, 'hours').isSameOrAfter());
|
||||||
|
|
||||||
|
alerts.forEach(a => {
|
||||||
|
if (!(a in onNow) && !(a in next24h) && !(a in later)) {
|
||||||
|
console.log(moment.unix(a["start_time"]).format('YYYY-MM-DD hh:mm') + " " + moment.unix(a["end_time"]).format('YYYY-MM-DD hh:mm'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (onNow.length > 0) {
|
if (onNow.length > 0) {
|
||||||
table.find('tbody').append('<tr class="table-primary"><td colspan="100" style="text-align:center;">On Now</td></tr>');
|
table.find('tbody').append('<tr class="table-primary"><td colspan="100" style="text-align:center;">On Now</td></tr>');
|
||||||
addAlertRowsToTable(table.find('tbody'), onNow);
|
addAlertRowsToTable(table.find('tbody'), onNow);
|
||||||
|
|||||||
@@ -66,13 +66,13 @@ function updateRefreshDisplay() {
|
|||||||
count = REFRESH_INTERVAL_SEC - secSinceUpdate;
|
count = REFRESH_INTERVAL_SEC - secSinceUpdate;
|
||||||
if (count <= 60) {
|
if (count <= 60) {
|
||||||
var number = count.toFixed(0);
|
var number = count.toFixed(0);
|
||||||
updatingString = "Updating in " + number + " second" + (number != "1" ? "s" : "") + ". ";
|
updatingString = "Updating in <span class='nowrap'>" + number + " second" + (number != "1" ? "s" : "") + ".</span>";
|
||||||
} else {
|
} else {
|
||||||
var number = Math.round(count / 60.0).toFixed(0);
|
var number = Math.round(count / 60.0).toFixed(0);
|
||||||
updatingString = "Updating in " + number + " minute" + (number != "1" ? "s" : "") + ". ";
|
updatingString = "Updating in <span class='nowrap'>" + number + " minute" + (number != "1" ? "s" : "") + ".</span>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$("#timing-container").text("Last updated at " + lastUpdateTime.format('HH:mm') + " UTC. " + updatingString);
|
$("#timing-container").html("Last updated at " + lastUpdateTime.format('HH:mm') + " UTC. " + updatingString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user