The View Service is the core orchestration layer of the Fabric Smart Client (FSC) that manages the lifecycle of views, contexts, and inter-node communication protocols. It provides a high-level abstraction for executing business logic through views while handling session management, identity resolution, and distributed protocol coordination.
The View Service enables developers to write business logic as "views" - self-contained units of work that can initiate protocols, respond to requests, and communicate with other FSC nodes. The service manages:
- View Lifecycle: Creation, execution, and cleanup of view instances
- Context Management: Isolated execution environments for views with session and identity management
- Protocol Coordination: Initiator/responder patterns for distributed protocols
- Session Management: Multiplexed communication channels between nodes
- Registry: Factory pattern for view instantiation and responder registration
graph TB
Manager[View Manager]
Registry[View Registry]
ContextFactory[Context Factory]
Context[View Context]
Sessions[Session Manager]
P2P[P2P Service]
Manager --> Registry
Manager --> ContextFactory
Manager --> Context
Context --> Sessions
Context --> P2P
subgraph "View Execution"
View[View Instance]
RunView[RunViewNow]
View --> RunView
end
Manager --> View
The Manager is the central orchestrator responsible for:
- Context Lifecycle: Creating, tracking, and disposing view contexts
- View Instantiation: Delegating to the registry to create view instances
- Protocol Initiation: Starting new protocols as an initiator
- Responder Coordination: Creating contexts for incoming protocol requests
- Metrics: Tracking active contexts and view executions
Key Methods:
InitiateView(ctx, view): Starts a new protocol with the given view as initiatorInitiateContext(ctx, view): Creates a context for a view without executing itNewSessionContext(ctx, contextID, session, me, remote): Creates or reuses a context for responding to a remote requestRegisterFactory(id, factory): Registers a factory for creating views by IDRegisterResponder(responder, initiatedBy): Registers a responder view for a given initiator
The Context provides the execution environment for views, implementing the view.Context interface:
Identity & Session Management:
Me(): Returns the local identity bound to this contextIsMe(id): Checks if an identity is local to this nodeSession(): Returns the default session (for responders)GetSession(caller, party): Gets or creates a session to a remote partyGetSessionByID(id, party): Gets a session by explicit ID
Service Access:
GetService(type): Retrieves services (local context-scoped or global)PutService(service): Registers a service in the local context scope
View Execution:
RunView(view, opts...): Executes a view within this contextInitiator(): Returns the initiator view (if this is an initiator context)
Lifecycle:
OnError(callback): Registers cleanup callbacks for error handlingDispose(): Releases all resources (sessions, callbacks)
The ContextFactory creates view contexts with proper initialization:
NewForInitiator(ctx, contextID, id, view): Creates a context for an initiator viewNewForResponder(ctx, contextID, me, session, remote): Creates a context for a responder view
The factory wires together:
- Service provider (global services)
- Session factory (for creating communication sessions)
- Endpoint service (for identity resolution)
- Identity provider (for local identities)
- Tracer (for observability)
The Registry manages view factories and responder mappings:
Factory Registration:
RegisterFactory(id, factory): Maps a view ID to a factoryNewView(id, input): Creates a view instance using the registered factory
Responder Registration:
RegisterResponder(responder, initiatedBy): Maps an initiator to a responder viewRegisterResponderWithIdentity(responder, id, initiatedBy): Maps with a specific identityGetResponder(initiatedBy): Retrieves the responder for an initiatorExistResponderForCaller(caller): Checks if a responder exists for a caller ID
View Identification:
- Uses reflection to generate unique identifiers:
<package>/<type> - Caches identifiers for performance
The Sessions component manages communication sessions within a context:
- Session Caching: Sessions are cached by
(viewID, partyID)tuple - Session Reuse: Existing open sessions are reused when possible
- Session Lifecycle: Tracks session state (open/closed)
- Default Session: Responder contexts have a default session from the initiator
Key Operations:
Put(viewID, party, session): Caches a sessionGet(viewID, party): Retrieves a cached sessionGetFirstOpen(viewID, parties): Finds the first open session from a list of party identitiesReset(): Clears all sessions
sequenceDiagram
participant User
participant Manager
participant ContextFactory
participant Context
participant View
participant Session
participant Remote
User->>Manager: InitiateView(ctx, view)
Manager->>ContextFactory: NewForInitiator(ctx, id, view)
ContextFactory->>Context: Create Context
Context-->>Manager: Context
Manager->>Context: RunView(view)
Context->>View: Call(context)
View->>Context: GetSession(caller, party)
Context->>Session: NewSession(...)
Session-->>Context: Session
View->>Session: Send(message)
Session->>Remote: Network Message
Remote-->>Session: Response
Session-->>View: Receive()
View-->>Context: Result
Context-->>Manager: Result
Manager->>Context: Dispose()
Manager-->>User: Result
Steps:
- Initiation: User calls
Manager.InitiateView(ctx, view) - Context Creation: Manager creates a new context via
ContextFactory.NewForInitiator - Context Registration: Manager registers the context in its internal map
- View Execution: Manager calls
Context.RunView(view)which invokesview.Call(context) - Session Creation: View requests sessions via
context.GetSession(caller, party) - Communication: View sends/receives messages through sessions
- Completion: View returns result
- Cleanup: Manager calls
context.Dispose()and removes context from map
sequenceDiagram
participant Remote
participant P2P
participant Manager
participant Registry
participant ContextFactory
participant Context
participant Responder
Remote->>P2P: Incoming Message
P2P->>Manager: NewSessionContext(ctx, contextID, session, me, remote)
alt Context Exists
Manager->>Context: Reuse Existing
else New Context
Manager->>ContextFactory: NewForResponder(...)
ContextFactory->>Context: Create Context
Manager->>Context: Register
end
P2P->>Registry: ExistResponderForCaller(caller)
Registry-->>P2P: Responder View
P2P->>Context: RunView(responder)
Context->>Responder: Call(context)
Responder->>Context: Session()
Context-->>Responder: Default Session
Responder->>Context: Send/Receive
Responder-->>Context: Result
Context-->>P2P: Complete
alt New Context
P2P->>Manager: DeleteContext(contextID)
end
Steps:
- Message Arrival: P2P service receives an incoming message
- Context Resolution: P2P calls
Manager.NewSessionContextto get or create a context - Responder Lookup: P2P queries
Registry.ExistResponderForCallerto find the responder view - View Execution: P2P runs the responder view in the context
- Session Access: Responder accesses the default session via
context.Session() - Communication: Responder sends/receives messages through the session
- Completion: Responder returns result
- Cleanup: If a new context was created, P2P deletes it
The Context struct is the main implementation of view.Context and ParentContext. It provides:
- Full context functionality
- Session management
- Service provider integration
- Error callback registration
- Cleanup and disposal
The ChildContext wraps a parent context to provide:
- Session Override: Can override the default session
- Initiator Override: Can override the initiator view
- Error Callbacks: Maintains its own list of error callbacks
- Delegation: Delegates most operations to the parent
Use Cases:
- Running a view with a different session
- Temporarily acting as an initiator from a responder context
- Isolating error handling for nested view executions
The WrappedContext wraps a parent context to provide a different context.Context:
- Overrides the Go context while delegating all other operations
- Used for propagating cancellation, deadlines, and trace spans
- Maintains the same view context semantics
- Creation: Sessions are created via
SessionFactory.NewSessionorNewSessionWithID - Caching: Sessions are cached in the context's
Sessionsmanager - Reuse: Existing open sessions are reused when
GetSessionis called - Closure: Sessions are closed when the context is disposed
- Cleanup: Session factory deletes sessions by ID
Sessions are scoped by:
- View ID: The identifier of the calling view
- Party ID: The identity of the remote party
This allows different views to have independent sessions to the same party.
When GetSession(caller, party) is called:
- Check for cached session by
(viewID, party) - If found and open, return it
- If not found, resolve the party identity:
- Try the party identity as-is
- Try resolving via endpoint service
- Try resolving as a label via identity provider
- Create a new session to the resolved identity
- Cache and return the session
The RunViewNow function is the core view execution engine:
func RunViewNow(parent ParentContext, v View, opts ...view.RunViewOption) (any, error)Execution Flow:
- Option Compilation: Parse run options (AsInitiator, AsResponder, SameContext, etc.)
- Context Selection: Use parent context or create a child context based on options
- Tracing: Start a new trace span for the view execution
- Context Creation:
- If
SameContext: Wrap parent with new Go context - If
AsInitiator: Create child context with initiator set - Otherwise: Create child context with optional session override
- If
- Panic Recovery: Wrap execution in defer/recover to handle panics
- View Invocation: Call
view.Call(context)or execute the provided call function - Error Handling: On error, call
context.Cleanup()to invoke error callbacks - Result Return: Return the view's result
AsInitiator(): Run as an initiator (setscontext.Initiator())AsResponder(session): Run as a responder with a specific sessionWithViewCall(func): Execute a function instead ofview.CallSameContext: Reuse the parent context without creating a childWithContext(ctx): Use a specific Go context
Initiate(context, view): Shortcut for initiating a new protocolAsResponder(context, session, func): Temporarily act as a responderAsInitiatorCall(context, initiator, func): Temporarily act as an initiatorRunCall(context, func): Execute a function as a view
Contexts support registering error callbacks via OnError(callback):
- Callbacks are invoked when a view execution fails or panics
- Callbacks are invoked in registration order
- Callbacks are protected by panic recovery
- Useful for resource cleanup (closing files, releasing locks, etc.)
When a view execution fails:
RunViewNowcatches the error or panic- Calls
context.Cleanup()to invoke all error callbacks - Returns the error to the caller
When a context is disposed:
Manager.DeleteContextis called- Calls
context.Dispose()to release resources - Deletes all sessions via
SessionFactory.DeleteSessions - Removes the context from the manager's map
All view executions are wrapped in panic recovery:
- Panics are caught and converted to errors
- Stack traces are logged
- Error callbacks are still invoked
- The error is returned to the caller
The context has access to global services via services.Provider:
- Registered at the application level
- Shared across all contexts
- Retrieved via
context.GetService(type)
Each context has a local ServiceProvider:
- Scoped to the context
- Registered via
context.PutService(service) - Retrieved first before checking global services
- Useful for context-specific dependencies (e.g., web streams)
When GetService(type) is called:
- Check local service provider
- If found, return it
- If not found, check global service provider
- Return error if not found in either
The View Service integrates with the P2P Service for handling incoming messages:
- Message Reception: Listens on the master session for incoming messages
- Responder Lookup: Queries the registry for the appropriate responder view
- Context Creation: Calls
Manager.NewSessionContextto get or create a context - View Execution: Runs the responder view in the context
- Error Handling: Sends error messages back to the initiator on failure
The text sent is the raw error returned by the responder view (err.Error()), forwarded unmodified via Session().SendError(context.WithoutCancel(viewCtx.Context()), ...). The runtime does not inspect or filter it — deciding what information is safe to disclose to a remote, potentially untrusted caller is the responder view's responsibility, not the P2P service's. See the View API for guidance on what responder views should and shouldn't return as errors.
sequenceDiagram
participant Remote
participant Comm
participant P2P
participant Manager
participant Context
participant Responder
Remote->>Comm: ViewPacket
Comm->>P2P: Message
P2P->>Manager: ExistResponderForCaller(caller)
Manager-->>P2P: Responder View
P2P->>Manager: NewSessionContext(...)
Manager-->>P2P: Context (new or existing)
P2P->>Context: RunView(responder)
Context->>Responder: Call(context)
Responder-->>Context: Result
Context-->>P2P: Complete
alt Error
P2P->>Context: Session().SendError(ctx, err)
end
alt New Context
P2P->>Manager: DeleteContext(contextID)
end
- Keep Views Focused: Each view should have a single, well-defined purpose
- Use Sessions Wisely: Cache sessions when possible, but be aware of their scope
- Handle Errors Gracefully: Use
OnErrorcallbacks for cleanup - Avoid Long-Running Operations: Views should complete in a reasonable time
- Use Tracing: Leverage the built-in tracing for observability
- Always Dispose: Ensure contexts are disposed when no longer needed
- Use Child Contexts: For nested view executions or temporary role changes
- Register Services Locally: Use local services for context-specific dependencies
- Avoid Context Leaks: The manager tracks contexts; ensure they're deleted
- Reuse Sessions: Let the context cache and reuse sessions
- Close Explicitly: Call
session.Close()when done (or rely on context disposal) - Handle Session Errors: Sessions can fail; handle errors appropriately
- Understand Scoping: Sessions are scoped by view and party
- Register Cleanup Callbacks: Use
OnErrorfor resource cleanup - Handle Panics: The framework recovers panics, but avoid them when possible
- Log Errors: Use the logger for debugging
- Return Meaningful Errors: Provide context in error messages
The View Service is configured through the FSC configuration file. Key settings include:
- Identity Configuration: Default identity and identity provider settings
- Session Configuration: Session factory and communication layer settings
- Tracing Configuration: OpenTelemetry tracing provider settings
- Metrics Configuration: Prometheus metrics provider settings
See the Configuration Guide for detailed configuration options.
The View Service exports Prometheus metrics:
contexts: Current number of active contexts (gauge)
The View Service integrates with OpenTelemetry for distributed tracing:
- Each view execution creates a new span
- Spans include attributes:
view,initiator_view,success - Spans are linked to parent spans for nested view executions
- Trace context is propagated across network boundaries
The View Service uses structured logging:
- Debug logs for view lifecycle events
- Info logs for important state changes
- Error logs for failures and panics
- Context-aware logging with trace IDs
| Component | File Path |
|---|---|
| View Manager | platform/view/services/view/manager.go |
| View Context | platform/view/services/view/context.go |
| Context Factory | platform/view/services/view/context.go |
| Child Context | platform/view/services/view/child.go |
| View Registry | platform/view/services/view/registry.go |
| Session Manager | platform/view/services/view/sessions.go |
| View Execution | platform/view/services/view/view.go |
| Service Provider | platform/view/services/view/sp.go |
| P2P Service | platform/view/services/view/p2p/service.go |
| Error Definitions | platform/view/services/view/errors.go |
- Communication Service - P2P communication layer
- View SDK - High-level view development guide
- Configuration Guide - FSC configuration reference