-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Explain configuration errors #1184
Explain configuration errors #1184
Conversation
Transactions CostsSizes and execution budgets for Hydra protocol transactions. Note that unlisted parameters are currently using
Script summary
Cost of Init Transaction
Cost of Commit TransactionThis is using ada-only outputs for better comparability.
Cost of CollectCom Transaction
Cost of Close Transaction
Cost of Contest Transaction
Cost of Abort TransactionSome variation because of random mixture of still initial and already committed outputs.
Cost of FanOut TransactionInvolves spending head output and burning head tokens. Uses ada-only UTxO for better comparability.
End-To-End Benchmark ResultsThis page is intended to collect the latest end-to-end benchmarks results produced by Hydra's Continuous Integration system from the latest Please take those results with a grain of salt as they are currently produced from very limited cloud VMs and not controlled hardware. Instead of focusing on the absolute results, the emphasis should be on relative results, eg. how the timings for a scenario evolve as the code changes. Generated at 2023-12-01 13:24:08.912387675 UTC 3-nodes ScenarioA rather typical setup, with 3 nodes forming a Hydra head.
Baseline ScenarioThis scenario represents a minimal case and as such is a good baseline against which to assess the overhead introduced by more complex setups. There is a single hydra-node d with a single client submitting single input and single output transactions with a constant UTxO set of 1.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a good small step and I approve merging this right away!
Thank you for putting the run
refactor into a dedicated commit, that made reviewing possible.
I like the fact that we have a function mapping one or the other error to some english text (and not re-use Show
)
I do not like that this would force us to make all exceptions that are explain
ed a ConfigurationException
(or a sub-type of it).
I think a good next step, would be to (following the example in exceptions
):
- create a type class
Explainable
which hasexplain
as the single method - create a type and functions:
data SomeExplainableException = forall e . (Explainable e, Exception e) => SomeExplainableException e
instance Show SomeExplainableException where
show (SomeExplainableException e) = show e
instance Exception SomeExplainableException
explainableExceptionToException :: (Explainable e, Exception e) => e -> SomeException
explainableExceptionToException = toException . SomeExplainableException
explainableExceptionFromException :: (Explainable e, Exception e) => SomeException -> Maybe e
explainableExceptionFromException x = do
SomeExplainableException a <- fromException x
cast a
- define any exception that should be explainable by this top-level catch using these, e.g. the
ConnectException
fromHydra.Chain.Direct
data ConnectException = ConnectException
{ ioException :: IOException
, nodeSocket :: SocketPath
, networkId :: NetworkId
}
deriving stock (Show)
instance Exception ConnectException where
toException = explainableExceptionToException
fromException = explainableExceptionFromException
instance Explainable ConnectException where
explain _ = "Use your imagination"
Alternative: Just define displayException
for all our exceptions and not catch
at all.
@ch1bo Thanks a lot for the review. I think what you propose is sensible and I would like to turn that into a proper ADR. So the toplevel catch would look like:
? I did not know how the |
After all, we said we would stick to boring Haskell :-D |
Thinking again about your proposal, I see one issue: With a "naive" While I agree we don't want to force any coupling between the various exceptions we could throw, I still think it's both simpler and more malleable to let the usage context decide what to do and how to display the exceptions, which implies some form of grouping of exceptions at the toplevel, just like we do for the logging. I don't see this as a problem as long as it's contained within the application part of the node, by which I mean the part which ties together the various components into a coherent executable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
While the I do not understand why you don't like implementations of these explanations to be done at the definition site, after all the part of the application which defines it must know "what this means" and maybe "how it can be avoided". Having a central place where all this knowledge needs to be replicated to again is suboptimal in my opinion. But we have both options with type classes (instances are non-orphans when defined in the class module or the type module). |
That's The part of the application that defines the error does not have the context in which this error will be reported, there is a difference between knowing something is wrong and knowing how to repair or avoid once you know it's wrong. For example, when you detect a connection is wrong the message might be different in the context of a main program where you define a parameter for the connection, an end-user web page where this connection is implicitly defined by your location, or from a field, etc. The part of the code throwing the error does not have in general any knowledge about how this error came to happen, which the use-site might have. In other words, the "meaning" of the error is (in part) context dependent, at least if you want to provide accurate and helpful error messages to users and systems. |
d6a0fda
to
5d085c3
Compare
... and strip down Main to nearly bare minimum.
5d085c3
to
ed04d04
Compare
This PR is a follow-up to a discussion we've had in #1179 about user-friendlier error handling in the hydra-node executable. The idea is simply to use Haskell's exception mechanism to signal various kinds of misconfigurations as structured data and separate
explain
function to provide human-readable error messages. The expected benefit is that this decouples the errors' definition from their representation, making it possible to provide different representations depending on the context, eg. i18n perhaps, or JSON.This PR only unifies errors from the
RunOptions
parsing and the protocol parameters parsing, it's missing the errors stemming from misalignment between given configuration and persisted state, and is a way to foster discussion about our error handling strategy.