forked from the-crypt-keeper/tldw
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
search parsing + building the chain & prompts
- Loading branch information
Showing
9 changed files
with
1,401 additions
and
678 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
# API Documentation | ||
|
||
## Overview | ||
|
||
API uses FastAPI to provide a RESTful interface to the backend services. The API is designed to be simple and easy to use, with a focus on providing a clean interface for the frontend to interact with. | ||
|
||
- **URLs** | ||
- Main page: http://127.0.0.1:8000 | ||
- API Documentation page: http://127.0.0.1:8000/docs | ||
|
||
|
||
|
||
## Endpoints | ||
|
||
|
||
|
||
``` | ||
Here’s the important part. We’ll create: | ||
A global asyncio.Queue of “write tasks.” | ||
A WriteTask class that holds the SQL, parameters, and an asyncio.Future to signal completion. | ||
A background worker (writer_worker) that pops tasks from the queue, executes them, and sets the result in the Future. | ||
Endpoints that push a WriteTask onto the queue, then await the Future before returning. | ||
# main.py | ||
import asyncio | ||
from fastapi import FastAPI, HTTPException | ||
from pydantic import BaseModel | ||
from typing import Any, Tuple, Union | ||
from database import get_db_connection | ||
app = FastAPI() | ||
# ----------------------------- | ||
# 1) A global queue + task class | ||
# ----------------------------- | ||
class WriteTask: | ||
"""Holds SQL, parameters, and a Future to let the enqueuing code wait for completion.""" | ||
def __init__(self, sql: str, params: tuple[Any, ...]): | ||
self.sql = sql | ||
self.params = params | ||
self.future: asyncio.Future = asyncio.get_event_loop().create_future() | ||
write_queue: asyncio.Queue[WriteTask] = asyncio.Queue() | ||
# ----------------------------- | ||
# 2) The background worker | ||
# ----------------------------- | ||
async def writer_worker(): | ||
"""Continuously processes write tasks from the queue, one at a time.""" | ||
while True: | ||
task: WriteTask = await write_queue.get() | ||
try: | ||
# Perform the write | ||
with get_db_connection() as conn: | ||
conn.execute(task.sql, task.params) | ||
conn.commit() | ||
# If success, set the result of the Future | ||
task.future.set_result(True) | ||
except Exception as e: | ||
# If failure, set the exception so the caller can handle it | ||
task.future.set_exception(e) | ||
finally: | ||
write_queue.task_done() | ||
# ----------------------------- | ||
# 3) Start the worker on startup | ||
# ----------------------------- | ||
@app.on_event("startup") | ||
async def startup_event(): | ||
# Launch the writer worker as a background task | ||
asyncio.create_task(writer_worker()) | ||
# ----------------------------- | ||
# 4) Pydantic model for input | ||
# ----------------------------- | ||
class ItemCreate(BaseModel): | ||
name: str | ||
# ----------------------------- | ||
# 5) Write endpoint (POST) | ||
# ----------------------------- | ||
@app.post("/items") | ||
async def create_item(item: ItemCreate): | ||
"""Queue a write to the database, then wait for its completion.""" | ||
sql = "INSERT INTO items (name) VALUES (?)" | ||
params = (item.name,) | ||
# Create a WriteTask | ||
write_task = WriteTask(sql, params) | ||
# Put the task in the queue | ||
await write_queue.put(write_task) | ||
# Wait for the task to complete | ||
try: | ||
result = await write_task.future # This will be True if successful | ||
return {"status": "success", "name": item.name} | ||
except Exception as exc: | ||
# If the DB write failed for some reason, raise a 500 | ||
raise HTTPException(status_code=500, detail=str(exc)) | ||
# ----------------------------- | ||
# 6) Read endpoint (GET) | ||
# ----------------------------- | ||
@app.get("/items") | ||
def read_items(): | ||
"""Simple read operation that does not need the queue.""" | ||
with get_db_connection() as conn: | ||
cursor = conn.cursor() | ||
cursor.execute("SELECT id, name FROM items") | ||
rows = cursor.fetchall() | ||
return [{"id": row[0], "name": row[1]} for row in rows] | ||
Explanation | ||
WriteTask stores (sql, params, future). The future is how we pass success/failure back to the original request. | ||
When a request hits POST /items, we: | ||
Construct a WriteTask. | ||
put() it on the write_queue. | ||
Immediately await write_task.future. We don’t return until the DB operation is done. | ||
The writer_worker loop picks tasks in FIFO order and executes them one-by-one, guaranteeing no concurrency for writes (thus avoiding locks). | ||
On success, task.future.set_result(True) is called. On failure, task.future.set_exception(e). | ||
The awaiting endpoint sees either a success (and returns HTTP 200) or an exception (and returns HTTP 500). | ||
This pattern means each request is effectively serialized for writes, but the user still gets a definitive success/failure response in the same request/response cycle. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,22 @@ | ||
# main.py | ||
# Description: This file contains the main FastAPI application, which serves as the primary API for the tldw application. | ||
# | ||
# Imports | ||
# | ||
# 3rd-party Libraries | ||
from fastapi import FastAPI | ||
# | ||
# Local Imports | ||
# | ||
######################################################################################################################## | ||
# | ||
# Functions: | ||
|
||
app = FastAPI(title="TLDW API", version="1.0.0") | ||
# Usage: uvicorn main:app --reload | ||
app = FastAPI(title="tldw API", version="1.0.0") | ||
|
||
@app.get("/") | ||
async def root(): | ||
return {"message": "Welcome to the tldw API"} | ||
|
||
|