Integrated Variant¶
The optional webatm_integrated package used by the
integrated build. It is wired into the core app
only when WEBATM_INTEGRATED=1.
webatm_integrated¶
webatm_integrated ¶
Provide the WebATM integrated extensions.
Shipped ONLY in the webatm-integrated build variant. Adds BlueSky server
lifecycle control (start/stop/restart/kill), live, in-order log streaming of the
bluesky --headless process tree to the web UI, and -- because BlueSky runs in
this same container -- pre-wires WebATM's file management directly to BlueSky's
own scenario / plugins / output directories (no manual base-path step).
The core webatm package never imports this package. It is wired in through a
single env-guarded hook in WebATM.app.create_app that calls register
only when WEBATM_INTEGRATED=1 and this package is installed.
LogStreamer ¶
Buffer process output and broadcast it as ordered, batched events.
Initialize the streamer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
socketio
|
SocketIO
|
Instance used to emit batches. |
required |
max_history
|
int
|
Maximum lines retained for history replay. |
2000
|
batch_ms
|
int
|
Delay in milliseconds used to coalesce a batch. |
100
|
batch_max
|
int
|
Maximum lines per emitted batch chunk. |
200
|
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
feed_line ¶
Ingest one output line, assign its order, and schedule a flush.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
line
|
str
|
The process output line to broadcast. |
required |
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
history ¶
Return a snapshot of buffered lines for late-joining clients.
Returns:
| Type | Description |
|---|---|
list[dict]
|
Buffered items with |
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
on_process_exit ¶
Emit an end-of-stream marker when the server process exits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
return_code
|
int
|
Exit code of the BlueSky server process. |
required |
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
BlueSkyProcessManager ¶
BlueSkyProcessManager(
on_line: Callable[[str], None] | None = None,
on_exit: Callable[[int], None] | None = None,
spawn: Callable | None = None,
cmd: list[str] | None = None,
)
Thread-safe lifecycle manager for the bluesky --headless process tree.
Tracks only the parent process; signals (stop/kill) address the whole process group so node children are reaped together with the server.
Initialize the process manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_line
|
Callable[[str], None] | None
|
Callback invoked with each output line of the process tree (newline stripped). |
None
|
on_exit
|
Callable[[int], None] | None
|
Callback invoked with the return code when the server process exits. |
None
|
spawn
|
Callable | None
|
Spawn primitive for the reader task (e.g.
|
None
|
cmd
|
list[str] | None
|
Command to launch; defaults to
|
None
|
Source code in WebATM-integrated/webatm_integrated/process_manager.py
start ¶
Spawn the headless server (in its own process group) and a reader.
The process is started in a new session with merged, line-buffered
stdout/stderr so the reader receives one ordered stream for the
server and all node children. A no-op if the server is already
running. If a concurrent :meth:stop is mid-shutdown, waits for it
to finish and then starts a fresh server instead of reporting the
doomed process as "already running".
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
stop ¶
Signal the whole process group, escalating to SIGKILL if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sig
|
int
|
Signal sent to the process group first. |
SIGTERM
|
escalate_after
|
float
|
Seconds to wait for exit before force-killing the group with SIGKILL. |
5.0
|
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
kill ¶
Force-kill the whole process group immediately (no graceful wait).
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
restart ¶
Stop the current tree (if any) and start a fresh one.
Returns:
| Type | Description |
|---|---|
dict
|
The |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
status ¶
Report whether the server is running, with its pid and state.
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
register ¶
Wire the integrated features into an existing WebATM app.
Called by WebATM.app.create_app when WEBATM_INTEGRATED=1. Points the
file-management routes at BlueSky's fixed working directory, creates the
process manager and log streamer (stashed on app as
bluesky_process_manager / bluesky_log_streamer), registers the
integrated REST routes and Socket.IO handlers, and arranges for the whole
BlueSky process group to be reaped when the worker exits. On the first boot
only (guarded by claim_first_boot(), so a replaced gunicorn worker never
resurrects a manually-stopped server) it also schedules the background
auto-start of the bundled BlueSky server; disable that with
WEBATM_AUTO_START=0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Flask
|
Flask application instance. |
required |
socketio
|
SocketIO
|
Flask-SocketIO instance
( |
required |
session_manager
|
SessionManager
|
Core session manager (accepted for forward-compat; currently unused). |
None
|
bluesky_proxy
|
BlueSkyProxy
|
Core proxy, used for the first-boot auto-connect. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The created |
Source code in WebATM-integrated/webatm_integrated/__init__.py
webatm_integrated.auto_start¶
webatm_integrated.auto_start ¶
Auto-start the bundled BlueSky server and connect the proxy on first boot.
Shipped ONLY in the webatm-integrated build. In this variant BlueSky runs
inside the same container as the WebATM backend, so there is no reason to make
the user open Settings and click Start/Connect before anything works: on
start-up we spawn the bluesky --headless process tree and, once its
command/data ports accept connections, connect the WebATM proxy to it. The user
then lands on a live, already-connected map.
This mirrors -- server-side and automatically -- the exact connect sequence the
manual /api/server/config route performs (start_client then
register_subscribers; subscribers can only attach once the client exists).
Opt out with WEBATM_AUTO_START=0 (e.g. for tests, or deployments that want
the manual Start button to drive the lifecycle). The core webatm package
never imports this module; it is reached only via webatm_integrated.register
(env-guarded on WEBATM_INTEGRATED=1).
auto_start_enabled ¶
Report whether to auto-start BlueSky and auto-connect on boot.
On by default; set WEBATM_AUTO_START=0 to disable.
Returns:
| Type | Description |
|---|---|
bool
|
True unless the |
Source code in WebATM-integrated/webatm_integrated/auto_start.py
claim_first_boot ¶
Atomically claim the one-shot auto-start for this boot.
Creates the marker file with O_CREAT | O_EXCL so only the first caller
per boot wins; every later caller (e.g. a replaced gunicorn worker re-running
register()) stands down, and auto-start never fights the manual
Start/Stop controls. The default marker lives on tmpfs (/dev/shm) so it
survives worker replacement but clears on a fresh container start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
marker_path
|
str | None
|
Marker file location. Defaults to the
|
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True for the first caller to create the marker file, False
thereafter. If the marker cannot be created at all (e.g. no
|
Source code in WebATM-integrated/webatm_integrated/auto_start.py
schedule_auto_start ¶
Run the auto-start sequence on a background task.
Backgrounded so register() (which runs during app creation) returns
immediately: waiting for BlueSky's ports can take several seconds on a cold
start, and we must not block the worker from beginning to serve requests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
socketio
|
SocketIO
|
Socket.IO instance whose
|
required |
manager
|
BlueSkyProcessManager
|
Process manager used to start the BlueSky server. |
required |
bluesky_proxy
|
BlueSkyProxy | None
|
Core proxy to connect once BlueSky is ready, or None to skip the auto-connect. |
required |
Source code in WebATM-integrated/webatm_integrated/auto_start.py
connect_proxy_when_ready ¶
connect_proxy_when_ready(
bluesky_proxy,
*,
host: str | None = None,
ready_timeout: float = 60.0,
poll_interval: float = 0.5,
is_port_listening: Callable[..., bool] | None = None,
register_subscribers: Callable[[], None] | None = None,
sleep: Callable[[float], None] | None = None,
) -> bool
Wait for BlueSky to accept connections, then connect the WebATM proxy.
Polls BlueSky's command/data ports until one is listening (or the timeout
elapses), then performs the same connect sequence as the manual route:
start_client followed by register_subscribers (subscribers attach to
the client created by start_client).
The port probe, subscriber registration and sleep are injectable so this can be unit-tested without a real BlueSky server or wall-clock delays.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bluesky_proxy
|
BlueSkyProxy
|
Core proxy to connect. |
required |
host
|
str | None
|
BlueSky server host. Defaults to the proxy's
|
None
|
ready_timeout
|
float
|
Maximum seconds to wait for a BlueSky port to start listening. |
60.0
|
poll_interval
|
float
|
Seconds to sleep between port probes. |
0.5
|
is_port_listening
|
Callable | None
|
Port probe taking
|
None
|
register_subscribers
|
Callable | None
|
Subscriber-registration hook.
Defaults to |
None
|
sleep
|
Callable | None
|
Sleep function. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if the proxy connect succeeded, False if BlueSky never came up within the timeout or the connect attempt raised. |
Source code in WebATM-integrated/webatm_integrated/auto_start.py
webatm_integrated.process_manager¶
webatm_integrated.process_manager ¶
BlueSky headless server process manager.
Owns the lifecycle of the bluesky --headless process tree: the headless
server plus every node child process it spawns. On POSIX, BlueSky spawns node
children as ordinary subprocesses that inherit the parent's stdout/stderr and
live in the parent's process group, so:
- a single merged pipe on the parent captures the server and all node-child output, already interleaved in order; and
- launching the parent in its own session (
start_new_session=True) lets us reap the entire tree with oneos.killpg.
BlueSkyProcessManager ¶
BlueSkyProcessManager(
on_line: Callable[[str], None] | None = None,
on_exit: Callable[[int], None] | None = None,
spawn: Callable | None = None,
cmd: list[str] | None = None,
)
Thread-safe lifecycle manager for the bluesky --headless process tree.
Tracks only the parent process; signals (stop/kill) address the whole process group so node children are reaped together with the server.
Initialize the process manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_line
|
Callable[[str], None] | None
|
Callback invoked with each output line of the process tree (newline stripped). |
None
|
on_exit
|
Callable[[int], None] | None
|
Callback invoked with the return code when the server process exits. |
None
|
spawn
|
Callable | None
|
Spawn primitive for the reader task (e.g.
|
None
|
cmd
|
list[str] | None
|
Command to launch; defaults to
|
None
|
Source code in WebATM-integrated/webatm_integrated/process_manager.py
start ¶
Spawn the headless server (in its own process group) and a reader.
The process is started in a new session with merged, line-buffered
stdout/stderr so the reader receives one ordered stream for the
server and all node children. A no-op if the server is already
running. If a concurrent :meth:stop is mid-shutdown, waits for it
to finish and then starts a fresh server instead of reporting the
doomed process as "already running".
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
stop ¶
Signal the whole process group, escalating to SIGKILL if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sig
|
int
|
Signal sent to the process group first. |
SIGTERM
|
escalate_after
|
float
|
Seconds to wait for exit before force-killing the group with SIGKILL. |
5.0
|
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
kill ¶
Force-kill the whole process group immediately (no graceful wait).
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
restart ¶
Stop the current tree (if any) and start a fresh one.
Returns:
| Type | Description |
|---|---|
dict
|
The |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
status ¶
Report whether the server is running, with its pid and state.
Returns:
| Type | Description |
|---|---|
dict
|
Result with |
Source code in WebATM-integrated/webatm_integrated/process_manager.py
webatm_integrated.log_streamer¶
webatm_integrated.log_streamer ¶
Live, in-order log streaming of the BlueSky process tree to web clients.
A single server-wide stream (one subprocess) is broadcast to all connected
browsers over the server_log Socket.IO event. Ordering is guaranteed by a
monotonic sequence number assigned under a lock at ingest, before any async
hop. Bursts (for example, creating many nodes at once) are coalesced into
batches so a flood of lines cannot overwhelm Socket.IO.
LogStreamer ¶
Buffer process output and broadcast it as ordered, batched events.
Initialize the streamer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
socketio
|
SocketIO
|
Instance used to emit batches. |
required |
max_history
|
int
|
Maximum lines retained for history replay. |
2000
|
batch_ms
|
int
|
Delay in milliseconds used to coalesce a batch. |
100
|
batch_max
|
int
|
Maximum lines per emitted batch chunk. |
200
|
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
feed_line ¶
Ingest one output line, assign its order, and schedule a flush.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
line
|
str
|
The process output line to broadcast. |
required |
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
history ¶
Return a snapshot of buffered lines for late-joining clients.
Returns:
| Type | Description |
|---|---|
list[dict]
|
Buffered items with |
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
on_process_exit ¶
Emit an end-of-stream marker when the server process exits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
return_code
|
int
|
Exit code of the BlueSky server process. |
required |
Source code in WebATM-integrated/webatm_integrated/log_streamer.py
webatm_integrated.bluesky_paths¶
webatm_integrated.bluesky_paths ¶
BlueSky file-management path wiring for the integrated build.
In the integrated variant BlueSky runs inside the same container as the WebATM
backend, so its scenario / plugins / output directories live on the same
filesystem and at a fixed, known location -- there is nothing for a user to
configure. This module resolves that location and points WebATM's existing
file-management routes (/api/bluesky/...) straight at it, replacing the
manual "configure base path" step the standalone build relies on.
BlueSky, installed as a pip package (which is exactly how the integrated image
ships it), keeps its working directory at ~/bluesky and maintains
scenario, plugins and output subdirectories under it (see BlueSky's
pathfinder). Pointing the file manager at that same working directory means
uploads and browsing land precisely where the running server reads them, with no
chance of the two disagreeing.
The core webatm package never imports this module; it is reached only via
webatm_integrated.register (env-guarded on WEBATM_INTEGRATED=1).
resolve_bluesky_workdir ¶
Return BlueSky's working directory (where scenario/plugins/output live).
For a pip-package install -- the only way the integrated build ships BlueSky
-- BlueSky uses ~/bluesky as its working directory. We deliberately
mirror that exact rule (rather than expose a separate, overridable setting)
so WebATM and the BlueSky server can never point at different directories.
Returns:
| Type | Description |
|---|---|
Path
|
BlueSky's working directory ( |
Source code in WebATM-integrated/webatm_integrated/bluesky_paths.py
configure_file_management ¶
Pre-configure WebATM's file-management routes for the integrated build.
Sets app.bluesky_base_path -- the very same attribute the standalone
build's /api/bluesky/configure-base-path route sets -- so every existing
file route (filestatus, upload, browse, list, delete, output) keeps working
unchanged, just pre-wired to BlueSky's working directory. The managed
subdirectories are best-effort created so the UI can browse and upload even
before the BlueSky server's first start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Flask
|
Flask application instance. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The configured base path (BlueSky's working directory). |
Source code in WebATM-integrated/webatm_integrated/bluesky_paths.py
webatm_integrated.routes¶
webatm_integrated.routes ¶
REST control routes for the integrated BlueSky server.
Namespaced under /api/integrated/ so they cannot collide with core routes
and are simply absent from the default build.
register_integrated_routes ¶
Register server lifecycle-control routes on the Flask app.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Flask
|
Flask application instance. |
required |
manager
|
BlueSkyProcessManager
|
Controls the bundled server. |
required |
Source code in WebATM-integrated/webatm_integrated/routes.py
webatm_integrated.socket_handlers¶
webatm_integrated.socket_handlers ¶
Socket.IO handlers for the integrated build.
Provides live-log history replay for late-joining clients. The lifecycle
actions themselves are REST-only (see :mod:.routes).
register_integrated_socket_handlers ¶
Register the integrated build's Socket.IO event handlers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
socketio
|
SocketIO
|
The Flask-SocketIO instance. |
required |
streamer
|
LogStreamer
|
Holds the server-log history. |
required |