# Reactive Kernel Notes
A brain dump of the various ways that the kernel should work, but may not currently uphold. I've attempted to define any terms that are important and remove ambiguity. I will continue adding to this issue, as this single comment is not complete record of the things the kernel does.
---
* [Types of Requests]()
* [Non-Awaitable, Non-Generator Request]()
* [Awaitable, Non-generator Request]()
* [(Async) Generator Request]()
* [Lifecycle of a Request]()
* [Initial Steps - all requests]()
* Additional steps - by type of request
* [Non-Awaitable, Non-Generator Request]()
* [Awaitable, Non-generator Request]()
* [(Async) Generator Request]()
* [Definitions/Notes]()
---
## Types of Requests
Three basic types exist:
- Non-Awaitable, Non-Generator Request
- Awaitable, Non-generator Request
- (Async) Generator Request
## Lifecycle of a Request
### Initial Steps - all requests
1. Receive `request`.
- extract `input variables`
- extract `output variable(s)` from the code string in the request.
3. Detect if the output variable
- Error if more than one output variable
- previously defined (old definition)
- detect the differences in `input variables` from old to the new definition
- update the dependency graph with the compute difference
- new definition
- create a new node in the dependency graph
- then add all the edges representing the `input variables`
3. Compute the *descendants* of the current `output variable(s)`
- `None` if it is a new definition.
### Non-Awaitable, Non-Generator Request
4. Execute the block of code using the execution context, and capture the various forms of output.
5. Send the output back to the front end, either establishing or updating using display ids. This output will take advantage of the established IPython mimetype code, using `_repr_html_`, `_repr_svg_`, etc.
6. **For each descendant** of the current `output variable(s)` repeat steps 4 & 5 with the descendant's block of code.
7. Send the final result of success/failure to the front end along with the new execution count.
8. End the `request`.
### Awaitable, Non-generator Request
4. Execute the block of code using the execution context
- capture the various forms of output, specifically the value of the `output variable(s)`
- await the value of the `output variable(s)`, because it is a coroutine,
- update the `execution context`'s `namespace` with the value of the awaited variable.
### (Async) Generator Request
4. Execute the block of code using the execution context
- capture the various forms of output, specifically the value of the `output variable(s)`
- Detect if this value is a regular generator or an async generator.
- a. If the value is a regular generator, then convert it to an async generator that will yield its values and sleep a tiny amount between each time.
- b. if the value is an async generator, do nothing.
5. Cancel any previous async generators that were producing values for the same `output variable(s)` as the current one.
6. Await the first value from the value that is now an async generator, and use that to update the `namespace` of the `execution context`.
7. Send the output back to the front end, either establishing or updating using display ids. This output will take advantage of the established IPython mimetype code, using `_repr_html_`, `_repr_svg_`, etc.
8. **For each descendant** of the current `output variable(s)` repeat steps 4-7 with the descendant's block of code.
9. Send the final result of success/failure to the front end along with the new execution count.
10. Repeat steps 5-8 until the async generator yields no more values, or the current async generator is cancelled.
---
# Definitions/Notes
- a `request`
- a message from the front end, usually `execute_request`
- contains some metadata
- contains a string of code to be executed by the kernel.
- `input variables`
- variables from the code block of the `request` that are not assigned to within the block of code from the `request`.
- In this context "assigned to" also covers class or function definition, anything that associates a name with an object.
- The assumption of the kernel is that any variable that is reference but not assigned within this code block, must have been assigned in another code block, sent in a previous request.
- `output variable(s)`
- variables from the code block of the `request` that are assigned to within the block of code from the `request`.
- `namespace`
- dictionary that holds the values of variable
- mapping names of variables to values of variables.
- `asyncio.sleep(0)`
- this coroutine is used to return control to the event loop and increase the number of points in the execution where other `request`/other computation can be interleaved.
- Returning control to the event loop in more places increases the appearance of parallel execution, even when all code in the event loop is running in a single thread.
- `execution context`
- this object will run code string and capture any output in the form of stdout, stderr, exception, etc.
- In the case of a single assignment as the last expression in the code block, the AST will be manipulated such that the displayhook will capture the value of the last assignment.
- The `execution context` will return a container object that holds all the different forms of output.