-
Notifications
You must be signed in to change notification settings - Fork 87
Technical Architecture
This document is constant work-in-progress which serves as raw material for more formal documents that would be published as part of the release lifecycle of Hydra node.
TODO: This should really be ADRs?
At its heart the hydra-node is a reactive loop that:
- Consumes input events sequentially from an internal queue,
- Applies each event to the current state yielding potentially an updated state and a sequence of effects,
- Execute each effect sequentially.
This design is basically identical to React's redux behaviour which in turn is inspired by The Elm Architecture which itself is a simplification of Functional Reactive Programming principles.
The reactive nature of the Hydra node means Request-response paradigm is not a good fit to provide a Client API: Clients input a stream of commands to a node which in turns issues a stream of responses representing the observable outcome of previous commands and interaction with peers in the network.
Therefore, the main API is exposed using the Websocket protocol with inputs and outputs conforming to some textual representation of Command
s and Result
s.
TODO: Rename ClientRequest -> Command and ClientResponse -> Result to be consistent?
This implies client software should be implemented accordingly and most notably cannot rely on any kind of synchronous response to give feedback to potential users or higher-level clients.
COMMENT(SN): These responses might also be sent unfacilitated by a client, e.g. when some other hydra-node initializes a Head and "your" hydra-node sees that init transactions on chain, it would send a response indicating such without an explicit request
- Effects pertaining to the Hydra domain are implemented using the Handle pattern
- System-level effects and general IO are used via the io-sim-classes package which provides typeclasses abstracting over basic IO operations.
- Instantiation to concrete IO is pushed at the outermost layers
The following diagram represents the internal structure of the HydraNode and the interactions between its components.
Legend:
- Grayed boxes represent components which are not developed yet
- Black boxes represent components which are expected to be used as black box, eg. without any knowledge of their inner workings.
- Arrows depict the flow of data (Requests, messages, responses...)
- We represent some components that are not part of the Hydra node proper for legibility's sake
- The HydraNode is a handle to all other components' handles
- This handle is used by the main loop to
processNextEvent
andprocessEffect
- It implements the Head Protocol's state machine as a pure function.
- The protocol is described in two parts in the Hydra paper:
- One part detailing how the Head deals with clients input
- One part detailing how the Head reacts to peers input provided by the network
- Head state c
- Structured logging is implemented using IOHK monitoring framework which provides backend for contra-tracer generic logging
- Each component defines its own tracing messages as a datatype and they are aggregated in the HydraLog datatype. Specialized
Tracer
s can be passed around from the top-level one usingcontramap
to peel one layer of the onion - Configuration of the main tracer is done via the withTracer wrapper function
- Metrics and monitoring are piggy-backed on tracing events:
- Monitoring collection is configured at start of the hydra-node
- Traced events can be interpreted as contributing to some specific metric value without trace producers needing to be aware of how this process happens
- Metrics are exposed using Prometheus format over URI
/metrics
from an HTTP server started on a configurable port.