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

Create a WebSocket backend #1

Open
snowleopard opened this issue Aug 25, 2017 · 3 comments
Open

Create a WebSocket backend #1

snowleopard opened this issue Aug 25, 2017 · 3 comments

Comments

@snowleopard
Copy link
Member

We need to figure out a way to connect Centrifuge to the frontend that @gtarawneh is developing.

The backend will need to interact with the frontend by handling requests of the following types:

  • Eval(e): given an expression e evaluate it in the server-side scope and send the result as a response.
    • Get(name) is a simple special case: lookup a value by name, i.e. evaluate the expression name.
  • Bind(name, e): bind a name to an expression and send an acknowledgement.

There may be some variants of the above, where we might also want to return any diagnostic output produced when executing the above requests, so it can be shown to the user. @gtarawneh Perhaps, you could add a small example of such an interactive session?

Some useful links:

@gtarawneh
Copy link
Member

Mini Documentation

The protocol is evolving but here's a mini documentation of the way it currently works.

The front and back-ends communicate by exchanging JSON objects. Each communication consists of a request sent by the front-end and a corresponding reply by the back-end. Below are some cookbook examples.

Setting a variable:

{'set': 'p1', 'value': {'first': 'John', 'last': 'Doe', 'age': 30}}
{'result': 'success'}

Getting a variable:

{'get': 'p1'}
{'result': 'success', 'return': {'first': 'John', 'last': 'Doe', 'age': 30}}

Errors:

{'get': 'p2'}
{'result': 'error', 'description': 'no such variable'}

Calls:

{'call': 'square', 'args': {'x': 5}}
{'result': 'success', 'return': 25}

Evaluation:

{'eval': 'square(5)'}
{'result': 'success', 'return': '25\n'}

Exceptions:

{'eval': 'hello world'}
{'result': 'exception', 'return': '  File "<console>", line 1\n    hello world\n              ^\nSyntaxError: invalid syntax\n'}

Notes

  1. There's a subtle difference between errors and exceptions. Errors indicate a problem with the request message (e.g. being in an incorrect format, or getting a non-existing variable) while exceptions are problems that occur while trying to generate a reply for a valid message (e.g. evaluate 1/0). Errors can occur for any message type while exceptions are only for eval and call messages.

  2. Another subtle difference is that between eval and call messages. Eval returns any content printed to stdout plus the final expression value (all in one string), while call returns the function result as an object.

@snowleopard
Copy link
Member Author

@gtarawneh Thanks for the mini documentation!

It's mostly clear, but I've got a few questions/comments:

  • I can see some redundancy in the API (as an example, get can be implemented via call/eval). Is it intended? Smaller APIs tend to be easier to document, test and maintain, but may require a bit more work from the front-end.

  • The 'error vs exception' confusion is ubiquitous, probably because all languages mean slightly different things by errors and exceptions (e.g. see Java, Python, Haskell). I would prefer if we just classified errors into 'request errors` and 'execution errors' or something similar, instead of falling into this trap.

  • I think the best way to clarify the difference between call and eval (and also to catch redundancies in the API) is to write precise mathematical semantics for each operation in terms of the before/after states of the backend. Happy to help with this.

Perhaps, you can set up a working document for the API specification somewhere so we could discuss it and work out details together?

@gtarawneh
Copy link
Member

@snowleopard some follow-up points:

I can see some redundancy in the API (as an example, get can be implemented via call/eval). Is it intended? Smaller APIs tend to be easier to document, test and maintain, but may require a bit more work from the front-end.

At the moment, get returns the object while eval returns a string representation.

The 'error vs exception' confusion is ubiquitous, probably because all languages mean slightly different things by errors and exceptions (e.g. see Java, Python, Haskell). I would prefer if we just classified errors into 'request errors` and 'execution errors' or something similar, instead of falling into this trap.

Aha, yes that sounds reasonable. I'll simplify things and just merge the two concepts into error, and differentiate between them using additional fields.

I think the best way to clarify the difference between call and eval (and also to catch redundancies in the API) is to write precise mathematical semantics for each operation in terms of the before/after states of the backend. Happy to help with this.

Yes I agree this would help, and this is definitely something we should do at some point. But let's keep it fluid for the time being, because I'm still exploring some options in terms of API design.

Perhaps, you can set up a working document for the API specification somewhere so we could discuss it and work out details together?

Sure, I'll add this to the repo as a starting point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants