diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index 42279cbdd..661994910 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -5,6 +5,7 @@ package issues import ( "context" + "fmt" "os" "runtime/pprof" "sync/atomic" @@ -202,11 +203,16 @@ func getIssueIndexerQueueHandler(ctx context.Context) func(items ...*IndexerMeta func populateIssueIndexer(ctx context.Context) { ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Service: PopulateIssueIndexer", process.SystemProcessType, true) defer finished() + if err := PopulateIssueIndexer(ctx, true); err != nil { + log.Error("Issue indexer population failed: %v", err) + } +} + +func PopulateIssueIndexer(ctx context.Context, keepRetrying bool) error { for page := 1; ; page++ { select { case <-ctx.Done(): - log.Warn("Issue Indexer population shutdown before completion") - return + return fmt.Errorf("shutdown before completion: %w", ctx.Err()) default: } repos, _, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{ @@ -221,20 +227,22 @@ func populateIssueIndexer(ctx context.Context) { } if len(repos) == 0 { log.Debug("Issue Indexer population complete") - return + return nil } for _, repo := range repos { for { select { case <-ctx.Done(): - log.Info("Issue Indexer population shutdown before completion") - return + return fmt.Errorf("shutdown before completion: %w", ctx.Err()) default: } if err := updateRepoIndexer(ctx, repo.ID); err != nil { - log.Warn("Retry to populate issue indexer for repo %d: %v", repo.ID, err) - continue + if keepRetrying && ctx.Err() == nil { + log.Warn("Retry to populate issue indexer for repo %d: %v", repo.ID, err) + continue + } + return fmt.Errorf("populate issue indexer for repo %d: %v", repo.ID, err) } break } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index cbafef9d5..0bfe1eac7 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2752,6 +2752,7 @@ dashboard.stop_zombie_tasks = Stop zombie tasks dashboard.stop_endless_tasks = Stop endless tasks dashboard.cancel_abandoned_jobs = Cancel abandoned jobs dashboard.sync_branch.started = Branches Sync started +dashboard.rebuild_issue_indexer = Rebuild issue indexer users.user_manage_panel = User Account Management users.new_account = Create User Account diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index acf2d3373..48ea87df7 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + issue_indexer "code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/updatechecker" repo_service "code.gitea.io/gitea/services/repository" @@ -213,6 +214,16 @@ func registerGCLFS() { }) } +func registerRebuildIssueIndexer() { + RegisterTaskFatal("rebuild_issue_indexer", &BaseConfig{ + Enabled: false, + RunAtStart: false, + Schedule: "@annually", + }, func(ctx context.Context, _ *user_model.User, config Config) error { + return issue_indexer.PopulateIssueIndexer(ctx, false) + }) +} + func initExtendedTasks() { registerDeleteInactiveUsers() registerDeleteRepositoryArchives() @@ -227,4 +238,5 @@ func initExtendedTasks() { registerUpdateGiteaChecker() registerDeleteOldSystemNotices() registerGCLFS() + registerRebuildIssueIndexer() }