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>
32 lines
1.7 KiB
Markdown
32 lines
1.7 KiB
Markdown
# 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.
|