@@ -89,10 +89,10 @@ func (d *hookData) send(newHash string) {
89
89
}
90
90
91
91
// NewHookRunner returns a new HookRunner.
92
- func NewHookRunner (hook Hook , backoff time.Duration , data * hookData , log logintf , oneTime bool ) * HookRunner {
93
- hr := & HookRunner {hook : hook , backoff : backoff , data : data , log : log }
94
- if oneTime {
95
- hr .oneTimeResult = make (chan bool , 1 )
92
+ func NewHookRunner (hook Hook , backoff time.Duration , data * hookData , log logintf , oneTime bool , async bool ) * HookRunner {
93
+ hr := & HookRunner {hook : hook , backoff : backoff , data : data , log : log , oneTime : oneTime , async : async }
94
+ if oneTime || ! async {
95
+ hr .result = make (chan bool , 1 )
96
96
}
97
97
return hr
98
98
}
@@ -107,9 +107,13 @@ type HookRunner struct {
107
107
data * hookData
108
108
// Logger
109
109
log logintf
110
- // Used to send a status result when running in one-time mode.
110
+ // Used to send a status result when running in one-time or non-async mode.
111
111
// Should be initialised to a buffered channel of size 1.
112
- oneTimeResult chan bool
112
+ result chan bool
113
+ // Bool for whether this is a one-time hook or not.
114
+ oneTime bool
115
+ // Bool for whether this is an async hook or not.
116
+ async bool
113
117
}
114
118
115
119
// Just the logr methods we need in this package.
@@ -120,8 +124,17 @@ type logintf interface {
120
124
}
121
125
122
126
// Send sends hash to hookdata.
123
- func (r * HookRunner ) Send (hash string ) {
127
+ func (r * HookRunner ) Send (hash string ) error {
124
128
r .data .send (hash )
129
+ if ! r .async {
130
+ r .log .V (1 ).Info ("waiting for completion" , "hash" , hash , "name" , r .hook .Name ())
131
+ err := r .WaitForCompletion ()
132
+ r .log .V (1 ).Info ("hook completed" , "hash" , hash , "err" , err , "name" , r .hook .Name ())
133
+ if err != nil {
134
+ return err
135
+ }
136
+ }
137
+ return nil
125
138
}
126
139
127
140
// Run waits for trigger events from the channel, and run hook when triggered.
@@ -144,45 +157,49 @@ func (r *HookRunner) Run(ctx context.Context) {
144
157
r .log .Error (err , "hook failed" , "hash" , hash , "retry" , r .backoff )
145
158
updateHookRunCountMetric (r .hook .Name (), "error" )
146
159
// don't want to sleep unnecessarily terminating anyways
147
- r .sendOneTimeResultAndTerminate (false )
160
+ r .sendResult (false )
148
161
time .Sleep (r .backoff )
149
162
} else {
150
163
updateHookRunCountMetric (r .hook .Name (), "success" )
151
164
lastHash = hash
152
- r .sendOneTimeResultAndTerminate (true )
165
+ r .sendResult (true )
153
166
break
154
167
}
155
168
}
156
169
}
157
170
}
158
171
159
- // If oneTimeResult is nil, does nothing. Otherwise, forwards the caller
160
- // provided success status (as a boolean) of HookRunner to receivers of
161
- // oneTimeResult, closes said chanel, and terminates this goroutine.
162
- // Using this function to write to oneTimeResult ensures it is only ever
163
- // written to once.
164
- func (r * HookRunner ) sendOneTimeResultAndTerminate (completedSuccessfully bool ) {
165
- if r .oneTimeResult != nil {
166
- r .oneTimeResult <- completedSuccessfully
167
- close (r .oneTimeResult )
172
+ func (r * HookRunner ) sendResult (completedSuccessfully bool ) {
173
+ // if onetime is true, we send the result then exit
174
+ if r .oneTime {
175
+ r .result <- completedSuccessfully
176
+ close (r .result )
168
177
runtime .Goexit ()
178
+ } else if ! r .async {
179
+ // if onetime is false, and we've set non-async we send but don't exit.
180
+ r .result <- completedSuccessfully
169
181
}
182
+ // if neither oneTime nor !async, we do nothing here.
170
183
}
171
184
172
185
// WaitForCompletion waits for HookRunner to send completion message to
173
186
// calling thread and returns either true if HookRunner executed successfully
174
187
// and some error otherwise.
175
- // Assumes that r.oneTimeResult is not nil, but if it is, returns an error.
188
+ // Assumes that either r.oneTime or !r.async, otherwise returns an error.
176
189
func (r * HookRunner ) WaitForCompletion () error {
177
190
// Make sure function should be called
178
- if r .oneTimeResult == nil {
191
+ if r .result == nil {
179
192
return fmt .Errorf ("HookRunner.WaitForCompletion called on async runner" )
180
193
}
181
194
182
- // Perform wait on HookRunner
183
- hookRunnerFinishedSuccessfully := <- r .oneTimeResult
184
- if ! hookRunnerFinishedSuccessfully {
185
- return fmt .Errorf ("hook completed with error" )
195
+ // If oneTimeResult is not nil, we wait for its result.
196
+ if r .result != nil {
197
+ hookRunnerFinishedSuccessfully := <- r .result
198
+ r .log .V (1 ).Info ("hook completed" , "success" , hookRunnerFinishedSuccessfully ,
199
+ "oneTime" , r .oneTime , "async" , r .async , "name" , r .hook .Name ())
200
+ if ! hookRunnerFinishedSuccessfully {
201
+ return fmt .Errorf ("hook completed with error" )
202
+ }
186
203
}
187
204
188
205
return nil
0 commit comments