diff --git a/dist/plan b/dist/plan index 2a6d5c3..994157b 100755 Binary files a/dist/plan and b/dist/plan differ diff --git a/plan/command/sync.go b/plan/command/sync.go index 742e431..0f7d13f 100644 --- a/plan/command/sync.go +++ b/plan/command/sync.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "time" "go-mod.ewintr.nl/planner/item" "go-mod.ewintr.nl/planner/plan/storage" @@ -39,17 +40,21 @@ func (s Sync) Do(deps Dependencies) (CommandResult, error) { } // get new/updated items - ts, err := deps.SyncRepo.LastUpdate() + oldTS, err := deps.SyncRepo.LastUpdate() if err != nil { 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 { return nil, fmt.Errorf("could not receive updates: %v", err) } updated := make([]item.Item, 0) + var newTS time.Time for _, ri := range recItems { + if ri.Updated.After(newTS) { + newTS = ri.Updated + } if ri.Deleted { 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) @@ -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 } diff --git a/plan/storage/memory/sync.go b/plan/storage/memory/sync.go index 42c6acb..4fc1006 100644 --- a/plan/storage/memory/sync.go +++ b/plan/storage/memory/sync.go @@ -52,6 +52,10 @@ func (r *Sync) DeleteAll() error { return nil } +func (r *Sync) SetLastUpdate(ts time.Time) error { + return nil +} + func (r *Sync) LastUpdate() (time.Time, error) { r.mutex.RLock() defer r.mutex.RUnlock() diff --git a/plan/storage/sqlite/migrations.go b/plan/storage/sqlite/migrations.go index 5a645f3..a786d46 100644 --- a/plan/storage/sqlite/migrations.go +++ b/plan/storage/sqlite/migrations.go @@ -39,6 +39,9 @@ var migrations = []string{ `INSERT INTO localids (id, local_id) SELECT id, local_id FROM localids_backup`, `DROP TABLE localids_backup`, + `ALTER TABLE items ADD COLUMN date 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")`, } diff --git a/plan/storage/sqlite/sync.go b/plan/storage/sqlite/sync.go index 5c72256..fdf5fba 100644 --- a/plan/storage/sqlite/sync.go +++ b/plan/storage/sqlite/sync.go @@ -84,20 +84,22 @@ func (s *SqliteSync) DeleteAll() error { 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) { - var updatedStr sql.NullString - err := s.db.QueryRow("SELECT MAX(updated) FROM items").Scan(&updatedStr) - if err != nil { + var tsStr string + if err := s.db.QueryRow("SELECT timestamp FROM syncupdate").Scan(&tsStr); err != nil { return time.Time{}, fmt.Errorf("%w: failed to get last update: %v", ErrSqliteFailure, err) } - - if !updatedStr.Valid { - return time.Time{}, nil // Return zero time if NULL or no rows - } - - lastUpdate, err := time.Parse(time.RFC3339, updatedStr.String) + ts, err := time.Parse(time.RFC3339, tsStr) 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 } diff --git a/plan/storage/storage.go b/plan/storage/storage.go index 914e98c..3cb7672 100644 --- a/plan/storage/storage.go +++ b/plan/storage/storage.go @@ -25,6 +25,7 @@ type Sync interface { FindAll() ([]item.Item, error) Store(i item.Item) error DeleteAll() error + SetLastUpdate(ts time.Time) error LastUpdate() (time.Time, error) } diff --git a/sync/client/http.go b/sync/client/http.go index 324c490..d7451ed 100644 --- a/sync/client/http.go +++ b/sync/client/http.go @@ -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, ",")) 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) if err != nil {