I don’t understand how to avoid concurrency when there are more sessions.
Let’s imagine there are some table User:
class User(Base):
__tablename__ = "user"
id: Mapped[UUID] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(unique=True)
hashed_password: Mapped[str]
crud functions:
async def create(db: AsyncSession, user_scheme: UserCreate) -> User:
user = User(
**user_scheme.model_dump(exclude={"password"}),
hashed_password=hash_password(user_scheme.password),
)
db.add(user)
await db.commit()
return user
async def exists_by_email(db: AsyncSession, user_email: str) -> bool:
stmt = sql.select(sql.exists(User).where(User.email == user_email))
res = await db.scalar(stmt)
return bool(res)
and route function:
@router.post("/", status_code=201, response_model=UserRead)
async def register_user(db: SessionDepends, user_scheme: UserCreate) -> User:
# step 1: check if is email taken
if await crud.user.exists_by_email(db, user_scheme.email):
raise HTTPException(409, "Email is already taken")
# step 2: create and return user
return await crud.user.create(db, user_scheme)
What if there are two clients that trying to register user with a same email and occur situations like below:
Session 1 | Session 2 |
---|---|
Check if the email is taken -> False |
|
Check if the email is taken -> False |
|
Create user -> user |
|
Create user -> exception |
|
Return -> 201 user |
Return -> 500 :( |
I want to learn how to properly write code in these cases?
2