package sync import ( "encoding/json" "fmt" "os" "path/filepath" "git.jnss.me/joakim/opal/internal/engine" "github.com/google/uuid" ) // QueuedChange represents a change waiting to be synced type QueuedChange struct { ID string `json:"id"` Timestamp int64 `json:"timestamp"` TaskUUID uuid.UUID `json:"task_uuid"` Type string `json:"type"` // create, update, delete Data json.RawMessage `json:"data"` } // Queue manages offline changes type Queue struct { filepath string changes []QueuedChange } // NewQueue creates a new queue instance func NewQueue() (*Queue, error) { configDir, err := engine.GetConfigDir() if err != nil { return nil, err } queuePath := filepath.Join(configDir, "sync_queue.json") q := &Queue{filepath: queuePath} if err := q.load(); err != nil { // If file doesn't exist, start with empty queue if !os.IsNotExist(err) { return nil, err } q.changes = []QueuedChange{} } return q, nil } // Add adds a change to the queue func (q *Queue) Add(change QueuedChange) error { q.changes = append(q.changes, change) return q.save() } // GetPending returns all pending changes func (q *Queue) GetPending() []QueuedChange { return q.changes } // Clear removes all changes from the queue func (q *Queue) Clear() error { q.changes = []QueuedChange{} return q.save() } // Size returns the number of pending changes func (q *Queue) Size() int { return len(q.changes) } // load reads the queue from disk func (q *Queue) load() error { data, err := os.ReadFile(q.filepath) if err != nil { return err } return json.Unmarshal(data, &q.changes) } // save writes the queue to disk func (q *Queue) save() error { data, err := json.MarshalIndent(q.changes, "", " ") if err != nil { return err } return os.WriteFile(q.filepath, data, 0644) } // QueueLocalChanges adds local task changes to the queue func QueueLocalChanges(tasks []*engine.Task) error { queue, err := NewQueue() if err != nil { return fmt.Errorf("failed to create queue: %w", err) } for _, task := range tasks { taskData, err := json.Marshal(task) if err != nil { continue } change := QueuedChange{ ID: uuid.New().String(), Timestamp: task.Modified.Unix(), TaskUUID: task.UUID, Type: "update", Data: taskData, } if err := queue.Add(change); err != nil { return fmt.Errorf("failed to queue change: %w", err) } } return nil }