Skip to content

Commit 1887c95

Browse files
KN4CK3R6543
andauthored
Decouple HookTask from Repository (#17940)
At the moment a repository reference is needed for webhooks. With the upcoming package PR we need to send webhooks without a repository reference. For example a package is uploaded to an organization. In theory this enables the usage of webhooks for future user actions. This PR removes the repository id from `HookTask` and changes how the hooks are processed (see `services/webhook/deliver.go`). In a follow up PR I want to remove the usage of the `UniqueQueue´ and replace it with a normal queue because there is no reason to be unique. Co-authored-by: 6543 <[email protected]>
1 parent e828564 commit 1887c95

File tree

12 files changed

+216
-279
lines changed

12 files changed

+216
-279
lines changed

models/fixtures/hook_task.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
-
22
id: 1
3-
repo_id: 1
43
hook_id: 1
54
uuid: uuid1
65
is_delivered: true

models/repo.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,18 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
123123
return err
124124
}
125125

126+
if _, err := db.GetEngine(ctx).In("hook_id", builder.Select("id").From("webhook").Where(builder.Eq{"webhook.repo_id": repo.ID})).
127+
Delete(&webhook.HookTask{}); err != nil {
128+
return err
129+
}
130+
126131
if err := db.DeleteBeans(ctx,
127132
&access_model.Access{RepoID: repo.ID},
128133
&activities_model.Action{RepoID: repo.ID},
129134
&repo_model.Collaboration{RepoID: repoID},
130135
&issues_model.Comment{RefRepoID: repoID},
131136
&git_model.CommitStatus{RepoID: repoID},
132137
&git_model.DeletedBranch{RepoID: repoID},
133-
&webhook.HookTask{RepoID: repoID},
134138
&git_model.LFSLock{RepoID: repoID},
135139
&repo_model.LanguageStat{RepoID: repoID},
136140
&issues_model.Milestone{RepoID: repoID},

models/webhook/hooktask.go

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ type HookResponse struct {
104104
// HookTask represents a hook task.
105105
type HookTask struct {
106106
ID int64 `xorm:"pk autoincr"`
107-
RepoID int64 `xorm:"INDEX"`
108107
HookID int64
109108
UUID string
110109
api.Payloader `xorm:"-"`
@@ -178,14 +177,29 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
178177

179178
// CreateHookTask creates a new hook task,
180179
// it handles conversion from Payload to PayloadContent.
181-
func CreateHookTask(t *HookTask) error {
180+
func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) {
182181
data, err := t.Payloader.JSONPayload()
183182
if err != nil {
184-
return err
183+
return nil, err
185184
}
186185
t.UUID = gouuid.New().String()
187186
t.PayloadContent = string(data)
188-
return db.Insert(db.DefaultContext, t)
187+
return t, db.Insert(ctx, t)
188+
}
189+
190+
func GetHookTaskByID(ctx context.Context, id int64) (*HookTask, error) {
191+
t := &HookTask{}
192+
193+
has, err := db.GetEngine(ctx).ID(id).Get(t)
194+
if err != nil {
195+
return nil, err
196+
}
197+
if !has {
198+
return nil, ErrHookTaskNotExist{
199+
TaskID: id,
200+
}
201+
}
202+
return t, nil
189203
}
190204

191205
// UpdateHookTask updates information of hook task.
@@ -195,53 +209,36 @@ func UpdateHookTask(t *HookTask) error {
195209
}
196210

197211
// ReplayHookTask copies a hook task to get re-delivered
198-
func ReplayHookTask(hookID int64, uuid string) (*HookTask, error) {
199-
var newTask *HookTask
200-
201-
err := db.WithTx(func(ctx context.Context) error {
202-
task := &HookTask{
212+
func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask, error) {
213+
task := &HookTask{
214+
HookID: hookID,
215+
UUID: uuid,
216+
}
217+
has, err := db.GetByBean(ctx, task)
218+
if err != nil {
219+
return nil, err
220+
} else if !has {
221+
return nil, ErrHookTaskNotExist{
203222
HookID: hookID,
204223
UUID: uuid,
205224
}
206-
has, err := db.GetByBean(ctx, task)
207-
if err != nil {
208-
return err
209-
} else if !has {
210-
return ErrHookTaskNotExist{
211-
HookID: hookID,
212-
UUID: uuid,
213-
}
214-
}
215-
216-
newTask = &HookTask{
217-
UUID: gouuid.New().String(),
218-
RepoID: task.RepoID,
219-
HookID: task.HookID,
220-
PayloadContent: task.PayloadContent,
221-
EventType: task.EventType,
222-
}
223-
return db.Insert(ctx, newTask)
224-
})
225+
}
225226

226-
return newTask, err
227+
newTask := &HookTask{
228+
UUID: gouuid.New().String(),
229+
HookID: task.HookID,
230+
PayloadContent: task.PayloadContent,
231+
EventType: task.EventType,
232+
}
233+
return newTask, db.Insert(ctx, newTask)
227234
}
228235

229236
// FindUndeliveredHookTasks represents find the undelivered hook tasks
230-
func FindUndeliveredHookTasks() ([]*HookTask, error) {
237+
func FindUndeliveredHookTasks(ctx context.Context) ([]*HookTask, error) {
231238
tasks := make([]*HookTask, 0, 10)
232-
if err := db.GetEngine(db.DefaultContext).Where("is_delivered=?", false).Find(&tasks); err != nil {
233-
return nil, err
234-
}
235-
return tasks, nil
236-
}
237-
238-
// FindRepoUndeliveredHookTasks represents find the undelivered hook tasks of one repository
239-
func FindRepoUndeliveredHookTasks(repoID int64) ([]*HookTask, error) {
240-
tasks := make([]*HookTask, 0, 5)
241-
if err := db.GetEngine(db.DefaultContext).Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
242-
return nil, err
243-
}
244-
return tasks, nil
239+
return tasks, db.GetEngine(ctx).
240+
Where("is_delivered=?", false).
241+
Find(&tasks)
245242
}
246243

247244
// CleanupHookTaskTable deletes rows from hook_task as needed.
@@ -250,7 +247,7 @@ func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType,
250247

251248
if cleanupType == OlderThan {
252249
deleteOlderThan := time.Now().Add(-olderThan).UnixNano()
253-
deletes, err := db.GetEngine(db.DefaultContext).
250+
deletes, err := db.GetEngine(ctx).
254251
Where("is_delivered = ? and delivered < ?", true, deleteOlderThan).
255252
Delete(new(HookTask))
256253
if err != nil {
@@ -259,7 +256,8 @@ func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType,
259256
log.Trace("Deleted %d rows from hook_task", deletes)
260257
} else if cleanupType == PerWebhook {
261258
hookIDs := make([]int64, 0, 10)
262-
err := db.GetEngine(db.DefaultContext).Table("webhook").
259+
err := db.GetEngine(ctx).
260+
Table("webhook").
263261
Where("id > 0").
264262
Cols("id").
265263
Find(&hookIDs)

models/webhook/webhook.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ import (
1919
"xorm.io/builder"
2020
)
2121

22-
// __ __ ___. .__ __
23-
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
24-
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
25-
// \ /\ ___/| \_\ \ Y ( <_> | <_> ) <
26-
// \__/\ / \___ >___ /___| /\____/ \____/|__|_ \
27-
// \/ \/ \/ \/ \/
28-
2922
// ErrWebhookNotExist represents a "WebhookNotExist" kind of error.
3023
type ErrWebhookNotExist struct {
3124
ID int64
@@ -47,6 +40,7 @@ func (err ErrWebhookNotExist) Unwrap() error {
4740

4841
// ErrHookTaskNotExist represents a "HookTaskNotExist" kind of error.
4942
type ErrHookTaskNotExist struct {
43+
TaskID int64
5044
HookID int64
5145
UUID string
5246
}
@@ -58,7 +52,7 @@ func IsErrHookTaskNotExist(err error) bool {
5852
}
5953

6054
func (err ErrHookTaskNotExist) Error() string {
61-
return fmt.Sprintf("hook task does not exist [hook: %d, uuid: %s]", err.HookID, err.UUID)
55+
return fmt.Sprintf("hook task does not exist [task: %d, hook: %d, uuid: %s]", err.TaskID, err.HookID, err.UUID)
6256
}
6357

6458
func (err ErrHookTaskNotExist) Unwrap() error {

models/webhook/webhook_test.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,12 @@ func TestHookTasks(t *testing.T) {
208208
func TestCreateHookTask(t *testing.T) {
209209
assert.NoError(t, unittest.PrepareTestDatabase())
210210
hookTask := &HookTask{
211-
RepoID: 3,
212211
HookID: 3,
213212
Payloader: &api.PushPayload{},
214213
}
215214
unittest.AssertNotExistsBean(t, hookTask)
216-
assert.NoError(t, CreateHookTask(hookTask))
215+
_, err := CreateHookTask(db.DefaultContext, hookTask)
216+
assert.NoError(t, err)
217217
unittest.AssertExistsAndLoadBean(t, hookTask)
218218
}
219219

@@ -232,14 +232,14 @@ func TestUpdateHookTask(t *testing.T) {
232232
func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
233233
assert.NoError(t, unittest.PrepareTestDatabase())
234234
hookTask := &HookTask{
235-
RepoID: 3,
236235
HookID: 3,
237236
Payloader: &api.PushPayload{},
238237
IsDelivered: true,
239238
Delivered: time.Now().UnixNano(),
240239
}
241240
unittest.AssertNotExistsBean(t, hookTask)
242-
assert.NoError(t, CreateHookTask(hookTask))
241+
_, err := CreateHookTask(db.DefaultContext, hookTask)
242+
assert.NoError(t, err)
243243
unittest.AssertExistsAndLoadBean(t, hookTask)
244244

245245
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 0))
@@ -249,13 +249,13 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
249249
func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
250250
assert.NoError(t, unittest.PrepareTestDatabase())
251251
hookTask := &HookTask{
252-
RepoID: 2,
253252
HookID: 4,
254253
Payloader: &api.PushPayload{},
255254
IsDelivered: false,
256255
}
257256
unittest.AssertNotExistsBean(t, hookTask)
258-
assert.NoError(t, CreateHookTask(hookTask))
257+
_, err := CreateHookTask(db.DefaultContext, hookTask)
258+
assert.NoError(t, err)
259259
unittest.AssertExistsAndLoadBean(t, hookTask)
260260

261261
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 0))
@@ -265,14 +265,14 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
265265
func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
266266
assert.NoError(t, unittest.PrepareTestDatabase())
267267
hookTask := &HookTask{
268-
RepoID: 2,
269268
HookID: 4,
270269
Payloader: &api.PushPayload{},
271270
IsDelivered: true,
272271
Delivered: time.Now().UnixNano(),
273272
}
274273
unittest.AssertNotExistsBean(t, hookTask)
275-
assert.NoError(t, CreateHookTask(hookTask))
274+
_, err := CreateHookTask(db.DefaultContext, hookTask)
275+
assert.NoError(t, err)
276276
unittest.AssertExistsAndLoadBean(t, hookTask)
277277

278278
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 1))
@@ -282,14 +282,14 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
282282
func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
283283
assert.NoError(t, unittest.PrepareTestDatabase())
284284
hookTask := &HookTask{
285-
RepoID: 3,
286285
HookID: 3,
287286
Payloader: &api.PushPayload{},
288287
IsDelivered: true,
289288
Delivered: time.Now().AddDate(0, 0, -8).UnixNano(),
290289
}
291290
unittest.AssertNotExistsBean(t, hookTask)
292-
assert.NoError(t, CreateHookTask(hookTask))
291+
_, err := CreateHookTask(db.DefaultContext, hookTask)
292+
assert.NoError(t, err)
293293
unittest.AssertExistsAndLoadBean(t, hookTask)
294294

295295
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
@@ -299,13 +299,13 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
299299
func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
300300
assert.NoError(t, unittest.PrepareTestDatabase())
301301
hookTask := &HookTask{
302-
RepoID: 2,
303302
HookID: 4,
304303
Payloader: &api.PushPayload{},
305304
IsDelivered: false,
306305
}
307306
unittest.AssertNotExistsBean(t, hookTask)
308-
assert.NoError(t, CreateHookTask(hookTask))
307+
_, err := CreateHookTask(db.DefaultContext, hookTask)
308+
assert.NoError(t, err)
309309
unittest.AssertExistsAndLoadBean(t, hookTask)
310310

311311
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
@@ -315,14 +315,14 @@ func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
315315
func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *testing.T) {
316316
assert.NoError(t, unittest.PrepareTestDatabase())
317317
hookTask := &HookTask{
318-
RepoID: 2,
319318
HookID: 4,
320319
Payloader: &api.PushPayload{},
321320
IsDelivered: true,
322321
Delivered: time.Now().AddDate(0, 0, -6).UnixNano(),
323322
}
324323
unittest.AssertNotExistsBean(t, hookTask)
325-
assert.NoError(t, CreateHookTask(hookTask))
324+
_, err := CreateHookTask(db.DefaultContext, hookTask)
325+
assert.NoError(t, err)
326326
unittest.AssertExistsAndLoadBean(t, hookTask)
327327

328328
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))

0 commit comments

Comments
 (0)