Repository navigation
First Check
Example Codeimport threading
import uuid
import httpx
data = {
"email": f"{uuid.uuid4().hex}@example.com",
"password": "changethis123",
"full_name": "Race",
}
def signup() -> None:
r = httpx.post("http://localhost:8000/api/v1/users/signup", json=data)
print(r.status_code)
threads = [threading.Thread(target=signup) for _ in range(2)]
for t in threads:
t.start()
for t in threads:
t.join()
# Expected: 200 and 400. When the two requests overlap: 200 and 500.DescriptionTwo signup requests with the same email at the same moment: one returns 200 and the other returns 500. One after the other they return 200 and 400. The same happens on POST /api/v1/users/. Both requests pass the email check before either one inserts. The unique index on user.email stops the second insert, and that error is not handled. No duplicate user is created. I have a small fix with two tests in #2527, and all checks passed there. Sorry for opening the PR before a discussion. Would you like me to reopen it? This may also explain #1400, where a 500 on signup with an existing email could not be reproduced Operating SystemWindows Operating System DetailsNo response Project Versionmaster at aabb901 Python Version3.14 Additional ContextI found this with racetrap, a tool I am building that forces the order of SQL statements between two requests: https://github.com/w-rahul/racetrap |
Replies: 2 comments
|
Hi! Your analysis matches the code on
Catching One thing #2527 does not cover: the two update endpoints have the same pattern for email changes. from sqlalchemy.exc import IntegrityError
# PATCH /users/me
user_data = user_in.model_dump(exclude_unset=True)
current_user.sqlmodel_update(user_data)
session.add(current_user)
try:
session.commit()
except IntegrityError:
session.rollback()
raise HTTPException(status_code=409, detail="User with this email already exists")
session.refresh(current_user)
return current_userFor About reopening #2527: that is the maintainers' call. Per the contribution rules quoted when it was closed, the PR is opened (or reopened) once a team member asks for it in this discussion, so linking it here as you did is the expected step. Hope this helps! |
#2527