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:
parent
988ec17d9d
commit
008415e752
@ -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)
|
||||
}()
|
||||
|
||||
@ -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")
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user