From b2f828db5e5878d47de32c292d95c95c4217de68 Mon Sep 17 00:00:00 2001 From: 6543 Date: Sat, 21 Oct 2023 04:05:29 +0200 Subject: [PATCH] refactor: make db iterate context aware (#27710) the iteration will run until finished atm. this changes it by checking if if the context got canceled before each run of a loop sequence is executed [View this pull with now whitespace](https://github.com/go-gitea/gitea/pull/27710/files?diff=unified&w=1) --- models/db/iterate.go | 33 ++++++++++++++++++-------------- modules/doctor/repository.go | 37 ++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/models/db/iterate.go b/models/db/iterate.go index fc8c78d83ea3..e1caefa72b8b 100644 --- a/models/db/iterate.go +++ b/models/db/iterate.go @@ -17,22 +17,27 @@ func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx contex batchSize := setting.Database.IterateBufferSize sess := GetEngine(ctx) for { - beans := make([]*Bean, 0, batchSize) - if cond != nil { - sess = sess.Where(cond) - } - if err := sess.Limit(batchSize, start).Find(&beans); err != nil { - return err - } - if len(beans) == 0 { - return nil - } - start += len(beans) - - for _, bean := range beans { - if err := f(ctx, bean); err != nil { + select { + case <-ctx.Done(): + return ctx.Err() + default: + beans := make([]*Bean, 0, batchSize) + if cond != nil { + sess = sess.Where(cond) + } + if err := sess.Limit(batchSize, start).Find(&beans); err != nil { return err } + if len(beans) == 0 { + return nil + } + start += len(beans) + + for _, bean := range beans { + if err := f(ctx, bean); err != nil { + return err + } + } } } } diff --git a/modules/doctor/repository.go b/modules/doctor/repository.go index aa3f064ddd84..d69ba2048bb2 100644 --- a/modules/doctor/repository.go +++ b/modules/doctor/repository.go @@ -37,24 +37,29 @@ func deleteOrphanedRepos(ctx context.Context) (int64, error) { adminUser := &user_model.User{IsAdmin: true} for { - var ids []int64 - if err := e.Table("`repository`"). - Join("LEFT", "`user`", "repository.owner_id=user.id"). - Where(builder.IsNull{"`user`.id"}). - Select("`repository`.id").Limit(batchSize).Find(&ids); err != nil { - return deleted, err - } - - // if we don't get ids we have deleted them all - if len(ids) == 0 { - return deleted, nil - } - - for _, id := range ids { - if err := repo_service.DeleteRepositoryDirectly(ctx, adminUser, id, true); err != nil { + select { + case <-ctx.Done(): + return deleted, ctx.Err() + default: + var ids []int64 + if err := e.Table("`repository`"). + Join("LEFT", "`user`", "repository.owner_id=user.id"). + Where(builder.IsNull{"`user`.id"}). + Select("`repository`.id").Limit(batchSize).Find(&ids); err != nil { return deleted, err } - deleted++ + + // if we don't get ids we have deleted them all + if len(ids) == 0 { + return deleted, nil + } + + for _, id := range ids { + if err := repo_service.DeleteRepositoryDirectly(ctx, adminUser, id, true); err != nil { + return deleted, err + } + deleted++ + } } } }