Skip to content

Commit e9116ba

Browse files
committed
Rewrite ADR29 to be about EventSource/EventSink
1 parent eeb93d4 commit e9116ba

File tree

1 file changed

+49
-17
lines changed

1 file changed

+49
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
slug: 29
33
title: |
4-
29. EventServer abstraction for event persistence
5-
authors: [@cardenaso11, @quantumplation]
4+
29. EventSource & EventSink abstractions
5+
authors: [@cardenaso11, @quantumplation, @ch1bo]
66
tags: []
77
---
88

@@ -11,30 +11,62 @@ Draft
1111

1212
## Context
1313

14-
The Hydra node represents a significant engineering asset, providing layer 1 monitoring, peer to peer consensus, durable persistence, and an isomorphic Cardano ledger. Because of this, it is being eyed as a key building block not just in Hydra based applications, but other protocols as well.
14+
* The Hydra node represents a significant engineering asset, providing layer 1 monitoring, peer to peer consensus, durable persistence, and an isomorphic Cardano ledger. Because of this, it is being eyed as a key building block not just in Hydra based applications, but other protocols as well.
1515

16-
One remaining difficulty in integrating Hydra into a fully productionalized software stack is the persistence model. Currently, the Hydra node achieves durability by writing a sequence of "StateChanged" events to disk. If a node is interrupted, upon restarting, it can replay just these events, ignoring their corresponding effects, to recover the same internal state it had when it was interrupted. However, downstream consumers don't have the same luxury.
16+
* Currently the `hydra-node` uses a very basic persistence mechanism for it's internal `HeadState`, that is saving `StateChanged` events to file on disk and reading them back to load and re-aggregate the `HeadState` upon startup.
17+
- Some production setups would benefit from storing these events to a service like Amazon Kinesis data stream instead of local files.
1718

18-
We propose generalizing the persistence mechanism to open the door to a plugin based approach to extending the Hydra node.
19+
* The `hydra-node` websocket-based API is the only available event stream right now and might not fit all purposes.
20+
- See also ADR [3](/adr/3) and [25](/adr/25)
21+
- Internally, this is realized as a single `Server` handle which can `sendOutput :: ServerOutput tx -> m ()`
22+
- These `ServerOutput`s closely relate to `StateChanged` events and `ClientEffect`s are yielded by the logic layer often together with the `StateChanged`. For example:
23+
```hs
24+
onInitialChainAbortTx newChainState committed headId =
25+
StateChanged HeadAborted{chainState = newChainState}
26+
<> Effects [ClientEffect $ ServerOutput.HeadIsAborted{headId, utxo = fold committed}]
27+
```
28+
29+
* Users of `hydra-node` are interested to add alternative implementations for storing, loading and consuming events of the Hydra protocol.
1930

2031
# Decision
2132

22-
We propose adding a "persistence combinator", which can combine one or more "persistenceIncremental" instances.
33+
* We create two new interfaces in the `hydra-node` architecture:
34+
35+
- ```data EventSource e m = EventSource { getEvents :: m [e] }```
36+
- ```data EventSink e m = EventSink { putEvent :: e -> m () }```
37+
38+
* We realize our current `PersistenceIncremental` used for persisting `StateChanged` events is both an `EventSource` and an `EventSink`
2339

24-
When appending to the combinator, it will forward the append to each persistence mechanism.
40+
* We drop the `persistence` from the main handle `HydraNode tx m`, add **one** `EventSource` and allow **many** `EventSinks`
2541

26-
As the node starts up, as part of recovering the node state, it will also ensure "at least once" semantics for each persistence mechanism. It will maintain a notion of a "primary" instance, from which events are loaded, and "secondary instances", which are given the opportunity to re-observe each event.
42+
```hs
43+
data HydraNode tx m = HydraNode
44+
{ -- ...
45+
, eventSource :: EventSource (StateChanged tx) m
46+
, eventSinks :: [EventSink (StateChanged tx) m]
47+
}
48+
```
2749

28-
Each persistence mechanism will be responsible for it's own durability; for example, it may maintain its own checkpoint, and only re-broadcast the event if its after the checkpoint.
50+
* The `stepHydraNode` main loop does call `putEvent` on all `eventSinks` in sequence.
51+
52+
- TBD: transaction semantics? what happens if one fails?
2953

30-
The exact implementation details of the above are left unspecified, to allow some flexibility and experimentation on the exact mechanism to realize these goals.
54+
* The default `hydra-node` main loop does use the file-based `EventSource` and a single file-based `EventSink` (using the same file).
55+
56+
* TBD: As the node starts up, when loading events from the `EventSource`, it will also ensure "at least once" semantics for each `EventSink`.
57+
58+
* We realize that the `EventSource` and `EventSink` handles, as well as their aggregation in `HydraNode` are used as an API by forks of the `hydra-node` and try to minimize changes to it.
3159

3260
## Consequences
3361

34-
Here are the consequences we forsee from this change:
35-
- The default operation of the node remains unchanged
36-
- Projects forking the hydra node have a natively supported mechanism to extend node persistence
37-
- These extensions can preserve robust "at least once" semantics for each hydra event
38-
- Sundae Labs will build a "Save transaction batches to S3" proof of concept extension
39-
- Sundae Labs will build a "Scrolls source" proof of concept integration
40-
- This may also enable a future ADRs for dynamically loaded plugins without having to fork the Hydra node at all
62+
* TODO: Naming conflicts / overloaded terms -> should resolve by calling something not "Event"?
63+
64+
* The default operation of the `hyda-node` remains unchanged
65+
* The API `Server` can be modelled and refactored as an `EventSink`
66+
- TBD: Do `Network` and `Chain` parts qualify as `EventSink`s as well or shall those be triggered by `Effect`s still?
67+
* Projects forking the hydra node have a natively supported mechanism to extend node persistence
68+
* These extensions can preserve robust "at least once" semantics for each hydra event
69+
* Sundae Labs can build a "Save transaction batches to S3" proof of concept `EventSink`
70+
* Sundae Labs can build a "Scrolls source" `EventSink`
71+
* Sundae Labs can build a "Amazon Kinesis" `EventSource` and `EventSink`
72+
* Extension points like `EventSource` and `EventSink` could be dynamically loaded as plugins without having to fork `hydra-node` (maybe in a future ADR)

0 commit comments

Comments
 (0)