Auto-delete expired events via daily scheduled cleanup job
All checks were successful
CI / backend-test (push) Successful in 58s
CI / frontend-test (push) Successful in 23s
CI / frontend-e2e (push) Successful in 1m10s
CI / build-and-publish (push) Has been skipped

Adds a Spring @Scheduled job (daily at 03:00) that deletes all events
whose expiry_date is before CURRENT_DATE using a native SQL DELETE.
RSVPs are cascade-deleted via the existing FK constraint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 21:58:35 +01:00
parent 2a6a658df9
commit 4bfaee685c
14 changed files with 499 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
# Research: Auto-Delete Expired Events
**Feature**: 013-auto-delete-expired | **Date**: 2026-03-09
## Deletion Strategy
- **Decision**: Direct native SQL DELETE query via Spring Data JPA `@Query`.
- **Rationale**: Simplest approach. No entity loading overhead. The existing `ON DELETE CASCADE` FK constraint on `fk_rsvps_event_id` (migration `003-create-rsvps-table.xml`) handles cascading deletion of RSVPs automatically. The existing `idx_events_expiry_date` index ensures the WHERE clause is efficient.
- **Alternatives considered**:
- JPA repository `deleteAll(findExpired())`: Loads entities into memory first, unnecessary overhead.
- Database-level cron (`pg_cron`): Less portable, adds external dependency.
- Soft delete with lazy cleanup: Over-engineered for fete's scale and privacy goals.
- No deletion (filter only): Contradicts privacy-by-design principle.
## Scheduling Mechanism
- **Decision**: Spring `@Scheduled(cron = ...)` annotation.
- **Rationale**: Already available in Spring Boot, no additional dependencies. Simple, declarative, well-tested.
- **Alternatives considered**:
- Quartz Scheduler: Too heavy for a single daily job.
- External cron (OS-level): Requires separate process management, harder to test.
## Transaction Behavior
- **Decision**: Single transaction for the DELETE statement.
- **Rationale**: A single `DELETE FROM events WHERE expiry_date < CURRENT_DATE` is atomic. If the DB connection drops mid-execution, the transaction rolls back and no events are partially deleted. The next run picks up all expired events.
## Enabling @Scheduled
- **Decision**: Add `@EnableScheduling` to `FeteApplication.java`.
- **Rationale**: Simplest approach. Only one scheduled job exists, no need for a separate config class.