Fix several bugs and race conditions.
This commit is contained in:
@@ -5,6 +5,7 @@ from typing import Optional
|
||||
from datetime import datetime
|
||||
from fastapi import FastAPI, HTTPException, Path
|
||||
from pydantic import BaseModel, Field
|
||||
from filelock import FileLock
|
||||
import argparse
|
||||
import uvicorn
|
||||
|
||||
@@ -49,7 +50,11 @@ class Vote(BaseModel):
|
||||
DATA_DIR = "" # will be overridden via command line
|
||||
|
||||
def get_tour_filepath(tour_id: str) -> str:
|
||||
return os.path.join(DATA_DIR, f"{tour_id}.json")
|
||||
fname = f"{tour_id}.json"
|
||||
full = os.path.abspath(os.path.join(DATA_DIR, fname))
|
||||
if not full.startswith(os.path.abspath(DATA_DIR) + os.sep):
|
||||
raise HTTPException(status_code=400, detail="Invalid tour ID")
|
||||
return full
|
||||
|
||||
# ─── ENDPOINT: CREATE TOUR ─────────────────────────────────────────────────────
|
||||
|
||||
@@ -74,7 +79,7 @@ def create_tour(tour: TourCreate):
|
||||
filepath = get_tour_filepath(tour_id)
|
||||
with open(filepath, "w") as f:
|
||||
# Using default=str so that datetime objects become ISO strings
|
||||
json.dump(new_tour.dict(), f, default=str)
|
||||
json.dump(new_tour.model_dump(), f, default=str)
|
||||
|
||||
return new_tour
|
||||
|
||||
@@ -117,22 +122,24 @@ def add_idea(tour_id: str, idea: IdeaCreate):
|
||||
if not os.path.exists(filepath):
|
||||
raise HTTPException(status_code=404, detail="Tour not found")
|
||||
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
lock = FileLock(filepath + ".lock")
|
||||
with lock:
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
|
||||
idea_id = str(uuid.uuid4())
|
||||
new_idea = Idea(
|
||||
id=idea_id,
|
||||
name=idea.name,
|
||||
description=idea.description,
|
||||
voters=[],
|
||||
start_time=idea.start_time,
|
||||
end_time=idea.end_time,
|
||||
)
|
||||
idea_id = str(uuid.uuid4())
|
||||
new_idea = Idea(
|
||||
id=idea_id,
|
||||
name=idea.name,
|
||||
description=idea.description,
|
||||
voters=[],
|
||||
start_time=idea.start_time,
|
||||
end_time=idea.end_time,
|
||||
)
|
||||
|
||||
data["ideas"].append(new_idea.dict())
|
||||
with open(filepath, "w") as f:
|
||||
json.dump(data, f, default=str)
|
||||
data["ideas"].append(new_idea.model_dump())
|
||||
with open(filepath, "w") as f:
|
||||
json.dump(data, f, default=str)
|
||||
|
||||
return new_idea
|
||||
|
||||
@@ -147,17 +154,19 @@ def vote_idea(tour_id: str, idea_id: str, vote: Vote):
|
||||
if not os.path.exists(filepath):
|
||||
raise HTTPException(status_code=404, detail="Tour not found")
|
||||
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
lock = FileLock(filepath + ".lock")
|
||||
with lock:
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
|
||||
for idea in data["ideas"]:
|
||||
if idea["id"] == idea_id:
|
||||
if vote.voterName not in idea["voters"]:
|
||||
idea["voters"].append(vote.voterName)
|
||||
# Persist the change
|
||||
with open(filepath, "w") as f:
|
||||
json.dump(data, f, default=str)
|
||||
return Idea(**idea)
|
||||
for idea in data["ideas"]:
|
||||
if idea["id"] == idea_id:
|
||||
if vote.voterName not in idea["voters"]:
|
||||
idea["voters"].append(vote.voterName)
|
||||
# Persist the change
|
||||
with open(filepath, "w") as f:
|
||||
json.dump(data, f, default=str)
|
||||
return Idea(**idea)
|
||||
|
||||
raise HTTPException(status_code=404, detail="Idea not found")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user