2 Commits

Author SHA1 Message Date
Ian Renton
2fead92dc5 SSE updates every 5 seconds is probably fine, we don't really need every second. #3 2025-12-24 08:57:38 +00:00
Ian Renton
e8ca488001 Run/Pause button #3 2025-12-24 08:53:44 +00:00
5 changed files with 34 additions and 17 deletions

View File

@@ -10,6 +10,9 @@ import tornado_eventsource.handler
from core.prometheus_metrics_handler import api_requests_counter from core.prometheus_metrics_handler import api_requests_counter
from core.utils import serialize_everything from core.utils import serialize_everything
SSE_HANDLER_MAX_QUEUE_SIZE = 100
SSE_HANDLER_QUEUE_CHECK_INTERVAL = 5000
# API request handler for /api/v1/alerts # API request handler for /api/v1/alerts
class APIAlertsHandler(tornado.web.RequestHandler): class APIAlertsHandler(tornado.web.RequestHandler):
@@ -63,11 +66,11 @@ class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
self.query_params = {k: v[0].decode("utf-8") for k, v in self.request.arguments.items()} self.query_params = {k: v[0].decode("utf-8") for k, v in self.request.arguments.items()}
# Create a alert queue and add it to the web server's list. The web server will fill this when alerts arrive # Create a alert queue and add it to the web server's list. The web server will fill this when alerts arrive
self.alert_queue = Queue(maxsize=100) self.alert_queue = Queue(maxsize=SSE_HANDLER_MAX_QUEUE_SIZE)
self.sse_alert_queues.append(self.alert_queue) self.sse_alert_queues.append(self.alert_queue)
# Set up a timed callback to check if anything is in the queue # Set up a timed callback to check if anything is in the queue
self.heartbeat = tornado.ioloop.PeriodicCallback(self._callback, 1000) self.heartbeat = tornado.ioloop.PeriodicCallback(self._callback, SSE_HANDLER_QUEUE_CHECK_INTERVAL)
self.heartbeat.start() self.heartbeat.start()
except Exception as e: except Exception as e:

View File

@@ -10,6 +10,9 @@ import tornado_eventsource.handler
from core.prometheus_metrics_handler import api_requests_counter from core.prometheus_metrics_handler import api_requests_counter
from core.utils import serialize_everything from core.utils import serialize_everything
SSE_HANDLER_MAX_QUEUE_SIZE = 1000
SSE_HANDLER_QUEUE_CHECK_INTERVAL = 5000
# API request handler for /api/v1/spots # API request handler for /api/v1/spots
class APISpotsHandler(tornado.web.RequestHandler): class APISpotsHandler(tornado.web.RequestHandler):
@@ -65,11 +68,11 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
self.query_params = {k: v[0].decode("utf-8") for k, v in self.request.arguments.items()} self.query_params = {k: v[0].decode("utf-8") for k, v in self.request.arguments.items()}
# Create a spot queue and add it to the web server's list. The web server will fill this when spots arrive # Create a spot queue and add it to the web server's list. The web server will fill this when spots arrive
self.spot_queue = Queue(maxsize=1000) self.spot_queue = Queue(maxsize=SSE_HANDLER_MAX_QUEUE_SIZE)
self.sse_spot_queues.append(self.spot_queue) self.sse_spot_queues.append(self.spot_queue)
# Set up a timed callback to check if anything is in the queue # Set up a timed callback to check if anything is in the queue
self.heartbeat = tornado.ioloop.PeriodicCallback(self._callback, 1000) self.heartbeat = tornado.ioloop.PeriodicCallback(self._callback, SSE_HANDLER_QUEUE_CHECK_INTERVAL)
self.heartbeat.start() self.heartbeat.start()
except Exception as e: except Exception as e:

View File

@@ -10,7 +10,7 @@
<div class="mt-3"> <div class="mt-3">
<div id="settingsButtonRow" class="row"> <div id="settingsButtonRow" class="row">
<div class="col-lg-6 me-auto pt-3"> <div class="col-lg-6 me-auto pt-3 hideonmobile">
<p id="timing-container">Loading...</p> <p id="timing-container">Loading...</p>
</div> </div>
<div class="col-lg-6 text-end"> <div class="col-lg-6 text-end">
@@ -22,7 +22,7 @@
<input type="radio" class="btn-check" name="runPause" id="pauseButton" autocomplete="off"> <input type="radio" class="btn-check" name="runPause" id="pauseButton" autocomplete="off">
<label class="btn btn-outline-primary" for="pauseButton"><i class="fa-solid fa-pause"></i> Pause</label> <label class="btn btn-outline-primary" for="pauseButton"><i class="fa-solid fa-pause"></i> Pause</label>
</span> </span>
<span style="position: relative;"> <span class="hideonmobile" style="position: relative;">
<i id="searchicon" class="fa-solid fa-magnifying-glass"></i> <i id="searchicon" class="fa-solid fa-magnifying-glass"></i>
<input id="search" type="search" class="form-control" oninput="filtersUpdated();" placeholder="Search"> <input id="search" type="search" class="form-control" oninput="filtersUpdated();" placeholder="Search">
</span> </span>

View File

@@ -345,13 +345,6 @@ div.band-spot:hover span.band-spot-info {
max-height: 26em; max-height: 26em;
overflow: scroll; overflow: scroll;
} }
/* No search on mobile */
input#search {
display: none;
}
i#searchicon {
display: none;
}
} }
@media (min-width: 992px) { @media (min-width: 992px) {

View File

@@ -19,8 +19,11 @@ function loadSpots() {
spots = jsonData; spots = jsonData;
// Update table // Update table
updateTable(); updateTable();
// Start SSE connection to fetch updates in the background // Start SSE connection to fetch updates in the background, if we are in "run" mode
let run = $('#runButton:checked').val();
if (run) {
startSSEConnection(); startSSEConnection();
}
}); });
} }
@@ -70,8 +73,8 @@ function startSSEConnection() {
// Update the special timing display for the live spots page, which varies depending on run/pause selection. // Update the special timing display for the live spots page, which varies depending on run/pause selection.
function updateTimingDisplayRunPause() { function updateTimingDisplayRunPause() {
// todo run/pause let run = $('#runButton:checked').val();
$("#timing-container").html("Last spot received at " + lastUpdateTime.format('HH:mm') + " UTC."); $("#timing-container").html((run ? "Connected to server. Last update at " : "Paused at ") + lastUpdateTime.format('HH:mm') + " UTC.");
} }
// Build a query string for the API, based on the filters that the user has selected. // Build a query string for the API, based on the filters that the user has selected.
@@ -474,4 +477,19 @@ $(document).ready(function() {
loadOptions(); loadOptions();
// Display intro box // Display intro box
displayIntroBox(); displayIntroBox();
// Set up run/pause toggles
$("#runButton").change(function() {
// Need to start the SSE connection but also do a full re-query to catch up anything that we missed, so we
// might as well just call loadSpots again which will trigger it all
loadSpots();
updateTimingDisplayRunPause();
});
$("#pauseButton").change(function() {
// If we are pausing and have an open SSE connection, stop it
if (evtSource != null) {
evtSource.close();
}
updateTimingDisplayRunPause();
});
}); });