Skip to main content

sl_map_web/
state.rs

1//! Shared application state passed to every handler.
2
3use std::sync::Arc;
4use std::sync::atomic::AtomicBool;
5
6use axum::extract::FromRef;
7use axum_extra::extract::cookie::Key;
8use sl_glw::GlwEventCache;
9use sl_map_apis::map_tiles::MapTileCache;
10use sl_map_apis::region::RegionNameToGridCoordinatesCache;
11use tokio::sync::Mutex;
12
13use crate::config::Config;
14use crate::fonts::FontDirectory;
15use crate::jobs::JobStore;
16
17/// State shared between all axum handlers.
18///
19/// The two cache types both require `&mut self` to drive lookups, so they
20/// are wrapped in async [`Mutex`]es. As a side effect this serialises
21/// renders to one at a time; that is acceptable for v1 because each render
22/// is also bounded by the upstream rate limiter.
23#[derive(Clone, Debug)]
24#[expect(
25    clippy::module_name_repetitions,
26    reason = "`AppState` is the conventional name for axum shared state and would be ambiguous as just `State`"
27)]
28pub struct AppState {
29    /// the on-disk + in-memory cache of map tiles, shared with the CLI.
30    pub map_tile_cache: Arc<Mutex<MapTileCache>>,
31    /// the region name <-> grid coordinates cache.
32    pub region_cache: Arc<Mutex<RegionNameToGridCoordinatesCache>>,
33    /// the in-memory store of running and recently completed render jobs.
34    pub jobs: Arc<JobStore>,
35    /// the runtime configuration.
36    pub config: Arc<Config>,
37    /// SQLite pool used by the auth subsystem (users, sessions, set-password
38    /// tokens). Cheap to clone.
39    pub db: sqlx::SqlitePool,
40    /// signing key for the session cookie, derived from the configured
41    /// `session_signing_key` at startup. `Key` is internally a buffer of
42    /// bytes; cloning is cheap.
43    pub cookie_key: Key,
44    /// in-process flag raised whenever a code path may have produced stale
45    /// files under `<storage_dir>/renders/` without unlinking them inline
46    /// (e.g. a cascade delete from removing a group). The orphan sweeper
47    /// only scans the filesystem when this flag is set so an idle server
48    /// does no filesystem work.
49    pub library_cleanup_dirty: Arc<AtomicBool>,
50    /// three-tier cache (memory LRU + redb + http-cache-semantics) for
51    /// GLW events. Created at startup from `config.cache_dir` like the
52    /// CLI does. Used by render workers when a render requests a GLW
53    /// overlay via event id or event key.
54    pub glw_event_cache: Arc<Mutex<GlwEventCache>>,
55    /// fonts discovered under `config.fonts_directory` at startup.
56    /// Surfaced through `GET /api/fonts` and used by render workers to
57    /// resolve a client-supplied `font_id` to the font file path.
58    pub fonts: Arc<FontDirectory>,
59}
60
61// `axum_extra::extract::cookie::SignedCookieJar` extracts itself via
62// `FromRef<S, Key>`, so we expose the `cookie_key` through `FromRef`.
63impl FromRef<AppState> for Key {
64    fn from_ref(input: &AppState) -> Self {
65        input.cookie_key.clone()
66    }
67}