This should greatly improve resilience as we no longer have any
tasks within `tokio` that can fail without recovering.
Instead, we periodically ping the actor with a `Sync` message which
updates the local state of all scripts and sends out messages accordingly.
Caused trouble because of route collisions, so the integration was done now.
Required distinguishing Maker and Taker on the cfd level, which comes in handy anyway.
We distinguish by order origin, but still map to a `Role` enum (`Taker` / `Maker`) for readability.
To avoid duplication the `Role` from contract setup was moved into the model and used throughout.
The complexity of the code part was not worth the information we got out of it, so it was simplified.
Should hopefully make it a bit more readable and easier to understand.
All display related decisions are taken in the UI, but on top of the UI's model.
For this purpose we introduce classes for `CfdState` and `Position` so we can add the relevant mapping functions to these classes.
To achieve the mapping from daemon sse even to the `Cfd` / `Order` interface (that now contain classes instead of just primitives) we extend the sse hook to accept a mapping function.
We define this mapping function for `Cfd` and `Order`, because those contain classes, for all others we just use the default mapping.
Actions are dynamically rendered based on the state.
The daemon decides on the action name.
A single post endpoint handles all actions.
The UI maps the actions to icons.
Co-authored-by: Thomas Eizinger <thomas@coblox.tech>
The default path through the function would be to propagate every
error. However, we want to inspect whether it is one very specific
error.
Make this clear in the code structure by having a dedicated `if let`
for the special case but keep using `?` afterwards.
As the profit margin is connected to the CFD feed, refresh the feed whenever
current price or the CFDs change.
Note: this is not exactly a clean revert, as I head to solve some conflicts when
rebasing.
This reverts commit 4b8237c9d6.
After last night's conversation, we decided to return to the first version of
the PR, which will come in a subsequent commit.
`attach_stream` uses `send` under the hood which will process messages
in order. This will guarantee that the `taker_cfd::Actor` processes the
messages in the order they come in on the wire. That allows us to assume
that we will always get the `Accept` message before the first `Setup` message.
This goes towards handling all cfd state transitions in one place, so it becomes easier to reason about it.
Currently, state transitions are scattered over the code of the cfd actor.
This change bundles the actual transition in the cfd itself.
Inserting the new state into the db is still in the responsibility of the caller.
note: the `monitor` import in `taker.rs` should technically not be part of this commit, but was needed because I decided that the `CfdMonitoringEvent` should live in the `monitor` actor. But since that is not part of the `Cfd` in `model` the taker needs to know about the `monitor`.
We currently have cases where the CFD might transition to a same state twice when restarting.
Furthermore, we might transition from `Open` to `Open` upon renewal.
Since it is currently unclear if this restriction is really needed we just print a warning in the logs instead of failing.
The problem was that the restriction on the JOIN clause does not properly filter the complete set, but actually results in wrongly joining the CFDs.
This resulted in two CFDs returned, where one was wrongly assembled (the id of the first one, but the data of the second one).
In a cases where the wrong one is the first one in the list of returned CFDs we would run into an error when inserting a new state, because we would try to alter the state of a wrong CFD.
Fixed by joining on the id and filtering for the order.uuid in the where clause.
Note:
I also tested to add the `and orders.uuid = ?` restriction to the first join clause (in addition to the id clause) which might theoretically be more optimized.
That would work as well, but I found it harder to reason about it. As part of the overall where clause one can see the restriction to exactly this value more clearly.