Add performance optimizations and database indexes

Database Indexes (migrations 006-009):
- Add case-insensitive indexes for auth lookups (email, username)
- Add composite indexes for task kanban queries
- Add indexes for notification, document, and completion queries
- Add unique index for active share codes
- Remove redundant idx_share_code_active and idx_notification_user_sent

Repository Optimizations:
- Add FindResidenceIDsByUser() lightweight method (IDs only, no preloads)
- Optimize GetResidenceUsers() with single UNION query (was 2 queries)
- Optimize kanban completion preloads to minimal columns (id, task_id, completed_at)

Service Optimizations:
- Remove Category/Priority/Frequency preloads from task queries
- Remove summary calculations from CRUD responses (client calculates)
- Use lightweight FindResidenceIDsByUser() instead of full FindByUser()

These changes reduce database load and response times for common operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-14 01:06:08 -06:00
parent 2ea5cea936
commit 0cf64cfb0c
22 changed files with 436 additions and 203 deletions

View File

@@ -533,13 +533,14 @@ func TestRecurringTask_Lifecycle_FirstCompletion(t *testing.T) {
err = taskRepo.CreateCompletion(completion)
require.NoError(t, err)
// Reload to get frequency
// Reload task
task, err = taskRepo.FindByID(task.ID)
require.NoError(t, err)
// Simulate the next_due_date update (from task_service.CreateCompletion)
// For recurring task: NextDueDate = CompletedAt + FrequencyDays
nextDue := completedAt.AddDate(0, 0, *task.Frequency.Days)
// Note: Frequency is no longer preloaded for performance, use the weeklyFreq we already have
nextDue := completedAt.AddDate(0, 0, *weeklyFreq.Days)
task.NextDueDate = &nextDue
err = taskRepo.Update(task)
require.NoError(t, err)
@@ -603,7 +604,8 @@ func TestRecurringTask_Lifecycle_MultipleCompletions(t *testing.T) {
})
task, _ = taskRepo.FindByID(task.ID)
nextDue1 := completedAt1.AddDate(0, 0, *task.Frequency.Days)
// Note: Frequency is no longer preloaded for performance, use weeklyFreq we already have
nextDue1 := completedAt1.AddDate(0, 0, *weeklyFreq.Days)
task.NextDueDate = &nextDue1
taskRepo.Update(task)
@@ -632,7 +634,8 @@ func TestRecurringTask_Lifecycle_MultipleCompletions(t *testing.T) {
})
task, _ = taskRepo.FindByID(task.ID)
nextDue2 := completedAt2.AddDate(0, 0, *task.Frequency.Days)
// Note: Frequency is no longer preloaded for performance, use weeklyFreq we already have
nextDue2 := completedAt2.AddDate(0, 0, *weeklyFreq.Days)
task.NextDueDate = &nextDue2
taskRepo.Update(task)
@@ -725,7 +728,7 @@ func TestKanbanBoard_OneTimeTaskCompletion_MovesToCompleted(t *testing.T) {
db.Create(task)
// Before completion - should be in due_soon
board, err := taskRepo.GetKanbanData(residence.ID, 30)
board, err := taskRepo.GetKanbanData(residence.ID, 30, time.Now().UTC())
require.NoError(t, err)
dueSoonCount := 0
@@ -751,7 +754,7 @@ func TestKanbanBoard_OneTimeTaskCompletion_MovesToCompleted(t *testing.T) {
db.Save(task)
// After completion - should be in completed
board, err = taskRepo.GetKanbanData(residence.ID, 30)
board, err = taskRepo.GetKanbanData(residence.ID, 30, time.Now().UTC())
require.NoError(t, err)
for _, col := range board.Columns {
@@ -790,7 +793,7 @@ func TestKanbanBoard_RecurringTaskCompletion_StaysActionable(t *testing.T) {
db.Create(task)
// Before completion - should be overdue
board, err := taskRepo.GetKanbanData(residence.ID, 30)
board, err := taskRepo.GetKanbanData(residence.ID, 30, time.Now().UTC())
require.NoError(t, err)
var overdueCount, completedCount, dueSoonCount int
@@ -821,7 +824,7 @@ func TestKanbanBoard_RecurringTaskCompletion_StaysActionable(t *testing.T) {
db.Save(task)
// After completion - should be in due_soon, NOT completed
board, err = taskRepo.GetKanbanData(residence.ID, 30)
board, err = taskRepo.GetKanbanData(residence.ID, 30, time.Now().UTC())
require.NoError(t, err)
for _, col := range board.Columns {