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"]
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
}
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
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 |