Skip to content
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

Implement errors #1769

Closed
3 of 4 tasks
nkrkv opened this issue Apr 23, 2019 · 0 comments · Fixed by #1777
Closed
3 of 4 tasks

Implement errors #1769

nkrkv opened this issue Apr 23, 2019 · 0 comments · Fixed by #1777

Comments

@nkrkv
Copy link
Member

nkrkv commented Apr 23, 2019

Rationale

Currently, errors are signalized with ERR pulses. They require much boilerplate to pass an error further (big any’s with all ERR united) and do not carry any information about the error reason. Also, using pulses for errors makes it hard to express that a value is malformed. We can improve the system by introducing a dedicated concept for errors.

Errors concept

From time to time things go wrong. A sensor can refuse to respond, a server can become unavailable, a list index can fall out of range. Nodes should have a way to signalize that they fail so that other nodes which use their results can recover or show the error to a device user. XOD makes it possible with an error concept.

A node can raise an error to demonstrate that it has failed to evaluate. When the node raises an error all downstream nodes become “infected” and enter the error condition too. They won’t be evaluated as long as the original error is in effect. Their downstream nodes—in their turn—inherit the same error as well. The cascade goes on until the whole downstream subgraph of the original node is considered erroneous.

Errors are neither values nor pulses. They spread via links regardless of the link types and node evaluation policies. Errors are an overlay mechanism.

Any error risen has a code attached. The code loosely describes the error reason. It is a choice between one of the values defined by XOD. With the codes, someone who faces an error can better understand how to deal with it. Examples of the error codes are:

  • E16 (Bad Use) — the node input values are invalid
  • E32 (Hardware Fail) — general hardware communication problem
  • E48 (Network Fail) — network or internet communication failure

In contrast to errors, the error codes are values of a type Errcode which exist specifically to handle errors.

The error mechanism in XOD is something between exceptions in C++ or Python, and Either monads in Haskell or other functional programming languages. Unlike the “elder brothers” XOD does not carries custom error objects around: to keep resource usage at minimum, only short error codes are used.

During a transaction, if an erroneous node should be evaluated following the execution model rules, it will be evaluated if it raises an error but did not inherit any. This way it can recover and “cure” the whole downstream subgraph bringing back the normal operation.

Also, a node may declare itself as an error catcher. In this case, it will be evaluated even if it inherits an error. Such nodes are used to recover from far upstream errors and take a specific action when something went wrong. In particular, the standard library provides the following error handlers:

  • if-error
  • pulse-on-error
  • error-code

With these nodes, you can extract the code out to display it, retry an attempt, or freeze the device until a reboot.

At another end, to produce an error use the error node or the raiseError function in the C++ code.

Acceptance criteria

  • The new Errcode built-in type is introduced; accepts literals of the Exx form
  • C++ API has functions raiseError, getError<input_IN>(ctx)
  • C++ supports #pragma XOD catch enable
  • The if-error, pulse-on-error, error-code, and error nodes are implemented

How to implement

  • Add a uint8_t error field to the Node structs
  • Use the MSB to denote whether an error is own (0) or inherited (1)
  • In runTransaction, for each node, update the error value by picking and merging upstream errors
  • In runTransaction, expand the logic of dirtiness markup to mark downstream nodes dirty if the current node just got or lost the error state
  • If a node inherits an error and does not declares itself as a catcher, skip evaluate and go on
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants