Sessions¶
A session is an isolated workspace inside a running Algomancy backend.
It owns its own scenarios, runs, KPI measurements, and uploaded datasets,
and it is the unit of scoping for every persistence operation. Every
deployment — even a single-user workshop — runs with at least one
session active; the SessionManager always auto-creates a default
"main" session when none exists yet.
flowchart LR
SM[SessionManager] --> S1[Session A]
SM --> S2[Session B]
SM --> S3[Session C]
S1 --> DM1[DataManager]
S1 --> SP1[ScenarioProcessor]
S1 --> Sc1[Scenarios + Runs + KPIs]
S2 --> DM2[DataManager]
S2 --> SP2[ScenarioProcessor]
S2 --> Sc2[Scenarios + Runs + KPIs]
Identity and display name¶
Each session has two strings:
Field |
Mutability |
Used for |
|---|---|---|
|
immutable UUID generated at creation time |
URL paths, database FKs, GUI store values |
|
mutable, free-form human label |
dropdowns, page headers, any UI surface |
The split matters because the display_name is the part users actually
want to change — “alice_experiment_v1” might become “alice_experiment_final”
without affecting any URL bookmark, database row, or scenario reference.
Renames go through SessionManager.rename_session(id, new_display_name)
or, over HTTP, PATCH /api/v1/sessions/{id} with body
{"display_name": "..."}.
Persistence backends¶
Sessions live in one of two backends; both expose the same SessionManager API but differ in where the data lands.
Filesystem (default)¶
Each session is a subdirectory of data_path. The directory contains the
session’s datasets (one subdirectory per dataset, plus the saved scenario
state) and a small meta.json:
data/
├── main/
│ ├── meta.json ← {"id": "<uuid>", "display_name": "main"}
│ ├── scenarios.json
│ └── example_data/
│ ├── sku_data.csv
│ └── ...
└── alice_experiment/
├── meta.json
├── scenarios.json
└── ...
The directory name is decided once, when the session is first created
(it’s the slugified display_name), and never changes afterwards.
Renaming a session only updates meta.json. Pre-M14 session directories
without a meta.json are migrated transparently on first scan — the
directory name becomes the initial display_name and a fresh UUID is
written.
Database¶
Sessions are rows of algomancy_sessions:
algomancy_sessions
├── id VARCHAR PK ← UUID
├── display_name VARCHAR NOT NULL
└── created_at TIMESTAMP
The session’s scenarios, runs, and KPI measurements live in
algomancy_scenarios, algomancy_scenario_runs, and
algomancy_kpi_measurements (all keyed by session_id). The session’s
datasets are persisted through one of two paths, chosen per-DataSource
by DatabaseDataManager:
Per-sub-table SQL (default, used by the bundled
DataSourceand any custom subclass that implements theSqlTableLayoutprotocol) — each DataFrame becomes its own table namedds__{session_id}__{dataset_name}__{sub_table}. Data stays externally queryable and is loaded lazily on first access.JSON blob (fallback, used by any other
BaseDataSourcesubclass) — the DataSource is serialised viato_json()into apayloadcolumn on the catalogue.
Either way the row in algomancy_datasets carries the dataset’s id,
name, classification, and creation time. See
Database persistence of custom data sources
for the opt-in protocol.
To choose the database backend pass persistence_backend="database"
and database_url=... to CoreConfig / ApiConfiguration.
Isolation guarantees¶
Within a single backend process, sessions are mutually isolated at the SessionManager layer: a ScenarioManager only sees data + scenarios that belong to its session. A scenario in one session cannot reference a dataset in another; a KPI computation cannot reach across.
The framework does not yet enforce isolation between processes. If you point two backend processes at the same data folder, both will load the same sessions and writes will race. The Frontends page calls this out: prefer one frontend per backend process unless the second one is read-only.
Lifecycle¶
Operation |
SessionManager |
HTTP |
|---|---|---|
Create |
|
|
Copy |
|
|
Rename |
|
|
Delete |
|
|
Resolve display name → id |
|
(use the list response) |
Deleting a session cascades through all of its scenarios, runs, KPI
measurements, and uploaded data — on the database backend the dynamic
ds__{id}__* tables are dropped. Deleting the last remaining session is
never an empty state: a fresh "main" session is auto-created in its
place.
When to create a session¶
Shape |
Approach |
|---|---|
Single-user workshop, one analyst |
Stay on the auto-created |
Multiple analysts sharing one backend |
One session per analyst; switch via the admin page dropdown |
Same analyst, multiple experiments |
One session per experiment; rename freely as the experiment evolves |
Programmatic clients (API) |
Sessions are how you scope HTTP requests; create one per logical workspace |
How the API and GUI scope by session¶
The algomancy-api HTTP service nests all scenario, data, algorithm,
and KPI routes under /api/v1/sessions/{session_id}/.... The session_id
in the URL is a UUID; the URL routing layer also accepts the current
display_name as a soft-compat alias so casual single-tenant
deployments can use human-readable URLs while migrating to UUIDs.
The Dash GUI carries the active session id in a dcc.Store
(ACTIVE_SESSION) so every page renders against the same session. The
session picker on the admin page reads SessionManager.list_sessions()
and shows display_name in the dropdown while storing the id as the
selected value.
When FeatureConfig.show_session_picker=False the picker is hidden —
useful for single-tenant deployments where the user shouldn’t be
switching contexts. Sessions still exist underneath, the UI just doesn’t
expose the controls.
See also: Frontends for how the GUI and API consume the SessionManager, and HTTP API reference for the full session route shape.