go.ligato.io/vpp-agent/v3@v3.5.0/plugins/kvscheduler/api/txn_options.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package api 16 17 import ( 18 "context" 19 "encoding/json" 20 "time" 21 ) 22 23 type schedulerCtxKey int 24 25 const ( 26 // resyncCtxKey is a key under which *resync* txn option is stored 27 // into the context. 28 resyncCtxKey schedulerCtxKey = iota 29 30 // nonBlockingTxnCtxKey is a key under which *non-blocking* txn option is 31 // stored into the context. 32 nonBlockingTxnCtxKey 33 34 // retryCtxKey is a key under which *retry* txn option is stored into 35 // the context. 36 retryCtxKey 37 38 // revertCtxKey is a key under which *revert* txn option is stored into 39 // the context. 40 revertCtxKey 41 42 // txnDescriptionCtxKey is a key under which transaction description is stored 43 // into the context. 44 txnDescriptionCtxKey 45 46 // txnSimulationCtxKey is a key under which option enabling txn simulation 47 // is stored into the context. 48 txnSimulationCtxKey 49 ) 50 51 // modifiable default parameters for the *retry* txn option 52 var ( 53 // DefaultRetryPeriod delays first retry by one second. 54 DefaultRetryPeriod = time.Second 55 56 // DefaultRetryMaxCount limits the number of retries to 3 attempts at maximum. 57 DefaultRetryMaxCount = 3 58 59 // DefaultRetryBackoff enables exponential back-off for retry delay. 60 DefaultRetryBackoff = true 61 ) 62 63 /* Full-Resync */ 64 65 // resyncOpt represents the *resync* transaction option. 66 type resyncOpt struct { 67 resyncType ResyncType 68 verboseSBRefresh bool 69 } 70 71 // ResyncType is one of: Upstream, Downstream, Full. 72 type ResyncType int 73 74 const ( 75 // NotResync is the default value for ResyncType, used when resync is actually 76 // not enabled. 77 NotResync ResyncType = iota 78 79 // FullResync resynchronizes the agent with both SB and NB. 80 FullResync 81 82 // UpstreamResync resynchronizes the agent with NB. 83 // It can be used by NB in situations when fully re-calculating the desired 84 // state is far easier or more efficient that to determine the minimal difference 85 // that needs to be applied to reach that state. 86 // The agent's view of SB is not refreshed, instead it is expected to be up-to-date. 87 UpstreamResync 88 89 // DownstreamResync resynchronizes the agent with SB. 90 // In this case it is assumed that the state required by NB is up-to-date 91 // (transaction should be empty) and only the agent's view of SB is refreshed 92 // and any discrepancies are acted upon. 93 DownstreamResync 94 ) 95 96 func (t ResyncType) String() string { 97 switch t { 98 case NotResync: 99 return "NotResync" 100 case FullResync: 101 return "FullResync" 102 case UpstreamResync: 103 return "UpstreamResync" 104 case DownstreamResync: 105 return "DownstreamResync" 106 default: 107 return "UnknownResync" 108 } 109 } 110 111 var resyncType_value = map[string]int{ 112 "NotResync": int(NotResync), 113 "FullResync": int(FullResync), 114 "UpstreamResync": int(UpstreamResync), 115 "DownstreamResync": int(DownstreamResync), 116 } 117 118 func (t ResyncType) MarshalJSON() ([]byte, error) { 119 return json.Marshal(t.String()) 120 } 121 122 func (t *ResyncType) UnmarshalJSON(b []byte) error { 123 if b[0] == '"' { 124 var s string 125 if err := json.Unmarshal(b, &s); err != nil { 126 return err 127 } 128 if v, ok := resyncType_value[s]; ok { 129 *t = ResyncType(v) 130 } else { 131 *t = NotResync 132 } 133 } else { 134 var n int 135 if err := json.Unmarshal(b, &n); err != nil { 136 return err 137 } 138 *t = ResyncType(n) 139 } 140 return nil 141 } 142 143 // WithResync prepares context for transaction that, based on the resync type, 144 // will trigger resync between the configuration states of NB, the agent and SB. 145 // For DownstreamResync the transaction should be empty, otherwise it should 146 // carry non-NIL values - existing NB values not included in the transaction 147 // are automatically removed. 148 // When <verboseSBRefresh> is enabled, the refreshed state of SB will be printed 149 // into stdout. The argument is irrelevant for UpstreamResync, where SB state is 150 // not refreshed. 151 func WithResync(ctx context.Context, resyncType ResyncType, verboseSBRefresh bool) context.Context { 152 return context.WithValue(ctx, resyncCtxKey, &resyncOpt{ 153 resyncType: resyncType, 154 verboseSBRefresh: verboseSBRefresh, 155 }) 156 } 157 158 // IsResync returns true if the transaction context is configured to trigger resync. 159 func IsResync(ctx context.Context) (resyncType ResyncType, verboseSBRefresh bool) { 160 resyncArgs, isResync := ctx.Value(resyncCtxKey).(*resyncOpt) 161 if !isResync { 162 return NotResync, false 163 } 164 return resyncArgs.resyncType, resyncArgs.verboseSBRefresh 165 } 166 167 /* Non-blocking Txn */ 168 169 // nonBlockingTxnOpt represents the *non-blocking* transaction option. 170 type nonBlockingTxnOpt struct { 171 // no attributes 172 } 173 174 // WithoutBlocking prepares context for transaction that should be scheduled 175 // for execution without blocking the caller of the Commit() method. 176 // By default, commit is blocking. 177 func WithoutBlocking(ctx context.Context) context.Context { 178 return context.WithValue(ctx, nonBlockingTxnCtxKey, &nonBlockingTxnOpt{}) 179 } 180 181 // IsNonBlockingTxn returns true if transaction context is configured for 182 // non-blocking Commit. 183 func IsNonBlockingTxn(ctx context.Context) bool { 184 _, nonBlocking := ctx.Value(nonBlockingTxnCtxKey).(*nonBlockingTxnOpt) 185 return nonBlocking 186 } 187 188 /* Retry */ 189 190 // RetryOpt represents the *retry* transaction option. 191 type RetryOpt struct { 192 Period time.Duration 193 MaxCount int 194 ExpBackoff bool 195 } 196 197 // WithRetry prepares context for transaction for which the scheduler will retry 198 // any (retriable) failed operations after given <period>. If <expBackoff> 199 // is enabled, every failed retry will double the next delay. Non-zero <maxCount> 200 // limits the maximum number of retries the scheduler will execute. 201 // Can be combined with revert - even failed revert operations will be re-tried. 202 // By default, the scheduler will not automatically retry failed operations. 203 func WithRetry(ctx context.Context, period time.Duration, maxCount int, expBackoff bool) context.Context { 204 return context.WithValue(ctx, retryCtxKey, &RetryOpt{ 205 Period: period, 206 MaxCount: maxCount, 207 ExpBackoff: expBackoff, 208 }) 209 } 210 211 // WithRetryDefault is a specialization of WithRetry, where retry parameters 212 // are set to default values. 213 func WithRetryDefault(ctx context.Context) context.Context { 214 return context.WithValue(ctx, retryCtxKey, &RetryOpt{ 215 Period: DefaultRetryPeriod, 216 MaxCount: DefaultRetryMaxCount, 217 ExpBackoff: DefaultRetryBackoff, 218 }) 219 } 220 221 // WithRetryMaxCount is a specialization of WithRetry, where <period> and <expBackoff> 222 // are set to default values and the maximum number of retries can be customized. 223 func WithRetryMaxCount(ctx context.Context, maxCount int) context.Context { 224 return context.WithValue(ctx, retryCtxKey, &RetryOpt{ 225 Period: DefaultRetryPeriod, 226 MaxCount: maxCount, 227 ExpBackoff: DefaultRetryBackoff, 228 }) 229 } 230 231 // IsWithRetry returns true if transaction context is configured to allow retry, 232 // including the option parameters, or nil if retry is not enabled. 233 func IsWithRetry(ctx context.Context) (retryArgs *RetryOpt, withRetry bool) { 234 retryArgs, withRetry = ctx.Value(retryCtxKey).(*RetryOpt) 235 return 236 } 237 238 /* Revert */ 239 240 // revertOpt represents the *revert* transaction option. 241 type revertOpt struct { 242 // no attributes 243 } 244 245 // WithRevert prepares context for transaction that will be reverted if any 246 // of its operations fails. 247 // By default, the scheduler executes transactions in a best-effort mode - even 248 // in the case of an error it will keep the effects of successful operations. 249 func WithRevert(ctx context.Context) context.Context { 250 return context.WithValue(ctx, revertCtxKey, &revertOpt{}) 251 } 252 253 // IsWithRevert returns true if the transaction context is configured 254 // to revert transaction if any of its operations fails. 255 func IsWithRevert(ctx context.Context) bool { 256 _, isWithRevert := ctx.Value(revertCtxKey).(*revertOpt) 257 return isWithRevert 258 } 259 260 /* Txn Description */ 261 262 // txnDescriptionOpt represents the *txn-description* transaction option. 263 type txnDescriptionOpt struct { 264 description string 265 } 266 267 // WithDescription prepares context for transaction that will have description 268 // provided. 269 // By default, transactions are without description. 270 func WithDescription(ctx context.Context, description string) context.Context { 271 return context.WithValue(ctx, txnDescriptionCtxKey, &txnDescriptionOpt{description: description}) 272 } 273 274 // IsWithDescription returns true if the transaction context is configured 275 // to include transaction description. 276 func IsWithDescription(ctx context.Context) (description string, withDescription bool) { 277 descriptionOpt, withDescription := ctx.Value(txnDescriptionCtxKey).(*txnDescriptionOpt) 278 if !withDescription { 279 return "", false 280 } 281 return descriptionOpt.description, true 282 } 283 284 /* Txn Simulation */ 285 286 // txnSimulationOpt represents the *txn-simulation* transaction option. 287 type txnSimulationOpt struct { 288 // no attributes 289 } 290 291 // WithSimulation enables simulation of txn operations, which is triggered before 292 // execution to obtain the sequence of intended operations without actually 293 // calling any CRUD operations and assuming no failures. 294 // By default, simulation is disabled. 295 func WithSimulation(ctx context.Context) context.Context { 296 return context.WithValue(ctx, txnSimulationCtxKey, &txnSimulationOpt{}) 297 } 298 299 // IsWithSimulation returns true if transaction context is configured to enable 300 // pre-execution simulation. 301 func IsWithSimulation(ctx context.Context) bool { 302 _, withSimulation := ctx.Value(txnSimulationCtxKey).(*txnSimulationOpt) 303 return withSimulation 304 }