github.com/cilium/statedb@v0.3.2/reconciler/example/ops.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package main 5 6 import ( 7 "context" 8 "errors" 9 "iter" 10 "log/slog" 11 "os" 12 "path" 13 14 "github.com/cilium/hive/cell" 15 "github.com/cilium/statedb" 16 "github.com/cilium/statedb/reconciler" 17 ) 18 19 // MemoOps writes [Memo]s to disk. 20 // Implements the Reconciler.Operations[*Memo] API. 21 type MemoOps struct { 22 log *slog.Logger 23 directory string 24 } 25 26 // NewMemoOps creates the memo operations. 27 func NewMemoOps(lc cell.Lifecycle, log *slog.Logger, cfg Config) reconciler.Operations[*Memo] { 28 ops := &MemoOps{directory: cfg.Directory, log: log} 29 30 // Register the Start and Stop methods to be called when the application 31 // starts and stops respectively. The start hook will create the 32 // memo directory. 33 lc.Append(ops) 34 return ops 35 } 36 37 // Delete a memo. 38 func (ops *MemoOps) Delete(ctx context.Context, txn statedb.ReadTxn, memo *Memo) error { 39 filename := path.Join(ops.directory, memo.Name) 40 err := os.Remove(filename) 41 ops.log.Info("Delete", "filename", filename, "error", err) 42 return err 43 } 44 45 // Prune unexpected memos. 46 func (ops *MemoOps) Prune(ctx context.Context, txn statedb.ReadTxn, objects iter.Seq2[*Memo, statedb.Revision]) error { 47 expected := map[string]struct{}{} 48 49 for memo := range objects { 50 expected[memo.Name] = struct{}{} 51 } 52 53 // Find unexpected files 54 unexpected := map[string]struct{}{} 55 if entries, err := os.ReadDir(ops.directory); err != nil { 56 return err 57 } else { 58 for _, entry := range entries { 59 if _, ok := expected[entry.Name()]; !ok { 60 unexpected[entry.Name()] = struct{}{} 61 } 62 } 63 } 64 65 // ... and remove them. 66 var errs []error 67 for name := range unexpected { 68 filename := path.Join(ops.directory, name) 69 err := os.Remove(filename) 70 ops.log.Info("Prune", "filename", filename, "error", err) 71 if err != nil { 72 errs = append(errs, err) 73 } 74 } 75 return errors.Join(errs...) 76 } 77 78 // Update a memo. 79 func (ops *MemoOps) Update(ctx context.Context, txn statedb.ReadTxn, memo *Memo) error { 80 filename := path.Join(ops.directory, memo.Name) 81 err := os.WriteFile(filename, []byte(memo.Content), 0644) 82 ops.log.Info("Update", "filename", filename, "error", err) 83 return err 84 } 85 86 var _ reconciler.Operations[*Memo] = &MemoOps{} 87 88 func (ops *MemoOps) Start(cell.HookContext) error { 89 return os.MkdirAll(ops.directory, 0755) 90 } 91 92 func (*MemoOps) Stop(cell.HookContext) error { 93 return nil 94 } 95 96 var _ cell.HookInterface = &MemoOps{}