diff --git a/examples/Python/src/WebServer/logging.html b/examples/Python/src/WebServer/logging.html
index a7d671e0..2617992e 100644
--- a/examples/Python/src/WebServer/logging.html
+++ b/examples/Python/src/WebServer/logging.html
@@ -36,22 +36,18 @@
Stored Logs:
const port = document.getElementById("portInput").value || 5000;
const fullLogMessage = `Log from ${port}: ${logMessage}`;
const logData = {
+ operation: "newlog",
log: fullLogMessage,
};
- fetch(`http://127.0.0.1:${port}/log`, {
+ fetch(`http://127.0.0.1:${port}/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(logData),
- })
- .then((response) => response.json())
- .then((data) => {
- console.log("Response from server:", data);
- incrementLogValue();
- })
- .catch((error) => console.error("Error:", error));
+ }).catch((error) => console.error("Error:", error));
+ incrementLogValue();
}
function incrementLogValue() {
@@ -63,11 +59,12 @@ Stored Logs:
const port = document.getElementById("portInput").value || 5000;
const startTime = performance.now();
- fetch(`http://127.0.0.1:${port}/getlogs`, {
+ fetch(`http://127.0.0.1:${port}/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
+ body: JSON.stringify({ operation: "getlog" }),
})
.then((response) => response.json())
.then((data) => {
@@ -99,11 +96,12 @@ Stored Logs:
const port = document.getElementById("portInput").value || 5000;
const startTime = performance.now();
- fetch(`http://127.0.0.1:${port}/getlogs_consistent`, {
+ fetch(`http://127.0.0.1:${port}/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
+ body: JSON.stringify({ operation: "getlog_consistent" }),
})
.then((response) => response.json())
.then((data) => {
diff --git a/examples/Python/src/WebServer/logging.lf b/examples/Python/src/WebServer/logging.lf
index 0388818c..81c64054 100644
--- a/examples/Python/src/WebServer/logging.lf
+++ b/examples/Python/src/WebServer/logging.lf
@@ -2,99 +2,45 @@ target Python {
coordination: decentralized
}
-preamble {=
- from fastapi import FastAPI, Request, HTTPException
- from fastapi.middleware.cors import CORSMiddleware
- import threading
- import uvicorn
- import asyncio
- import uuid
-=}
+import WebServer from "../lib/WebServer.lf"
-reactor WebServer(bank_index=0, STA=0) {
- state app
- state events
- input sendlogs
- input sendlogs_consistent
+reactor Router {
+ input request
output newlog
output getlog
output getlog_consistent
- physical action newlog_action
- physical action getlog_action
- logical action getlog_consistent_action
- reaction(startup) -> newlog_action, getlog_action, getlog_consistent_action {=
- self.events = {}
- self.app = FastAPI()
- self.app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"],
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
- @self.app.post("/log")
- async def receive_log(request: Request):
- data = await request.json()
- if "log" in data:
- log_message = data["log"]
- newlog_action.schedule(0, log_message)
- return {"status": "success", "message": "Log stored successfully"}
- else:
- return {"status": "error", "message": "No log provided"}, 400
- @self.app.post("/getlogs")
- async def get_logs(request: Request):
- event = asyncio.Event()
- request_id = str(uuid.uuid4())
- self.events[request_id] = event
- getlog_action.schedule(0, request_id)
- await event.wait()
- logs = self.events[request_id]
- del self.events[request_id]
- return {"status": "success", "logs": logs}
-
- @self.app.post("/getlogs_consistent")
- async def getlogs_consistent(request: Request):
- event = asyncio.Event()
- request_id = str(uuid.uuid4())
- self.events[request_id] = event
- getlog_consistent_action.schedule(0, request_id)
- await event.wait()
- logs = self.events[request_id]
- del self.events[request_id]
- return {"status": "success", "logs": logs}
-
- def run_fastapi_app():
- print(f"[WebServer{self.bank_index}] FastAPI server starting")
- uvicorn.run(self.app, host="127.0.0.1", port=5000+self.bank_index, log_level="warning")
- fastapi_thread = threading.Thread(target=run_fastapi_app)
- fastapi_thread.start()
- =}
-
- reaction(newlog_action) -> newlog {=
- newlog.set(newlog_action.value)
- =}
-
- reaction(getlog_action) -> getlog {=
- getlog.set(getlog_action.value)
- =}
-
- reaction(getlog_consistent_action) -> getlog_consistent {=
- getlog_consistent.set(getlog_consistent_action.value)
- =}
-
- reaction(sendlogs) {=
- [logs, event_id] = sendlogs.value
- event = self.events[event_id]
- self.events[event_id] = logs
- event.set()
+ reaction(request) -> newlog, getlog, getlog_consistent {=
+ # print(f"Router received request: {request.value}")
+ request_id, req_data = request.value
+ if req_data["operation"] == "newlog" and "log" in req_data.keys():
+ newlog.set([request_id, req_data["log"]])
+ elif req_data["operation"] == "getlog":
+ getlog.set(request_id)
+ elif req_data["operation"] == "getlog_consistent":
+ getlog_consistent.set(request_id)
+ else:
+ print("Invalid Request")
+ return
=}
+}
- reaction(sendlogs_consistent) {=
- [logs, event_id] = sendlogs_consistent.value
- event = self.events[event_id]
- self.events[event_id] = logs
- event.set()
+reactor WebServerRouter(bank_index=0, STA=0) {
+ output newlog
+ output getlog
+ output getlog_consistent
+ webserver = new WebServer(port = {= 5000+self.bank_index =}, endpoint="/")
+ router = new Router()
+ webserver.request -> router.request
+ router.newlog -> newlog
+ router.getlog -> getlog
+ router.getlog_consistent -> getlog_consistent
+ input[2] response
+
+ reaction(response) -> webserver.response {=
+ for port in response:
+ if port.is_present:
+ webserver.response.set(port.value)
=}
}
@@ -108,27 +54,26 @@ reactor Database(bank_index=0, portwidth=2, STA = 0 s) {
self.logs = []
=}
- reaction(addlog) {=
+ reaction(addlog) -> sendlogs {=
for i, port in enumerate(addlog):
if port.is_present:
- log_message = port.value
+ request_id, log_message = port.value
self.logs.append(log_message)
=}
reaction(getlog) -> sendlogs {=
- sendlogs.set([self.logs, getlog.value])
+ sendlogs.set([getlog.value, {"status": "success", "logs": self.logs}])
=}
}
federated reactor(ReplicaCount=2) {
- server = new[ReplicaCount] WebServer()
+ server = new[ReplicaCount] WebServerRouter()
db = new[ReplicaCount] Database(portwidth=ReplicaCount)
(server.newlog)+ ~> db.addlog
server.getlog ~> db.getlog
- db.sendlogs ~> server.sendlogs
dbc = new[ReplicaCount] Database(portwidth=ReplicaCount, STA = 3 s)
(server.newlog)+ -> dbc.addlog
server.getlog_consistent -> dbc.getlog
- dbc.sendlogs ~> server.sendlogs_consistent
+ db.sendlogs, dbc.sendlogs ~> interleaved(server.response)
}
diff --git a/examples/Python/src/lib/WebServer.lf b/examples/Python/src/lib/WebServer.lf
index 1f9cdc74..7332d229 100644
--- a/examples/Python/src/lib/WebServer.lf
+++ b/examples/Python/src/lib/WebServer.lf
@@ -51,6 +51,9 @@ reactor WebServer(port=5000, endpoint="/") {
reaction(response) {=
request_id, resp_data = response.value
+ if request_id not in self.events:
+ print("Invalid Request ID")
+ return
event = self.events[request_id]
self.events[request_id] = resp_data
event.set()