@@ -34,7 +34,8 @@ const refreshBuffer = 4 * time.Minute
34
34
var (
35
35
// Instance URI is in the format:
36
36
// '/projects/<PROJECT>/locations/<REGION>/clusters/<CLUSTER>/instances/<INSTANCE>'
37
- // Additionally, we have to support legacy "domain-scoped" projects (e.g. "google.com:PROJECT")
37
+ // Additionally, we have to support legacy "domain-scoped" projects
38
+ // (e.g. "google.com:PROJECT")
38
39
instURIRegex = regexp .MustCompile ("projects/([^:]+(:[^:]+)?)/locations/([^:]+)/clusters/([^:]+)/instances/([^:]+)" )
39
40
)
40
41
@@ -71,8 +72,9 @@ func parseInstURI(cn string) (instanceURI, error) {
71
72
return c , nil
72
73
}
73
74
74
- // refreshOperation is a pending result of a refresh operation of data used to connect securely. It should
75
- // only be initialized by the Instance struct as part of a refresh cycle.
75
+ // refreshOperation is a pending result of a refresh operation of data used to
76
+ // connect securely. It should only be initialized by the Instance struct as
77
+ // part of a refresh cycle.
76
78
type refreshOperation struct {
77
79
result refreshResult
78
80
err error
@@ -83,24 +85,16 @@ type refreshOperation struct {
83
85
ready chan struct {}
84
86
}
85
87
86
- // Cancel prevents the instanceInfo from starting, if it hasn't already started. Returns true if timer
87
- // was stopped successfully, or false if it has already started.
88
- func (r * refreshOperation ) Cancel () bool {
88
+ // Cancel prevents the instanceInfo from starting, if it hasn't already
89
+ // started. Returns true if timer was stopped successfully, or false if it has
90
+ // already started.
91
+ func (r * refreshOperation ) cancel () bool {
89
92
return r .timer .Stop ()
90
93
}
91
94
92
- // Wait blocks until the refreshOperation attempt is completed.
93
- func (r * refreshOperation ) Wait (ctx context.Context ) error {
94
- select {
95
- case <- r .ready :
96
- return r .err
97
- case <- ctx .Done ():
98
- return ctx .Err ()
99
- }
100
- }
101
-
102
- // IsValid returns true if this result is complete, successful, and is still valid.
103
- func (r * refreshOperation ) IsValid () bool {
95
+ // IsValid returns true if this result is complete, successful, and is still
96
+ // valid.
97
+ func (r * refreshOperation ) isValid () bool {
104
98
// verify the result has finished running
105
99
select {
106
100
default :
@@ -126,15 +120,16 @@ type Instance struct {
126
120
r refresher
127
121
128
122
resultGuard sync.RWMutex
129
- // cur represents the current refreshOperation that will be used to create connections. If a valid complete
130
- // refreshOperation isn't available it's possible for cur to be equal to next.
123
+ // cur represents the current refreshOperation that will be used to
124
+ // create connections. If a valid complete refreshOperation isn't
125
+ // available it's possible for cur to be equal to next.
131
126
cur * refreshOperation
132
- // next represents a future or ongoing refreshOperation. Once complete, it will replace cur and schedule a
133
- // replacement to occur.
127
+ // next represents a future or ongoing refreshOperation. Once complete,
128
+ // it will replace cur and schedule a replacement to occur.
134
129
next * refreshOperation
135
130
136
- // ctx is the default ctx for refresh operations. Canceling it prevents new refresh
137
- // operations from being triggered.
131
+ // ctx is the default ctx for refresh operations. Canceling it prevents
132
+ // new refresh operations from being triggered.
138
133
ctx context.Context
139
134
cancel context.CancelFunc
140
135
}
@@ -165,8 +160,8 @@ func NewInstance(
165
160
ctx : ctx ,
166
161
cancel : cancel ,
167
162
}
168
- // For the initial refresh operation, set cur = next so that connection requests block
169
- // until the first refresh is complete.
163
+ // For the initial refresh operation, set cur = next so that connection
164
+ // requests block until the first refresh is complete.
170
165
i .resultGuard .Lock ()
171
166
i .cur = i .scheduleRefresh (0 )
172
167
i .next = i .cur
@@ -189,24 +184,32 @@ func (i *Instance) ConnectInfo(ctx context.Context) (string, *tls.Config, error)
189
184
return res .result .instanceIPAddr , res .result .conf , nil
190
185
}
191
186
192
- // ForceRefresh triggers an immediate refresh operation to be scheduled and used for future connection attempts.
187
+ // ForceRefresh triggers an immediate refresh operation to be scheduled and
188
+ // used for future connection attempts.
193
189
func (i * Instance ) ForceRefresh () {
194
190
i .resultGuard .Lock ()
195
191
defer i .resultGuard .Unlock ()
196
192
// If the next refresh hasn't started yet, we can cancel it and start an immediate one
197
- if i .next .Cancel () {
193
+ if i .next .cancel () {
198
194
i .next = i .scheduleRefresh (0 )
199
195
}
200
196
// block all sequential connection attempts on the next refresh result
201
197
i .cur = i .next
202
198
}
203
199
204
- // result returns the most recent refresh result (waiting for it to complete if necessary)
200
+ // result returns the most recent refresh result (waiting for it to complete if
201
+ // necessary)
205
202
func (i * Instance ) result (ctx context.Context ) (* refreshOperation , error ) {
206
203
i .resultGuard .RLock ()
207
204
res := i .cur
208
205
i .resultGuard .RUnlock ()
209
- err := res .Wait (ctx )
206
+ var err error
207
+ select {
208
+ case <- res .ready :
209
+ err = res .err
210
+ case <- ctx .Done ():
211
+ err = ctx .Err ()
212
+ }
210
213
if err != nil {
211
214
return nil , err
212
215
}
@@ -239,22 +242,26 @@ func (i *Instance) scheduleRefresh(d time.Duration) *refreshOperation {
239
242
res .result , res .err = i .r .performRefresh (i .ctx , i .instanceURI , i .key )
240
243
close (res .ready )
241
244
242
- // Once the refresh is complete, update "current" with working result and schedule a new refresh
245
+ // Once the refresh is complete, update "current" with working
246
+ // result and schedule a new refresh
243
247
i .resultGuard .Lock ()
244
248
defer i .resultGuard .Unlock ()
245
249
// if failed, scheduled the next refresh immediately
246
250
if res .err != nil {
247
251
i .next = i .scheduleRefresh (0 )
248
- // If the latest result is bad, avoid replacing the used result while it's
249
- // still valid and potentially able to provide successful connections.
250
- // TODO: This means that errors while the current result is still valid are
251
- // surpressed. We should try to surface errors in a more meaningful way.
252
- if ! i .cur .IsValid () {
252
+ // If the latest result is bad, avoid replacing the
253
+ // used result while it's still valid and potentially
254
+ // able to provide successful connections. TODO: This
255
+ // means that errors while the current result is still
256
+ // valid are surpressed. We should try to surface
257
+ // errors in a more meaningful way.
258
+ if ! i .cur .isValid () {
253
259
i .cur = res
254
260
}
255
261
return
256
262
}
257
- // Update the current results, and schedule the next refresh in the future
263
+ // Update the current results, and schedule the next refresh in
264
+ // the future
258
265
i .cur = res
259
266
select {
260
267
case <- i .ctx .Done ():
0 commit comments