package main import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "syscall" ) type store struct { path string lock *os.File Watches map[string]*watch `json:"watches"` } func openStore(path string) (*store, error) { if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { return nil, err } lock, err := os.OpenFile(path+".lock", os.O_CREATE|os.O_RDWR, 0600) if err != nil { return nil, err } if err := syscall.Flock(int(lock.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil { return nil, fmt.Errorf("checkpoint is already in use: %w", errors.Join(err, lock.Close())) } s := &store{path: path, lock: lock, Watches: make(map[string]*watch)} data, err := os.ReadFile(path) if errors.Is(err, os.ErrNotExist) { return s, nil } if err == nil { err = json.Unmarshal(data, s) } if err == nil && s.Watches == nil { err = errors.New("checkpoint has no watches") } if err != nil { return nil, errors.Join(err, s.close()) } for _, w := range s.Watches { if w.Known && w.Goal != nil && w.Goal.Status.waiting() && w.Turn.Status == "failed" { if w.Hold != nil && w.Goal.Status == "usageLimited" && w.Hold.Status == "usageLimited" { w.Hold = nil } if w.Hold == nil { w.Armed = true } } } return s, nil } func (s *store) close() error { return s.lock.Close() } func (s *store) save() error { data, err := json.Marshal(s) if err != nil { return err } f, err := os.CreateTemp(filepath.Dir(s.path), ".state-*") if err != nil { return err } defer func() { _ = os.Remove(f.Name()) }() if _, err = f.Write(data); err == nil { err = f.Sync() } closeErr := f.Close() if err != nil { return err } if closeErr != nil { return closeErr } return os.Rename(f.Name(), s.path) } func (s *store) watch(id string) *watch { w := s.Watches[id] if w == nil { w = &watch{} s.Watches[id] = w } return w }