fix incremental sync

This commit is contained in:
Erik Winter 2025-01-05 14:37:46 +01:00
parent 83affc6cac
commit 1944c67a4a
7 changed files with 33 additions and 14 deletions

BIN
dist/plan vendored

Binary file not shown.

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"time"
"go-mod.ewintr.nl/planner/item" "go-mod.ewintr.nl/planner/item"
"go-mod.ewintr.nl/planner/plan/storage" "go-mod.ewintr.nl/planner/plan/storage"
@ -39,17 +40,21 @@ func (s Sync) Do(deps Dependencies) (CommandResult, error) {
} }
// get new/updated items // get new/updated items
ts, err := deps.SyncRepo.LastUpdate() oldTS, err := deps.SyncRepo.LastUpdate()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not find timestamp of last update: %v", err) return nil, fmt.Errorf("could not find timestamp of last update: %v", err)
} }
recItems, err := deps.SyncClient.Updated([]item.Kind{item.KindTask}, ts) recItems, err := deps.SyncClient.Updated([]item.Kind{item.KindTask}, oldTS)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not receive updates: %v", err) return nil, fmt.Errorf("could not receive updates: %v", err)
} }
updated := make([]item.Item, 0) updated := make([]item.Item, 0)
var newTS time.Time
for _, ri := range recItems { for _, ri := range recItems {
if ri.Updated.After(newTS) {
newTS = ri.Updated
}
if ri.Deleted { if ri.Deleted {
if err := deps.LocalIDRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) { if err := deps.LocalIDRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) {
return nil, fmt.Errorf("could not delete local id: %v", err) return nil, fmt.Errorf("could not delete local id: %v", err)
@ -94,6 +99,10 @@ func (s Sync) Do(deps Dependencies) (CommandResult, error) {
} }
} }
if err := deps.SyncRepo.SetLastUpdate(newTS); err != nil {
return nil, fmt.Errorf("could not store update timestamp: %v", err)
}
return SyncResult{}, nil return SyncResult{}, nil
} }

View File

@ -52,6 +52,10 @@ func (r *Sync) DeleteAll() error {
return nil return nil
} }
func (r *Sync) SetLastUpdate(ts time.Time) error {
return nil
}
func (r *Sync) LastUpdate() (time.Time, error) { func (r *Sync) LastUpdate() (time.Time, error) {
r.mutex.RLock() r.mutex.RLock()
defer r.mutex.RUnlock() defer r.mutex.RUnlock()

View File

@ -39,6 +39,9 @@ var migrations = []string{
`INSERT INTO localids (id, local_id) `INSERT INTO localids (id, local_id)
SELECT id, local_id FROM localids_backup`, SELECT id, local_id FROM localids_backup`,
`DROP TABLE localids_backup`, `DROP TABLE localids_backup`,
`ALTER TABLE items ADD COLUMN date TEXT NOT NULL DEFAULT ''`, `ALTER TABLE items ADD COLUMN date TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE tasks ADD COLUMN project TEXT NOT NULL DEFAULT ''`, `ALTER TABLE tasks ADD COLUMN project TEXT NOT NULL DEFAULT ''`,
`CREATE TABLE syncupdate ("timestamp" TIMESTAMP NOT NULL)`,
`INSERT INTO syncupdate (timestamp) VALUES ("0001-01-01T00:00:00Z")`,
} }

View File

@ -84,20 +84,22 @@ func (s *SqliteSync) DeleteAll() error {
return nil return nil
} }
func (s *SqliteSync) SetLastUpdate(ts time.Time) error {
if _, err := s.db.Exec(`UPDATE syncupdate SET timestamp = ?`, ts.Format(time.RFC3339)); err != nil {
return fmt.Errorf("%w: could not store timestamp: %v", ErrSqliteFailure, err)
}
return nil
}
func (s *SqliteSync) LastUpdate() (time.Time, error) { func (s *SqliteSync) LastUpdate() (time.Time, error) {
var updatedStr sql.NullString var tsStr string
err := s.db.QueryRow("SELECT MAX(updated) FROM items").Scan(&updatedStr) if err := s.db.QueryRow("SELECT timestamp FROM syncupdate").Scan(&tsStr); err != nil {
if err != nil {
return time.Time{}, fmt.Errorf("%w: failed to get last update: %v", ErrSqliteFailure, err) return time.Time{}, fmt.Errorf("%w: failed to get last update: %v", ErrSqliteFailure, err)
} }
ts, err := time.Parse(time.RFC3339, tsStr)
if !updatedStr.Valid {
return time.Time{}, nil // Return zero time if NULL or no rows
}
lastUpdate, err := time.Parse(time.RFC3339, updatedStr.String)
if err != nil { if err != nil {
return time.Time{}, fmt.Errorf("%w: failed to parse last update time: %v", ErrSqliteFailure, err) return time.Time{}, fmt.Errorf("%w: could not convert db timstamp into time.Time: %v", ErrSqliteFailure, err)
} }
return lastUpdate, nil
return ts, nil
} }

View File

@ -25,6 +25,7 @@ type Sync interface {
FindAll() ([]item.Item, error) FindAll() ([]item.Item, error)
Store(i item.Item) error Store(i item.Item) error
DeleteAll() error DeleteAll() error
SetLastUpdate(ts time.Time) error
LastUpdate() (time.Time, error) LastUpdate() (time.Time, error)
} }

View File

@ -59,7 +59,7 @@ func (c *HTTP) Updated(ks []item.Kind, ts time.Time) ([]item.Item, error) {
} }
u := fmt.Sprintf("%s/sync?ks=%s", c.baseURL, strings.Join(ksStr, ",")) u := fmt.Sprintf("%s/sync?ks=%s", c.baseURL, strings.Join(ksStr, ","))
if !ts.IsZero() { if !ts.IsZero() {
u = fmt.Sprintf("%s&ts=", url.QueryEscape(ts.Format(time.RFC3339))) u = fmt.Sprintf("%s&ts=%s", u, url.QueryEscape(ts.Format(time.RFC3339)))
} }
req, err := http.NewRequest(http.MethodGet, u, nil) req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil { if err != nil {