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