github.com/cilium/statedb@v0.3.2/reconciler/config.go (about) 1 package reconciler 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/cilium/statedb" 8 "golang.org/x/time/rate" 9 ) 10 11 func defaultOptions() options { 12 return options{ 13 Metrics: nil, // use DefaultMetrics 14 15 // Refresh objects every 30 minutes at a rate of 100 per second. 16 RefreshInterval: 30 * time.Minute, 17 RefreshRateLimiter: rate.NewLimiter(100.0, 1), 18 19 // Prune when initialized and then once an hour. 20 PruneInterval: time.Hour, 21 22 // Retry failed operations with exponential backoff from 100ms to 1min. 23 RetryBackoffMinDuration: 100 * time.Millisecond, 24 RetryBackoffMaxDuration: time.Minute, 25 26 // Reconcile 100 rounds per second * 1000 yielding maximum rate of 27 // 100k objects per second. 28 IncrementalRoundSize: 1000, 29 RateLimiter: rate.NewLimiter(1000.0, 1), 30 } 31 } 32 33 type options struct { 34 // Metrics to use with this reconciler. The metrics capture the duration 35 // of operations during incremental and full reconcilation and the errors 36 // that occur during either. 37 // 38 // If nil, then the default metrics are used via Params. 39 // A simple implementation of metrics based on the expvar package come 40 // with the reconciler and a custom one can be used by implementing the 41 // Metrics interface. 42 Metrics Metrics 43 44 // RefreshInterval is the interval at which the objects are refreshed, 45 // e.g. how often Update() should be called to refresh an object even 46 // when it has not changed. This is implemented by periodically setting 47 // all objects that have not been updated for [RefreshInterval] or longer 48 // as pending. 49 // If set to 0 refreshing is disabled. 50 RefreshInterval time.Duration 51 52 // RefreshRateLimiter is optional and if set is used to limit the rate at 53 // which objects are marked for refresh. If not provided a default rate 54 // limiter is used. 55 RefreshRateLimiter *rate.Limiter 56 57 // PruneInterval is the interval at which Prune() is called to prune 58 // unexpected objects in the target system. If set to 0 pruning is disabled. 59 // Prune() will not be called before the table has been fully initialized 60 // (Initialized() returns true). 61 // A single Prune() can be forced via the [Reconciler.Prune] method regardless 62 // of this value (0 or not). 63 PruneInterval time.Duration 64 65 // RetryBackoffMinDuration is the minimum amount of time to wait before 66 // retrying a failed Update() or Delete() operation on an object. 67 // The retry wait time for an object will increase exponentially on 68 // subsequent failures until RetryBackoffMaxDuration is reached. 69 RetryBackoffMinDuration time.Duration 70 71 // RetryBackoffMaxDuration is the maximum amount of time to wait before 72 // retrying. 73 RetryBackoffMaxDuration time.Duration 74 75 // IncrementalRoundSize is the maximum number objects to reconcile during 76 // incremental reconciliation before updating status and refreshing the 77 // statedb snapshot. This should be tuned based on the cost of each operation 78 // and the rate of expected changes so that health and per-object status 79 // updates are not delayed too much. If in doubt, use a value between 100-1000. 80 IncrementalRoundSize int 81 82 // RateLimiter is optional and if set will use the limiter to wait between 83 // reconciliation rounds. This allows trading latency with throughput by 84 // waiting longer to collect a batch of objects to reconcile. 85 RateLimiter *rate.Limiter 86 } 87 88 type config[Obj any] struct { 89 // Table to reconcile. Mandatory. 90 Table statedb.RWTable[Obj] 91 92 // GetObjectStatus returns the reconciliation status for the object. 93 // Mandatory. 94 GetObjectStatus func(Obj) Status 95 96 // SetObjectStatus sets the reconciliation status for the object. 97 // This is called with a copy of the object returned by CloneObject. 98 // Mandatory. 99 SetObjectStatus func(Obj, Status) Obj 100 101 // CloneObject returns a shallow copy of the object. This is used to 102 // make it possible for the reconciliation operations to mutate 103 // the object (to for example provide additional information that the 104 // reconciliation produces) and to be able to set the reconciliation 105 // status after the reconciliation. 106 // Mandatory. 107 CloneObject func(Obj) Obj 108 109 // Operations defines how an object is reconciled. Mandatory. 110 Operations Operations[Obj] 111 112 // BatchOperations is optional and if provided these are used instead of 113 // the single-object operations. 114 BatchOperations BatchOperations[Obj] 115 116 options 117 } 118 119 func (cfg config[Obj]) validate() error { 120 if cfg.Table == nil { 121 return fmt.Errorf("%T.Table cannot be nil", cfg) 122 } 123 if cfg.GetObjectStatus == nil { 124 return fmt.Errorf("%T.GetObjectStatus cannot be nil", cfg) 125 } 126 if cfg.SetObjectStatus == nil { 127 return fmt.Errorf("%T.SetObjectStatus cannot be nil", cfg) 128 } 129 if cfg.CloneObject == nil { 130 return fmt.Errorf("%T.CloneObject cannot be nil", cfg) 131 } 132 if cfg.IncrementalRoundSize <= 0 { 133 return fmt.Errorf("%T.IncrementalBatchSize needs to be >0", cfg) 134 } 135 if cfg.RefreshInterval < 0 { 136 return fmt.Errorf("%T.RefreshInterval must be >=0", cfg) 137 } 138 if cfg.PruneInterval < 0 { 139 return fmt.Errorf("%T.PruneInterval must be >=0", cfg) 140 } 141 if cfg.RetryBackoffMaxDuration <= 0 { 142 return fmt.Errorf("%T.RetryBackoffMaxDuration must be >0", cfg) 143 } 144 if cfg.RetryBackoffMinDuration <= 0 { 145 return fmt.Errorf("%T.RetryBackoffMinDuration must be >0", cfg) 146 } 147 if cfg.Operations == nil { 148 return fmt.Errorf("%T.Operations must be defined", cfg) 149 } 150 return nil 151 }