STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
state.py
Go to the documentation of this file.
1"""In-memory application state for config and runner."""
2
3import threading
4from typing import Optional, Tuple
5from engine.pipeline.config_schemas import PintleEngineConfig
6from engine.core.runner import PintleEngineRunner
7
8
9class AppState:
10 """Holds the current config and runner instance.
11
12 The two are one pair: the runner is built from the config. Solves run in the thread pool
13 (``backend.session.run_compute``) while the config endpoints replace the pair, so a solve
14 takes ``snapshot()`` once and uses only that, and ``set_config`` swaps both at once.
15 """
16
17 def __init__(self):
18 self.config: Optional[PintleEngineConfig] = None
19 self.runner: Optional[PintleEngineRunner] = None
20 self.config_path: Optional[str] = None
21 self._pair_lock = threading.Lock()
22
23 def set_config(self, config: PintleEngineConfig, config_path: Optional[str] = None) -> None:
24 """Set config and create a new runner instance.
25
26 The runner is built first -- seconds, for a propellant whose CEA cache has to load --
27 and the pair swapped together after, so nothing reads the new config beside the old
28 runner while it builds. A runner that fails to build leaves the old pair in place.
29 """
30 runner = PintleEngineRunner(config)
31 with self._pair_lock:
32 self.config = config
33 self.runner = runner
34 if config_path is not None:
35 self.config_path = config_path
36
37 def snapshot(self) -> Tuple[Optional[PintleEngineConfig], Optional[PintleEngineRunner]]:
38 """The config and the runner built from it, read together.
39
40 A solve takes this once. Reading ``self.config`` again after the solve would pick up a
41 config written while it ran, and report one design's numbers against another's.
42 """
43 with self._pair_lock:
44 return self.config, self.runner
45
46 def has_config(self) -> bool:
47 """Check if a config is loaded."""
48 return self.config is not None and self.runner is not None
49
50
51# There is intentionally no module-level singleton. Live state is per-user:
52# each request resolves its own AppState via backend.session.get_session, so two
53# users connected at once never share one config/runner. See backend/session.py.
Tuple[Optional[PintleEngineConfig], Optional[PintleEngineRunner]] snapshot(self)
Definition state.py:37
None set_config(self, PintleEngineConfig config, Optional[str] config_path=None)
Definition state.py:23
Optional[PintleEngineRunner] runner
Definition state.py:19
Optional[str] config_path
Definition state.py:20
bool has_config(self)
Definition state.py:46
Optional[PintleEngineConfig] config
Definition state.py:18