0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-14 00:01:05 +02:00

added retry logic

This commit is contained in:
karthikbhandary2 2026-03-07 17:58:58 +05:30
parent 988ec17d9d
commit 008415e752
2 changed files with 24 additions and 9 deletions

View File

@ -552,6 +552,10 @@ func DeleteOrgRepos(ctx *context.APIContext) {
bgCtx := graceful.GetManager().HammerContext()
const batchSize = 50
const maxRetries = 3
// Track failed deletions with retry limit to prevent infinite loops when repos cannot be deleted.
// If a repo fails 3 times, skip it; if all remaining repos have hit max retries, exit the loop.
failedRepos := make(map[int64]int) // repo ID -> retry count
for {
repos := make([]*repo_model.Repository, 0, batchSize)
@ -572,16 +576,32 @@ func DeleteOrgRepos(ctx *context.APIContext) {
break
}
allFailed := true
for _, repo := range repos {
// Skip repos that have failed too many times
if failedRepos[repo.ID] >= maxRetries {
continue
}
if err := repo_service.DeleteRepository(bgCtx, doer, repo, true); err != nil {
desc := fmt.Sprintf("Failed to delete repository %s (ID: %d) in org ID %d: %v", repo.Name, repo.ID, orgID, err)
failedRepos[repo.ID]++
desc := fmt.Sprintf("Failed to delete repository %s (ID: %d) in org ID %d (attempt %d/%d): %v",
repo.Name, repo.ID, orgID, failedRepos[repo.ID], maxRetries, err)
if noticeErr := system_model.CreateNotice(bgCtx, system_model.NoticeRepository, desc); noticeErr != nil {
log.Error("Failed to create notice for repo deletion failure: %v", noticeErr)
}
} else {
allFailed = false
delete(failedRepos, repo.ID) // Remove from failed map if it succeeds
log.Info("Successfully deleted repository %s (ID: %d) in org ID %d", repo.Name, repo.ID, orgID)
}
}
// If all repos in this batch have failed max retries, break to avoid infinite loop
if allFailed && len(failedRepos) > 0 {
log.Error("All remaining repositories failed to delete after %d retries for org ID %d", maxRetries, orgID)
break
}
}
log.Info("Completed deletion of repositories in org ID %d", orgID)
}()

View File

@ -255,8 +255,9 @@ func TestAPIOrgGeneral(t *testing.T) {
}
func TestAPIDeleteOrgRepos(t *testing.T) {
defer tests.PrepareTestEnv(t)()
t.Run("Delete all repos successfully", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
// Create test org with owner
@ -284,7 +285,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
})
t.Run("Verify delete status code", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
@ -310,7 +310,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
})
t.Run("Fail without permissions", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
// user2 is owner of org3
@ -333,7 +332,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
})
t.Run("No system notice created on successful deletion", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
@ -382,7 +380,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
})
t.Run("Returns 204 when repos already deleted", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
@ -415,7 +412,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
})
t.Run("Returns 204 when no repos exist", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
@ -433,7 +429,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
})
t.Run("Pagination works for large org", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
@ -479,6 +474,6 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
// Verify all repos were deleted
remainingRepos, err := repo_model.GetOrgRepositories(t.Context(), org.ID)
assert.NoError(t, err)
assert.Empty(t, remainingRepos, "Org is empty")
assert.Empty(t, remainingRepos, "All repositories should be deleted")
})
}