From 41a27a4799cfd5b52186f126e6d5d15e3f251fc0 Mon Sep 17 00:00:00 2001 From: Erik Winter Date: Tue, 24 Aug 2021 07:26:58 +0200 Subject: [PATCH] keep relevant local updates --- internal/storage/memory.go | 3 ++ internal/storage/sqlite.go | 62 +++++++++++++++++++++++++++----------- internal/task/localtask.go | 4 +++ 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/internal/storage/memory.go b/internal/storage/memory.go index ad3e6ea..a6382b4 100644 --- a/internal/storage/memory.go +++ b/internal/storage/memory.go @@ -12,6 +12,9 @@ type localData struct { } // Memory is an in memory implementation of LocalRepository +// +// It is meant for testing and does not make an attempt to +// keep local state between consecutive calls to SetTasks() type Memory struct { tasks []*task.Task latestSync time.Time diff --git a/internal/storage/sqlite.go b/internal/storage/sqlite.go index b6fc48a..4ec28e3 100644 --- a/internal/storage/sqlite.go +++ b/internal/storage/sqlite.go @@ -76,7 +76,13 @@ func (s *Sqlite) SetTasks(tasks []*task.Task) error { return fmt.Errorf("%w: %v", ErrSqliteFailure, err) } - localIdMap := map[string]int{} + type localTaskInfo struct { + TaskId string + TaskVersion int + LocalId int + LocalUpdate task.LocalUpdate + } + localIdMap := map[string]localTaskInfo{} for _, t := range tasks { var recurStr string if t.Recur != nil { @@ -92,11 +98,17 @@ VALUES return fmt.Errorf("%w: %v", ErrSqliteFailure, err) } - localIdMap[t.Id] = 0 + localIdMap[t.Id] = localTaskInfo{ + TaskId: t.Id, + TaskVersion: t.Version, + LocalId: 0, + LocalUpdate: task.LocalUpdate{}, + } } - // set local_ids - rows, err := s.db.Query(`SELECT id, local_id FROM local_task`) + // set local_ids and local_updates: + // 1 - find existing + rows, err := s.db.Query(`SELECT id, local_id, local_update FROM local_task`) if err != nil { return fmt.Errorf("%w: %v", ErrSqliteFailure, err) } @@ -104,39 +116,55 @@ VALUES for rows.Next() { var id string var localId int - if err := rows.Scan(&id, &localId); err != nil { + var localUpdate task.LocalUpdate + if err := rows.Scan(&id, &localId, &localUpdate); err != nil { return fmt.Errorf("%w: %v", ErrSqliteFailure, err) } - if _, ok := localIdMap[id]; ok { - localIdMap[id] = localId + if oldInfo, ok := localIdMap[id]; ok { + newInfo := localTaskInfo{ + TaskId: oldInfo.TaskId, + TaskVersion: oldInfo.TaskVersion, + LocalId: localId, + LocalUpdate: localUpdate, + } + localIdMap[id] = newInfo } } + // 2 - remove old values if _, err := s.db.Exec(`DELETE FROM local_task`); err != nil { return fmt.Errorf("%w: %v", ErrSqliteFailure, err) } + // 3 - figure out new values var used []int - for _, localId := range localIdMap { - if localId != 0 { - used = append(used, localId) + for _, info := range localIdMap { + if info.LocalId != 0 { + used = append(used, info.LocalId) } } - - for id, localId := range localIdMap { - if localId == 0 { + for id, info := range localIdMap { + newInfo := info + // find new local_id when needed + if info.LocalId == 0 { newLocalId := NextLocalId(used) - localIdMap[id] = newLocalId used = append(used, newLocalId) + newInfo.LocalId = newLocalId } + // remove local_update when outdated + if info.LocalUpdate.ForVersion < info.TaskVersion { + newInfo.LocalUpdate = task.LocalUpdate{} + } + localIdMap[id] = newInfo } - for id, localId := range localIdMap { + // 4 - store new values + for id, info := range localIdMap { if _, err := s.db.Exec(` INSERT INTO local_task -(id, local_id) +(id, local_id, local_update) VALUES -(?, ?)`, id, localId); err != nil { +(?, ?, ?)`, id, info.LocalId, info.LocalUpdate); err != nil { return fmt.Errorf("%w: %v", ErrSqliteFailure, err) } } diff --git a/internal/task/localtask.go b/internal/task/localtask.go index c40d3fd..543327f 100644 --- a/internal/task/localtask.go +++ b/internal/task/localtask.go @@ -13,6 +13,10 @@ type LocalTask struct { LocalUpdate *LocalUpdate } +func (lt *LocalTask) HasUpdate() bool { + return lt.LocalUpdate.ForVersion != 0 +} + func (lt *LocalTask) AddUpdate(update *LocalUpdate) { if lt.LocalUpdate == nil { lt.LocalUpdate = &LocalUpdate{}