Make copy operation atomic with explicit transaction handling

- Wrapped copy operation in try/except with explicit rollback
- Added comments explaining atomicity
- Ensures all-or-nothing behavior for copying to multiple dates
This commit is contained in:
counterweight 2025-12-21 17:57:42 +01:00
parent c24597edb4
commit 1a478f7583
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C

View file

@ -160,34 +160,41 @@ async def copy_availability(
detail=f"No availability found for source date {request.source_date}",
)
# Copy to each target date
# Copy to each target date within a single atomic transaction
# All deletes and inserts happen before commit, ensuring atomicity
copied_days: list[AvailabilityDay] = []
for target_date in request.target_dates:
if target_date == request.source_date:
continue # Skip copying to self
# Delete existing availability for target date
await db.execute(
delete(Availability).where(Availability.date == target_date)
)
# Copy slots
target_slots: list[TimeSlot] = []
for source_slot in source_slots:
new_availability = Availability(
date=target_date,
start_time=source_slot.start_time,
end_time=source_slot.end_time,
try:
for target_date in request.target_dates:
if target_date == request.source_date:
continue # Skip copying to self
# Delete existing availability for target date
await db.execute(
delete(Availability).where(Availability.date == target_date)
)
db.add(new_availability)
target_slots.append(TimeSlot(
start_time=source_slot.start_time,
end_time=source_slot.end_time,
))
# Copy slots
target_slots: list[TimeSlot] = []
for source_slot in source_slots:
new_availability = Availability(
date=target_date,
start_time=source_slot.start_time,
end_time=source_slot.end_time,
)
db.add(new_availability)
target_slots.append(TimeSlot(
start_time=source_slot.start_time,
end_time=source_slot.end_time,
))
copied_days.append(AvailabilityDay(date=target_date, slots=target_slots))
copied_days.append(AvailabilityDay(date=target_date, slots=target_slots))
await db.commit()
# Commit all changes atomically
await db.commit()
except Exception:
# Rollback on any error to maintain atomicity
await db.rollback()
raise
return AvailabilityResponse(days=copied_days)