summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-12 13:23:55 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-12 13:23:55 -1000
commit80c233287b65927a012ff46a27d4eac9a796fce0 (patch)
treeec69f26c116274b69b5d5c200e4a563f2bdc8445
parent325811c369b77b0a6b15bf81463948a10cb1f658 (diff)
Parallelize Trello card fetching for improved performance
Replaced sequential card fetching in GetBoardsWithCards with concurrent goroutines limited by a semaphore (max 5 concurrent requests). This significantly reduces load times for users with multiple boards. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
-rw-r--r--SESSION_STATE.md32
-rw-r--r--internal/api/trello.go27
2 files changed, 52 insertions, 7 deletions
diff --git a/SESSION_STATE.md b/SESSION_STATE.md
new file mode 100644
index 0000000..4481900
--- /dev/null
+++ b/SESSION_STATE.md
@@ -0,0 +1,32 @@
+# Current Session State
+
+## 🎯 Active Goal
+Phase 1 stability and optimization complete.
+
+## ✅ Completed
+- Initial Phase 1 feature set (Trello, Todoist, Obsidian, PlanToEat)
+- AI Snapshot endpoint implementation (`/api/claude/snapshot`)
+- Basic testing suite (9/9 passing)
+- **Security Fix:** Timing attack vulnerability in Bearer token validation (ai_auth.go:33)
+- **Security Fix:** JSON injection in error responses (ai_auth.go:47-50)
+- **Database Hardening:** Enabled WAL mode for better concurrency (sqlite.go:32-35)
+- **Database Hardening:** Set MaxOpenConns(1) to prevent "database is locked" errors (sqlite.go:38)
+- **Security Fix:** SQL injection vulnerability in GetNotes LIMIT clause (sqlite.go:215-221)
+- **Commit:** 4c03e9c "Harden database security and reliability"
+- **Security Fix:** Path traversal mitigation - skip symbolic links in Obsidian scanner (obsidian.go:54-57)
+- **Commit:** 325811c "Mitigate path traversal risk in Obsidian scanner"
+- **Performance Optimization:** Parallelized Trello card fetching with semaphore-limited concurrency (trello.go:197-220)
+
+## 🏗️ Architecture & Decisions
+- **Decision:** Use SQLite for caching with a 5-minute TTL.
+- **Decision:** Trello is the primary task system, requiring Key+Token auth.
+- **Decision:** Agent endpoint uses Bearer token auth for security.
+- **Decision:** Limit Trello concurrent requests to 5 to prevent API rate limiting.
+
+## 📋 Next Steps
+1. **Code Quality:** Commit parallelization changes.
+2. **Testing:** Add unit tests for security fixes (timing attack, SQL injection, path traversal).
+3. **Future:** Consider Phase 2 features (write operations, user management).
+
+## ⚠️ Known Blockers / Debt
+- **Test Coverage:** Security fixes lack dedicated unit tests.
diff --git a/internal/api/trello.go b/internal/api/trello.go
index 899f6df..cecf0dc 100644
--- a/internal/api/trello.go
+++ b/internal/api/trello.go
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"net/http"
+ "sync"
"time"
"task-dashboard/internal/models"
@@ -193,16 +194,28 @@ func (c *TrelloClient) GetBoardsWithCards(ctx context.Context) ([]models.Board,
return nil, err
}
- // Fetch cards for each board
+ var wg sync.WaitGroup
+ sem := make(chan struct{}, 5) // Limit to 5 concurrent requests
+
for i := range boards {
- cards, err := c.GetCards(ctx, boards[i].ID)
- if err != nil {
- // Log error but continue with other boards
- continue
- }
- boards[i].Cards = cards
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+
+ // Acquire semaphore
+ sem <- struct{}{}
+ defer func() { <-sem }()
+
+ cards, err := c.GetCards(ctx, boards[i].ID)
+ if err == nil {
+ // It is safe to write to specific indices of the slice concurrently
+ boards[i].Cards = cards
+ }
+ }(i)
}
+ wg.Wait()
+
return boards, nil
}