Skip to content

Commit 3223ca6

Browse files
committed
Prompts: add started/completed, remove duration_ms
Migrate prompts to track async timings: remove duration_ms and add started (BIGINT NOT NULL, default epoch) and completed (BIGINT nullable). Update API and Pydantic schemas to return and accept started/completed, initialize response and completed as NULL on create, and set started to provided value or current epoch. Includes SQL and Python migration scripts, bumps package version to 2.0.1, and tweaks app metadata.
1 parent 93941d5 commit 3223ca6

6 files changed

Lines changed: 64 additions & 17 deletions

File tree

app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""NX AI - FastAPI, Python, Postgres, tsvector"""
22

33
# Current Version
4-
__version__ = "2.0.0"
4+
__version__ = "2.0.1"

app/api/prompts/prompts.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ def root() -> dict:
4242
conn = get_db_connection_direct()
4343
try:
4444
with conn.cursor() as cur:
45-
cur.execute("SELECT id, prompt, response, duration_ms, llm, timestamp FROM prompts ORDER BY id DESC;")
45+
cur.execute("SELECT id, prompt, response, llm, started, completed, timestamp FROM prompts ORDER BY id DESC;")
4646
rows = cur.fetchall()
47-
keys = ["id", "prompt", "response", "duration_ms", "llm", "timestamp"]
47+
keys = ["id", "prompt", "response", "llm", "started", "completed", "timestamp"]
4848
for row in rows:
4949
data.append(dict(zip(keys, row)))
5050
finally:
@@ -59,21 +59,24 @@ def create_prompt(prompt_in: PromptCreate = Body(...)):
5959
"""Create a new prompt record in the prompts table."""
6060
from app.utils.db import get_db_connection_direct
6161
import psycopg2
62+
import time
6263
conn = get_db_connection_direct()
64+
started = prompt_in.started if prompt_in.started is not None else int(time.time())
6365
try:
6466
with conn.cursor() as cur:
6567
cur.execute(
6668
"""
67-
INSERT INTO prompts (prompt, response, duration_ms, llm, timestamp)
68-
VALUES (%s, %s, %s, %s, COALESCE(%s, NOW()))
69-
RETURNING id, prompt, response, duration_ms, llm, timestamp
69+
INSERT INTO prompts (prompt, response, llm, started, completed, timestamp)
70+
VALUES (%s, %s, %s, %s, %s, COALESCE(%s, NOW()))
71+
RETURNING id, prompt, response, llm, started, completed, timestamp
7072
""",
7173
(
7274
prompt_in.prompt,
73-
prompt_in.response,
74-
prompt_in.duration_ms,
75+
None, # Always set response to NULL initially
7576
prompt_in.llm,
76-
prompt_in.timestamp,
77+
started,
78+
None, # completed is NULL initially
79+
None, # timestamp
7780
)
7881
)
7982
row = cur.fetchone()
@@ -84,7 +87,7 @@ def create_prompt(prompt_in: PromptCreate = Body(...)):
8487
finally:
8588
conn.close()
8689
if row:
87-
keys = ["id", "prompt", "response", "duration_ms", "llm", "timestamp"]
90+
keys = ["id", "prompt", "response", "llm", "started", "completed", "timestamp"]
8891
return dict(zip(keys, row))
8992
return {"error": "Failed to insert prompt."}
9093

app/api/prompts/schemas.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33

44
class PromptCreate(BaseModel):
55
prompt: str
6-
response: str
7-
duration_ms: int
86
llm: str
9-
timestamp: Optional[str] = None # ISO format, optional for auto
7+
started: Optional[int] = None # Unix epoch, set by backend if not provided
108

119
class PromptOut(BaseModel):
1210
id: int
1311
prompt: str
14-
response: str
15-
duration_ms: int
12+
response: Optional[str]
1613
llm: str
14+
started: int
15+
completed: Optional[int]
1716
timestamp: str
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- Migration: Update prompts table for async processing
2+
ALTER TABLE prompts
3+
DROP COLUMN IF EXISTS duration_ms,
4+
ADD COLUMN IF NOT EXISTS started BIGINT NOT NULL DEFAULT (extract(epoch from now())),
5+
ADD COLUMN IF NOT EXISTS completed BIGINT;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Python migration script to update prompts table:
3+
- Remove duration_ms column
4+
- Add started (BIGINT NOT NULL, default now as epoch)
5+
- Add completed (BIGINT, nullable)
6+
"""
7+
import os
8+
import psycopg2
9+
from dotenv import load_dotenv
10+
11+
load_dotenv()
12+
13+
ALTER_SQL = """
14+
ALTER TABLE prompts
15+
DROP COLUMN IF EXISTS duration_ms,
16+
ADD COLUMN IF NOT EXISTS started BIGINT NOT NULL DEFAULT (extract(epoch from now())),
17+
ADD COLUMN IF NOT EXISTS completed BIGINT;
18+
"""
19+
20+
def main():
21+
conn = psycopg2.connect(
22+
host=os.getenv('DB_HOST'),
23+
port=os.getenv('DB_PORT', '5432'),
24+
dbname=os.getenv('DB_NAME'),
25+
user=os.getenv('DB_USER'),
26+
password=os.getenv('DB_PASSWORD'),
27+
)
28+
try:
29+
with conn.cursor() as cur:
30+
cur.execute(ALTER_SQL)
31+
conn.commit()
32+
print("Migration applied successfully.")
33+
except Exception as e:
34+
conn.rollback()
35+
print(f"Migration failed: {e}")
36+
finally:
37+
conn.close()
38+
39+
if __name__ == "__main__":
40+
main()

app/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from app.api.routes import router
88

99
app = FastAPI(
10-
title="NX AI",
11-
description="NX AI - FastAPI, Python, Postgres, tsvector",
10+
title="Python",
11+
description="FastAPI, Python, Postgres, tsvector",
1212
version=__version__,
1313
)
1414

0 commit comments

Comments
 (0)