@@ -23,6 +23,7 @@ import (
23
23
"code.gitea.io/gitea/modules/graceful"
24
24
"code.gitea.io/gitea/modules/hostmatcher"
25
25
"code.gitea.io/gitea/modules/log"
26
+ "code.gitea.io/gitea/modules/process"
26
27
"code.gitea.io/gitea/modules/proxy"
27
28
"code.gitea.io/gitea/modules/queue"
28
29
"code.gitea.io/gitea/modules/setting"
@@ -43,7 +44,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
43
44
return
44
45
}
45
46
// There was a panic whilst delivering a hook...
46
- log .Error ("PANIC whilst trying to deliver webhook[%d] to %s Panic: %v\n Stacktrace: %s" , t .ID , w .URL , err , log .Stack (2 ))
47
+ log .Error ("PANIC whilst trying to deliver webhook task [%d] to webhook %s Panic: %v\n Stacktrace: %s" , t .ID , w .URL , err , log .Stack (2 ))
47
48
}()
48
49
49
50
t .IsDelivered = true
@@ -52,7 +53,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
52
53
53
54
switch w .HTTPMethod {
54
55
case "" :
55
- log .Info ("HTTP Method for webhook %d empty, setting to POST as default" , t . ID )
56
+ log .Info ("HTTP Method for webhook %s empty, setting to POST as default" , w . URL )
56
57
fallthrough
57
58
case http .MethodPost :
58
59
switch w .ContentType {
@@ -78,27 +79,27 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
78
79
case http .MethodGet :
79
80
u , err := url .Parse (w .URL )
80
81
if err != nil {
81
- return err
82
+ return fmt . Errorf ( "unable to deliver webhook task[%d] as cannot parse webhook url %s: %w" , t . ID , w . URL , err )
82
83
}
83
84
vals := u .Query ()
84
85
vals ["payload" ] = []string {t .PayloadContent }
85
86
u .RawQuery = vals .Encode ()
86
87
req , err = http .NewRequest ("GET" , u .String (), nil )
87
88
if err != nil {
88
- return err
89
+ return fmt . Errorf ( "unable to deliver webhook task[%d] as unable to create HTTP request for webhook url %s: %w" , t . ID , w . URL , err )
89
90
}
90
91
case http .MethodPut :
91
92
switch w .Type {
92
93
case webhook_model .MATRIX :
93
94
req , err = getMatrixHookRequest (w , t )
94
95
if err != nil {
95
- return err
96
+ return fmt . Errorf ( "unable to deliver webhook task[%d] as cannot create matrix request for webhook url %s: %w" , t . ID , w . URL , err )
96
97
}
97
98
default :
98
- return fmt .Errorf ("invalid http method for webhook: [%d] % v" , t .ID , w .HTTPMethod )
99
+ return fmt .Errorf ("invalid http method for webhook task [%d] in webhook %s: % v" , t .ID , w . URL , w .HTTPMethod )
99
100
}
100
101
default :
101
- return fmt .Errorf ("invalid http method for webhook: [%d] % v" , t .ID , w .HTTPMethod )
102
+ return fmt .Errorf ("invalid http method for webhook task [%d] in webhook %s: % v" , t .ID , w . URL , w .HTTPMethod )
102
103
}
103
104
104
105
var signatureSHA1 string
@@ -170,18 +171,32 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
170
171
}
171
172
}()
172
173
174
+ // OK We're now ready to attempt to deliver the task - we must double check that it
175
+ // has not been delivered in the meantime
176
+ marked , err := webhook_model .MarkTaskDelivered (ctx , t )
177
+ if err != nil {
178
+ log .Error ("MarkTaskDelivered[%d]: %v" , err )
179
+ return fmt .Errorf ("unable to mark task[%d] delivered in the db: %w" , t .ID , err )
180
+ }
181
+ if ! marked {
182
+ // This webhook task has already been delivered
183
+ log .Trace ("Webhook Task[%d] already delivered" , t .ID )
184
+ return nil
185
+ }
186
+
173
187
if setting .DisableWebhooks {
174
188
return fmt .Errorf ("webhook task skipped (webhooks disabled): [%d]" , t .ID )
175
189
}
176
190
177
191
if ! w .IsActive {
192
+ log .Trace ("Webhook %s in Webhook Task[%d] is not active" , w .URL , t .ID )
178
193
return nil
179
194
}
180
195
181
196
resp , err := webhookHTTPClient .Do (req .WithContext (ctx ))
182
197
if err != nil {
183
198
t .ResponseInfo .Body = fmt .Sprintf ("Delivery: %v" , err )
184
- return err
199
+ return fmt . Errorf ( "unable to deliver webhook task[%d] in %s due to error in http client: %w" , t . ID , w . URL , err )
185
200
}
186
201
defer resp .Body .Close ()
187
202
@@ -195,7 +210,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
195
210
p , err := io .ReadAll (resp .Body )
196
211
if err != nil {
197
212
t .ResponseInfo .Body = fmt .Sprintf ("read body: %s" , err )
198
- return err
213
+ return fmt . Errorf ( "unable to deliver webhook task[%d] in %s as unable to read response body: %w" , t . ID , w . URL , err )
199
214
}
200
215
t .ResponseInfo .Body = string (p )
201
216
return nil
@@ -257,17 +272,37 @@ func Init() error {
257
272
}
258
273
go graceful .GetManager ().RunWithShutdownFns (hookQueue .Run )
259
274
260
- tasks , err := webhook_model .FindUndeliveredHookTasks (graceful .GetManager ().HammerContext ())
261
- if err != nil {
262
- log .Error ("FindUndeliveredHookTasks failed: %v" , err )
263
- return err
264
- }
275
+ go graceful .GetManager ().RunWithShutdownContext (populateWebhookSendingQueue )
276
+
277
+ return nil
278
+ }
279
+
280
+ func populateWebhookSendingQueue (ctx context.Context ) {
281
+ ctx , _ , finished := process .GetManager ().AddContext (ctx , "Webhook: Populate sending queue" )
282
+ defer finished ()
265
283
266
- for _ , task := range tasks {
267
- if err := enqueueHookTask (task ); err != nil {
268
- log .Error ("enqueueHookTask failed: %v" , err )
284
+ lowerID := int64 (0 )
285
+ for {
286
+ taskIDs , err := webhook_model .FindUndeliveredHookTaskIDs (ctx , lowerID )
287
+ if err != nil {
288
+ log .Error ("Unable to populate webhook queue as FindUndeliveredHookTaskIDs failed: %v" , err )
289
+ return
290
+ }
291
+ if len (taskIDs ) == 0 {
292
+ return
293
+ }
294
+ lowerID = taskIDs [len (taskIDs )- 1 ]
295
+
296
+ for _ , taskID := range taskIDs {
297
+ select {
298
+ case <- ctx .Done ():
299
+ log .Warn ("Shutdown before Webhook Sending queue finishing being populated" )
300
+ return
301
+ default :
302
+ }
303
+ if err := enqueueHookTask (taskID ); err != nil {
304
+ log .Error ("Unable to push HookTask[%d] to the Webhook Sending queue: %v" , taskID , err )
305
+ }
269
306
}
270
307
}
271
-
272
- return nil
273
308
}
0 commit comments