mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-08-06 02:21:42 +00:00
Refactor of caching & data storage part 2 #118
This commit is contained in:
+14
-58
@@ -6,7 +6,7 @@ import tornado
|
||||
from tornado.web import StaticFileHandler
|
||||
|
||||
from core.config import ALLOW_SPOTTING, WEB_SERVER_PORT, API_ONLY_MODE, LOG_WEB_REQUESTS, BASE_URL
|
||||
from core.utils import empty_queue
|
||||
from core.data_store import DATA_STORE
|
||||
from server.handlers.api.addspot import APISpotHandler
|
||||
from server.handlers.api.alerts import APIAlertsHandler, APIAlertsStreamHandler
|
||||
from server.handlers.api.dxstats import APIDxStatsHandler
|
||||
@@ -18,6 +18,7 @@ from server.handlers.api.status import APIStatusHandler
|
||||
from server.handlers.manifesthandler import ManifestHandler
|
||||
from server.handlers.metrics import PrometheusMetricsHandler
|
||||
from server.handlers.pagetemplate import PageTemplateHandler
|
||||
from server.sse_broadcaster import SSEBroadcaster
|
||||
|
||||
_HERE = os.path.dirname(__file__ or "")
|
||||
|
||||
@@ -25,12 +26,12 @@ _HERE = os.path.dirname(__file__ or "")
|
||||
class WebServer:
|
||||
"""Provides the public-facing web server."""
|
||||
|
||||
def __init__(self, data_store):
|
||||
def __init__(self):
|
||||
"""Constructor"""
|
||||
|
||||
self._data_store = data_store
|
||||
self._sse_spot_queues = []
|
||||
self._sse_alert_queues = []
|
||||
self._data_store = DATA_STORE
|
||||
self._spot_broadcaster = SSEBroadcaster()
|
||||
self._alert_broadcaster = SSEBroadcaster()
|
||||
self._port = WEB_SERVER_PORT
|
||||
self._api_only_mode = API_ONLY_MODE
|
||||
self._shutdown_event = asyncio.Event()
|
||||
@@ -42,6 +43,10 @@ class WebServer:
|
||||
"status": "Starting"
|
||||
}
|
||||
|
||||
# Listen for new spots and alerts being added to the cache, so we can notify SSE clients immediately
|
||||
DATA_STORE.spots.add_listener(self._spot_broadcaster.publish)
|
||||
DATA_STORE.alerts.add_listener(self._alert_broadcaster.publish)
|
||||
|
||||
def start(self):
|
||||
"""Start the web server"""
|
||||
|
||||
@@ -64,13 +69,13 @@ class WebServer:
|
||||
(r"/api/v1/spots", APISpotsHandler, {"spots": self._data_store.spots, **handler_opts}),
|
||||
(r"/api/v1/alerts", APIAlertsHandler, {"alerts": self._data_store.alerts, **handler_opts}),
|
||||
(r"/api/v1/spots/stream", APISpotsStreamHandler,
|
||||
{"sse_spot_queues": self._sse_spot_queues, **handler_opts}),
|
||||
{"sse_spot_broadcaster": self._spot_broadcaster, **handler_opts}),
|
||||
(r"/api/v1/alerts/stream", APIAlertsStreamHandler,
|
||||
{"sse_alert_queues": self._sse_alert_queues, **handler_opts}),
|
||||
{"sse_alert_broadcaster": self._alert_broadcaster, **handler_opts}),
|
||||
(r"/api/v1/solar", APISolarConditionsHandler, {"solar_conditions": self._data_store.solar, **handler_opts}),
|
||||
(r"/api/v1/dxstats", APIDxStatsHandler, {"spots": self._data_store.spots, **handler_opts}),
|
||||
(r"/api/v1/options", APIOptionsHandler, {"status_data": self._data_store.status, **handler_opts}),
|
||||
(r"/api/v1/status", APIStatusHandler, {"status_data": self._data_store.status, **handler_opts}),
|
||||
(r"/api/v1/options", APIOptionsHandler, {"status_data": self._data_store.status_data, **handler_opts}),
|
||||
(r"/api/v1/status", APIStatusHandler, {"status_data": self._data_store.status_data, **handler_opts}),
|
||||
(r"/api/v1/lookup/call", APILookupCallHandler, {**handler_opts}),
|
||||
(r"/api/v1/lookup/sigref", APILookupSIGRefHandler, {**handler_opts}),
|
||||
(r"/api/v1/lookup/grid", APILookupGridHandler, {**handler_opts}),
|
||||
@@ -118,55 +123,6 @@ class WebServer:
|
||||
logging.info("You can access your copy of Spothole at " + BASE_URL)
|
||||
await self._shutdown_event.wait()
|
||||
|
||||
def notify_new_spot(self, spot):
|
||||
"""Internal method called when a new spot is added to the system. This is used to ping any SSE clients that are
|
||||
awaiting a server-sent message with new spots."""
|
||||
|
||||
for queue in self._sse_spot_queues:
|
||||
try:
|
||||
queue.put(spot)
|
||||
except:
|
||||
# Cleanup thread was probably deleting the queue, that's fine
|
||||
pass
|
||||
pass
|
||||
|
||||
def notify_new_alert(self, alert):
|
||||
"""Internal method called when a new alert is added to the system. This is used to ping any SSE clients that are
|
||||
awaiting a server-sent message with new spots."""
|
||||
|
||||
for queue in self._sse_alert_queues:
|
||||
try:
|
||||
queue.put(alert)
|
||||
except:
|
||||
# Cleanup thread was probably deleting the queue, that's fine
|
||||
pass
|
||||
pass
|
||||
|
||||
def clean_up_sse_queues(self):
|
||||
"""Clean up any SSE queues that are growing too large; probably their client disconnected and we didn't catch it
|
||||
properly for some reason."""
|
||||
|
||||
for q in self._sse_spot_queues:
|
||||
try:
|
||||
if q.full():
|
||||
logging.warning(
|
||||
"A full SSE spot queue was found, presumably because the client disconnected strangely. It has been removed.")
|
||||
self._sse_spot_queues.remove(q)
|
||||
empty_queue(q)
|
||||
except:
|
||||
# Probably got deleted already on another thread
|
||||
pass
|
||||
for q in self._sse_alert_queues:
|
||||
try:
|
||||
if q.full():
|
||||
logging.warning(
|
||||
"A full SSE alert queue was found, presumably because the client disconnected strangely. It has been removed.")
|
||||
self._sse_alert_queues.remove(q)
|
||||
empty_queue(q)
|
||||
except:
|
||||
# Probably got deleted already on another thread
|
||||
pass
|
||||
pass
|
||||
|
||||
def request_log(handler):
|
||||
"""Custom log function to provide more data about requests when enabled, and to provide the ability to turn off
|
||||
|
||||
Reference in New Issue
Block a user