Skip to content

StudioRealtimeGateway

Target

This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.

Bounded context BC-29 Experience Composition
Platform / plane Factory Studio / Experience
Deployment granularity standalone host
Status target · ConnectSoft.Factory.Studio.Realtime
Built from connectsoft-microservice · libraries: connectsoft-extensions-service-model-signal-r, connectsoft-extensions-saas-abstractions, connectsoft-extensions-messaging-model, connectsoft-extensions-observability
Decisions ADR-0014
Traceability FR-10 FUX-04 FUX-07 NFR-01 NFR-02 XL-06

Purpose and responsibilities

StudioRealtimeGateway is why a run page moves without polling. A session subscribes to streams (run timeline, run list, approvals, alerts, notifications, rollout, incident, saved views) after the BFF confirmed it may read the subject; the StreamBridge holds the upstream gRPC streams (DashboardService.Operations.Subscribe per scope, run event streams for open timelines) and the notification events, and fans them out to connections with per-connection buffers. A client resumes from its last sequence on reconnect; a gap beyond the buffer triggers a full refresh of the screen, never a silent skip. It runs on ConnectSoft.Extensions.ServiceModel.SignalR with a Redis backplane across replicas, cohosted with the BFF until connection counts justify its own deployment.

Context and boundaries

flowchart LR
    S["StudioRealtimeGateway"]
    StudioBff["StudioBff"] -->|event| S
    S -->|grpc| StudioBff["StudioBff"]
    S -->|grpc| DashboardService["DashboardService"]
    S -->|grpc| RunControlService["RunControlService"]
Hold "Alt" / "Option" to enable pan & zoom

The gateway never widens scope: a subscription filter can narrow what the session may read, not extend it. Push latency from upstream event to client is a platform objective.

Domain model

RealtimeSubscription — One session's subscription to one stream with its scope filter, the upstream gRPC stream or inbox it is served from, backpressure state and the last sequence delivered. (catalog entry)

Field Type Required Description
subscriptionId guid yes
tenantId string yes
sessionId guid yes
connectionId string yes
kind enum:StreamKind yes
filter json yes run id, project, environment, product
lastSequence long yes
backpressure bool yes
startedAt datetime yes

Invariants:

  • A subscription is created only after the BFF confirmed the session may read the subject; the filter cannot widen the session's scope.
  • On reconnect the client resumes from the last sequence; gaps beyond the buffer trigger a full refresh of the screen, never a silent skip.

Events: — · Tables: — · Repository: RealtimeSubscriptionRepository

erDiagram
    RealtimeSubscription {
        guid subscriptionId PK
        string tenantId
        guid sessionId
        string connectionId
        enum_StreamKind kind
        json filter
        long lastSequence
        bool backpressure
        datetime startedAt
    }
Hold "Alt" / "Option" to enable pan & zoom

Entities and value objects

None modelled

No entities or value objects are modelled for this item yet.

Data model and storage

Store Role Engine / profile Tables
Cache and coordination cache redis / azure-cache —

None modelled

No tables are modelled for this item yet.

APIs

Method Path Operation Scope Side effects Idempotency Gateway Summary
GET /studio/realtime/health RealtimeHealth factory.health.read read natural GW-01 Liveness, readiness, connection count and upstream stream health.
gRPC service Method Streaming Visibility Side effects Summary
Realtime Subscribe server bff read Hub-side subscription negotiation (SignalR transport in front; this is the server contract).

Messages

None modelled

No events are modelled for this item yet.

None modelled

No commands are modelled for this item yet.

Event Producer Handler Purpose
RunProjectionUpdated DashboardService PushRun Run list and timeline updates.
NotificationCreated StudioNotificationService PushNotification New notifications.
SavedViewChanged StudioBff PushViews Shared views refresh.
AlertFired AlertRuleService PushAlert Live alerts for operators.
AlertResolved AlertRuleService PushAlert Alert resolution.

Workers and jobs

Worker Trigger Output events Retry Idempotency key Summary
StreamBridge event — exponential subscriptionId + sequence Holds the upstream gRPC streams (operations projections per scope) and fans them out to subscribed connections with per-connection buffers and backpressure.

Actors and grains

None modelled

No grains are modelled for this item yet.

Sagas and long-running flows

None modelled

No sagas are modelled for this item yet.

sequenceDiagram
    participant UI as Studio client
    participant RT as StudioRealtimeGateway
    participant B as StudioBff
    participant D as DashboardService
    UI->>RT: connect (token), subscribe RunTimeline(runId)
    RT->>B: may this session read runId?
    B-->>RT: yes (scope)
    RT->>D: Operations.Subscribe(scope)
    D-)RT: RunProjectionUpdated (sequence n)
    RT-)UI: push (sequence n)
    Note over UI,RT: reconnect → resume from n, overflow → full refresh
Hold "Alt" / "Option" to enable pan & zoom

Options and configuration

Section Key Type Default Reloadable Secret Summary
Studio:Realtime BufferPerConnection int 500 yes no Messages buffered per connection before a full refresh is requested.
Studio:Realtime Backplane string redis no no SignalR backplane for multiple replicas (Redis in saas-default; Azure SignalR Service optional)

Metrics and observability

Metric Instrument Unit Dimensions Summary
connectsoft.factory.studio.realtime_connections updown {connection} tenant Open connections.
connectsoft.factory.studio.realtime_push_latency histogram ms kind Upstream event to client push.
connectsoft.factory.studio.realtime_refreshes counter {refresh} kind Full refreshes requested after buffer overflow.

Security

Authentication oauth2-jwt
Scopes factory.studio.use (Subscribe under the session's scope.); factory.health.read (Health probes.)
Roles Requester, Reviewer, AssetMaintainer, Operator, WorkspaceAdmin, PlatformAdmin, Observer
Tenant isolation per-request-claim
Data classification internal
Max side-effect class read
Secrets studio-signing (key-vault, rotate 90 d)

Dependencies

Outbound

Target Kind Purpose Failure mode Required
StudioBff grpc Session and permission resolution for subscriptions. fail-fast yes
DashboardService grpc Operations.Subscribe streams per scope. degrade yes
RunControlService grpc Run event streams for open timelines. degrade no

Inbound

Target Kind Purpose Failure mode Required
StudioBff event Saved view changes. — yes

Failure and recovery

Scenario Detection Recovery Data impact RTO (min)
Upstream stream drops stream error reconnect with backoff; clients resume from last sequence or refresh none 1
Replica loses connections hub disconnects clients reconnect through the backplane to another replica none 1

NFR targets

Target Class value (pilot-interactive) Override
latency_p95_ms 2000 —
availability_pct 99.5 —
throughput_rps 50 —
rpo_minutes 15 —
rto_minutes 240 —
cost_class low —

Deployment

Granularity standalone host
Topologies saas-default, hybrid, on-prem
Runtime aks; replicas 2–8
Ports https 8210, grpc 8212, silo 12210, gateway 31210

Current implementation

ConnectSoft.Extensions.ServiceModel.SignalR exists as a library; the DerechHaLev shell uses SignalR for live updates. No Factory hub exists.

Later capabilities

Azure SignalR Service profile; per-tenant connection quotas tied to editions; server-sent-events fallback for the CLI's watch mode.

Decisions and traceability

Family Ids
FR FR-10
FUX FUX-04, FUX-07
NFR NFR-01, NFR-02
XL XL-06