fix: break sync feedback loop, respect timestamps, surface errors
- Add migration v2: source column on change_log to distinguish local vs sync-originated entries, preventing the echo loop where synced tasks get re-pushed as local changes - PushChanges handler now skips save when server version is newer - Client PushChanges/pushQueuedChanges collect and report marshal errors instead of silently dropping them - De-duplicate getLocalChanges/getLastSyncTime into exported sync package functions - Fix logConflict winner detection via pointer identity instead of fragile UUID+timestamp comparison - Fix sync down to actually parse, save, and tag-sync pulled changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -307,6 +307,13 @@ func runMigrations() error {
|
||||
END;
|
||||
`,
|
||||
},
|
||||
{
|
||||
version: 2,
|
||||
sql: `
|
||||
ALTER TABLE change_log ADD COLUMN source TEXT NOT NULL DEFAULT 'local';
|
||||
CREATE INDEX idx_change_log_source ON change_log(source);
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
// Apply pending migrations
|
||||
@@ -409,3 +416,24 @@ func SetChangeLogRetentionDays(days int) error {
|
||||
_, err := db.Exec("INSERT OR REPLACE INTO sync_config (key, value) VALUES ('change_log_retention_days', ?)", days)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarkChangeLogAsSync marks the most recent change_log entry for a task UUID
|
||||
// as originating from sync (not local), preventing the feedback loop where
|
||||
// synced changes get re-pushed as local changes.
|
||||
func MarkChangeLogAsSync(taskUUID string) error {
|
||||
db := GetDB()
|
||||
if db == nil {
|
||||
return fmt.Errorf("database not initialized")
|
||||
}
|
||||
|
||||
_, err := db.Exec(`
|
||||
UPDATE change_log SET source = 'sync'
|
||||
WHERE id = (
|
||||
SELECT id FROM change_log
|
||||
WHERE task_uuid = ?
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
`, taskUUID)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user