Skip to content

Commit

Permalink
Document suggestions from code review
Browse files Browse the repository at this point in the history
Co-authored-by: Edward A. Lee <eal@eecs.berkeley.edu>
  • Loading branch information
Depetrol and edwardalee authored Oct 10, 2024
1 parent ba492d5 commit faf5ae2
Showing 1 changed file with 13 additions and 13 deletions.
26 changes: 13 additions & 13 deletions examples/Python/src/WebServer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ This example shows how to create an HTTP web server backend in Lingua Franca pyt
In this example, we will build a distributed logging service with two replicated databases, each database with an HTTP web server that handles add log and get log requests from frontend. The HTTP web server backend is `logging.lf`, and the frontend is `logging.html`. Valid requests are the following three kinds:

- Add log: adds a log to the distributed database. The add log request is broadcast to all database replicas.
- Get log: get all historical logs from a single database. This returns without waiting for maximum availability. However, the logs could be out of order and inconsistent with each other.
- Get log: get all historical logs from a single database. This returns without waiting for consistency, so the logs could be out of order and inconsistent with each other.
- Get log consistent: get consistent historical logs from a single database. This request will respond slower but with consistency, meaning requests to different replicas will return identical logs if the requests have the same timestamp.

## HTTP Server

Building an HTTP server in Lingua Franca python target is a nontrivial task for several reasons:

- The HTTP server in python is blocking operation that prevents a reaction from finishing
- Typical python web frameworks use decorator style and require you to return the response in the handler function, but to utilize the full potential of Lingua Franca, we often need to implement logic in different reactions.
- The HTTP server in python is a blocking operation that prevents a reaction from finishing.
- Typical python web frameworks use a decorator style and require you to return the response in the handler function, but to utilize the full potential of Lingua Franca, we often need to implement logic in different reactions.

To tackle the issues above, we can:

Expand All @@ -25,7 +25,7 @@ To tackle the issues above, we can:

## Minimal +1 Example

First, let's build a minimal web server that adds one to the number in the request. The backend is in `minimal.lf`, frontend is `minimal.html`.
First, let's build a minimal web server that adds one to the number in the request. The backend is in `minimal.lf`, and frontend is `minimal.html`.

The handler is as follows:

Expand Down Expand Up @@ -56,21 +56,21 @@ reaction(addone_action){=

When a request is processed by a handler, a response is generated in the following steps:

1. Create a python async io event and add it to `self.events`
2. Trigger a physical action in Lingua Franca to process the request
3. Block the handler until the event is unblocked by another reaction
4. When the action has been processed, another reaction unblocks the asyncio event
5. The handler can now continue to execute and respond to the web request
1. Create a python async io event and add it to `self.events`.
2. Trigger a physical action in Lingua Franca to process the request.
3. Block the handler until the event is unblocked by another reaction.
4. When the action has been processed, another reaction unblocks the asyncio event.
5. The handler can now continue to execute and respond to the web request.

## Distributed Logging

![logging](logging.svg)

Now we can implement a distributed logging system by instantiating several `WebServer` on different network ports adding two `Database` for each `WebServer`.
Now we can implement a distributed logging system by instantiating several `WebServer` reactors on different network ports and adding two `Database` reactors for each `WebServer`.

* One `Database` has the STA offset of 0, connected by physical connections. This will prioritize availability and fast response times.
* Another `Database` has the STA offset of 3s(This can be changed), connected by logical connections. This will guarantee that the logs in this `Database` will be consistent as long as out-of-order messages arrive within 3s.
* One `Database` reactor has an STA offset of 0 and is connected by physical connections. This will prioritize availability, generating a quick response that is not (necessarily) consistent.
* Another `Database` reactor has an STA offset of 3s (this can be changed) and is connected by logical connections. This will guarantee that the logs in this `Database` reactor will be consistent as long as out-of-order messages arrive within 3s.

Note that this is implemented with banks and multiports. When sending logs, we want the `WebServer` to send logs to all `Database`, so the `newlog` connection is a multiport; but when getting logs, we want to know the log state of the single corresponding `Database`, which means that there is no multiport for the get log operation.
Note that this is implemented with banks and multiports. When sending logs, we want the `WebServer` to send logs to all `Database` reactors, so the `newlog` connection is a multiport; but when getting logs, we want to know the log state of the single corresponding `Database` reactor, which means that there is no multiport for the get log operation.

The `sendlogs` connections from `Database` to `WebServer` are implemented with physical connections. This is because these connections carry no timing semantics -- they simply carry the data to be sent back to the frontend as a response and need to be executed as soon as possible.

0 comments on commit faf5ae2

Please sign in to comment.