From 6a59098c3096f5ebd3a61ef5268cbd480b0f1519 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Tue, 20 Jan 2026 10:40:29 -1000 Subject: Implement efficient sync for Todoist and Trello APIs - Add Todoist Sync API v9 support with incremental sync tokens - Store sync tokens in SQLite for persistence across restarts - Add field filtering to Trello API calls to reduce payload size - Update handlers to use incremental sync (merge changes vs full replace) Co-Authored-By: Claude Opus 4.5 --- internal/store/sqlite.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'internal/store/sqlite.go') diff --git a/internal/store/sqlite.go b/internal/store/sqlite.go index a078748..b8d0c97 100644 --- a/internal/store/sqlite.go +++ b/internal/store/sqlite.go @@ -186,6 +186,54 @@ func (s *Store) DeleteTask(id string) error { return err } +// UpsertTask inserts or updates a single task +func (s *Store) UpsertTask(task models.Task) error { + labelsJSON, _ := json.Marshal(task.Labels) + _, err := s.db.Exec(` + INSERT OR REPLACE INTO tasks + (id, content, description, project_id, project_name, due_date, priority, completed, labels, url, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + `, + task.ID, + task.Content, + task.Description, + task.ProjectID, + task.ProjectName, + task.DueDate, + task.Priority, + task.Completed, + string(labelsJSON), + task.URL, + task.CreatedAt, + ) + return err +} + +// DeleteTasksByIDs removes multiple tasks by ID +func (s *Store) DeleteTasksByIDs(ids []string) error { + if len(ids) == 0 { + return nil + } + tx, err := s.db.Begin() + if err != nil { + return err + } + defer tx.Rollback() + + stmt, err := tx.Prepare(`DELETE FROM tasks WHERE id = ?`) + if err != nil { + return err + } + defer stmt.Close() + + for _, id := range ids { + if _, err := stmt.Exec(id); err != nil { + return err + } + } + return tx.Commit() +} + // Notes operations // SaveNotes saves multiple notes to the database @@ -578,3 +626,33 @@ func (s *Store) DeleteCard(id string) error { _, err := s.db.Exec(`DELETE FROM cards WHERE id = ?`, id) return err } + +// Sync token operations + +// GetSyncToken retrieves the sync token for a service +func (s *Store) GetSyncToken(service string) (string, error) { + var token string + err := s.db.QueryRow(`SELECT token FROM sync_tokens WHERE service = ?`, service).Scan(&token) + if err == sql.ErrNoRows { + return "", nil + } + if err != nil { + return "", err + } + return token, nil +} + +// SetSyncToken saves the sync token for a service +func (s *Store) SetSyncToken(service, token string) error { + _, err := s.db.Exec(` + INSERT OR REPLACE INTO sync_tokens (service, token, updated_at) + VALUES (?, ?, CURRENT_TIMESTAMP) + `, service, token) + return err +} + +// ClearSyncToken removes the sync token for a service +func (s *Store) ClearSyncToken(service string) error { + _, err := s.db.Exec(`DELETE FROM sync_tokens WHERE service = ?`, service) + return err +} -- cgit v1.2.3