Service Mapping Note¶
Purpose¶
This note documents the current service boundaries, their implementation status, and where the client/backend split is clean vs. where gaps remain.
BackendClient¶
Status¶
Implemented and stable.
Contract¶
Synchronous REST client; all methods block until the HTTP response arrives
Called exclusively from
QtConcurrent::runworker threadsOne instance per async operation (no shared state between concurrent calls)
Covered operations (by tag)¶
Tag |
Methods |
|---|---|
meta |
|
files |
|
datasets |
|
catalogue |
|
vbt |
|
cube |
|
products |
|
tasks |
|
image |
|
cosmology |
|
hips |
|
resolve |
|
samp |
|
spectral |
|
Token resolution¶
Explicit
setToken()/Settings~/.visivo_tokenwritten by the backend at startup
Session management¶
openDataset() stores session_id; echoed as X-Visivo-Session in all subsequent calls for that dataset. openCatalogue() and openVbt() return their own session IDs; viewers call client.setSessionId() accordingly.
Pool-sharing contract (server-side)¶
The backend’s single ProcessPoolExecutor is shared across all endpoints, but its slots are reserved between interactive and heavy tiers so a long compute never starves UI-driven calls:
Interactive helpers (
_run,_run_with_limit): preview / slice / subvolume / probe / noise / image.Heavy helpers (
_run_heavy,_run_heavy_with_limit): moment / isosurface / pv / spectral linewidth / baseline / stack — gated by a globalasyncio.Semaphoreof sizemax(1, VISIVO_WORKERS - 1).
This is transparent to BackendClient: it just makes synchronous HTTP
calls; the throttle lives entirely on the FastAPI side. See
docs/async-patterns.md for the full classification table.
DatasetOpenService¶
Status¶
Local implementation, stable.
Contract¶
DatasetOpenRequest { filepath }DatasetOpenInfo— dataset classification (image vs. cube, dimensions)DatasetOpenService::inspect(const DatasetOpenRequest &)
Current local implementation¶
visivo_shared_core; no Qt::Widgets, no VTKInput: local desktop FITS file path
Uses
AstroUtilsto classify and inspect the file
Future remote mapping¶
Replace
filepathwith a backenddatasetIdor remote resource referenceReturn the same
DatasetOpenInfoshape; the GUI must not depend on the inspection being localNatural bridge: call
BackendClient::openDataset()and map the response intoDatasetOpenInfo
Gap before clean split¶
DatasetOpenRequeststill carries a local file path; no dataset-reference abstraction exists yet
ImageLayerImportService¶
Status¶
Local implementation, stable. Remote layer path now also uses loadImageLayer directly.
Contract¶
ImageLayerImportRequest { baseDatasetPath, layerFilepath }ImageLayerImportResultImageLayerImportService::inspect(const ImageLayerImportRequest &)
Current local implementation¶
visivo_shared_coreValidates WCS overlap and pixel-type compatibility between base dataset and candidate layer
Uses
AstroUtilson local FITS files
Remote layer path (current)¶
“Add New FITS File” in vtkWindowImage no longer goes through ImageLayerImportService. It opens a RemoteFileBrowserDialog, gets a backend-side path, and calls addLayerImage(path) directly. The layer is then loaded by loadImageLayer() / AstroUtils / libwcs — the same pipeline used by the existing “Add New Layer” action and VLKB layers.
ImageLayerImportService is therefore used only for the legacy local-file path; all new remote/VLKB layer loading bypasses it.
Future remote mapping¶
Replace path-based request with dataset/layer reference identifiers
Validation result shape stays the same
Backend equivalent: validate via dataset metadata already known to the server
Gap before clean split¶
Request still carries two local file paths; no stable reference identity model
MomentProcessingService¶
Status¶
Backend-authoritative facade, stable.
Contract¶
MomentRequest— carriesdatasetId, moment order, channel range, RMSMomentResult— carries image payload, scientific metadata, WCS statusMomentProcessingService::computeMoment(const MomentRequest &)
Current implementation¶
visivo_shared_vtk; wrapsBackendClient::requestMoment()orwaitForTaskCompletion()Authoritative computation always runs on the backend
Result is a portable image payload + metadata; the client renders it locally
Task-based path¶
For long-running moments, the client uses createMomentTask() + waitForTaskCompletion() via BackendClient. RemoteMomentWindow uses this path. vtkWindowCube uses the synchronous requestMoment() path.
Gap before clean split¶
Desktop-local FITS files must be manually opened on the backend first (via
DataHub/RemoteFileBrowserDialog) before moment computation is possibleNo automated upload/staging pipeline for local files; this remains a manual step
Tabular query / pagination¶
Status¶
Implemented and stable.
Pagination state (per viewer)¶
Field |
Default |
Reset on |
|---|---|---|
|
50 000 |
never |
|
0 |
|
|
-1 |
|
|
false |
after watcher fires |
Filters are re-applied verbatim on each page (same filters[] vector, different offset).
Cosmology distance service¶
Status¶
Implemented and stable.
Contract¶
Single:
POST /v1/cosmology/distance— one redshift → distance_MpcBatch:
POST /v1/cosmology/distance/batch—redshifts[]+model→distances_Mpc[]Client:
BackendClient::requestCosmologyDistanceBatch(redshifts, model)Result:
BackendCosmologyBatchResult { valid, error, model, distancesMpc[] }
Client-side integration¶
vtkWindowCatalogue3Duses the batch endpoint for Planck15/13/WMAP9 models (async viam_cosmologyWatcher)Planck18 uses the local
Catalogue3DParser::detail::comovingDistanceMpc()integration; no network callDistances are stored as per-entry override (
Catalogue3DEntry::distanceMpc);entryDistanceMpc()applies the priority chain transparently
HiPS service¶
Status¶
Implemented and stable.
Contract¶
openHiPS(url)→BackendHiPSSurveyInfoTile fetch:
requestHiPSAllsky(),requestHiPSTile()View-aware tile set:
requestHiPSTilesForView()Catalogue overlay:
requestHiPSCatalogueOverlay()Name resolution:
resolveTarget()→BackendTargetResolveResult
Client-side integration¶
HiPSWindow / HiPSViewportWidget manage the tile cache and compositing entirely client-side. The backend is responsible only for computing which tiles are needed and serving the tile bytes.
Auth services¶
Backend token (simple bearer)¶
Managed by BackendClient. Token is read from ~/.visivo_token or set explicitly from SettingsDialog. No service boundary gap — token handling is complete.
VLKB OIDC¶
Managed by AuthWrapper + OIDCAuthorizationCodeFlow. Flow: browser-based PKCE → localhost redirect → HttpServerReplyHandler. Custom visivo:// scheme handled by VisIVOUrlSchemeHandler.
Gap: tokens are in-process only; no keychain integration.
Diagnostics¶
Status¶
Implemented and stable.
Contract¶
DiagnosticsManager::instance()->publish(
level, category, source, message,
datasetId, sessionId, operationTag
);
All backend-calling code publishes structured entries before and after operations. DiagnosticsWindow::showSingleton() exposes a process-wide window, reachable from:
View → Diagnostics in
MainWindowView → Diagnostics in child windows (
vtkWindowCube,vtkWindowImage)Command Palette → “Open Diagnostics Window” (⌘K from any window)
No external sink (file, remote log collector) is implemented yet.
Summary¶
Service |
Local impl |
Remote impl |
Gap |
|---|---|---|---|
|
✓ (process mgmt) |
— |
none |
|
✓ (startup UX) |
— |
none |
|
✓ |
— |
local path; no dataset-ref model |
|
✓ (legacy local) |
✓ (remote browse → loadImageLayer) |
service not used for remote path |
|
— |
✓ (backend-auth) |
no local staging pipeline |
|
— |
✓ |
none |
Tabular query + pagination |
— |
✓ |
none |
Cosmology distance |
local (Planck18) |
✓ (batch) |
none |
HiPS tiles |
— |
✓ |
none |
Auth (bearer token) |
✓ |
— |
none |
Auth (OIDC VLKB) |
✓ |
— |
no keychain |
Diagnostics (in-process) |
✓ |
— |
no external sink |
Loading placeholder |
✓ (all 4 viewers) |
— |
none |