fix(migrations): wait out GitHub rate limits and tolerate failed patch downloads (#40012)

Large GitHub migrations failed once the API budget ran out. A rejected
request never updated the downloader's rate state, so go-github refused
every retry locally.

- Record the rate limit from error responses too, so the next request
waits for the reset
- Retry repository-wide comment pages like the other downloader calls
- Stop `waitAndPickClient` spinning when the rate refresh fails
- Skip reaction requests when the reaction rollup reports none
- Log a failed patch download instead of failing the migration

---------

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
authored and GitHub committed 2026-10-31 17:31:51 +01:00
1 parent 680f2a2598
commit 9cd06bf57f
8 files changed
+274 -71

No files matched your search

+15
View File
@@ -154,6 +154,21 @@ func (d *RetryDownloader) GetComments(ctx context.Context, commentable Commentab
return comments, isEnd, err
}
func (d *RetryDownloader) GetAllComments(ctx context.Context, page, perPage int) ([]*Comment, bool, error) {
var (
comments []*Comment
isEnd bool
err error
)
err = d.retry(ctx, func(ctx context.Context) error {
comments, isEnd, err = d.Downloader.GetAllComments(ctx, page, perPage)
return err
})
return comments, isEnd, err
}
// GetPullRequests returns a repository's pull requests with retry
func (d *RetryDownloader) GetPullRequests(ctx context.Context, page, perPage int) ([]*PullRequest, bool, error) {
var (
+15 -8
View File
@@ -11,12 +11,19 @@ import (
"github.com/stretchr/testify/assert"
)
func TestRetryDownloaderExhaustsAttempts(t *testing.T) {
failure := errors.New("permission denied")
attempts := 0
assert.ErrorIs(t, NewRetryDownloader(nil, 3, 0).retry(t.Context(), func(_ctx context.Context) error {
attempts++
return failure
}), failure)
assert.Equal(t, 3, attempts)
type failingCommentsDownloader struct {
NullDownloader
attempts int
}
func (d *failingCommentsDownloader) GetAllComments(_ctx context.Context, _page, _perPage int) ([]*Comment, bool, error) {
d.attempts++
return nil, false, errors.New("permission denied")
}
func TestRetryDownloaderExhaustsAttempts(t *testing.T) {
source := &failingCommentsDownloader{}
_, _, err := NewRetryDownloader(source, 3, 0).GetAllComments(t.Context(), 1, 50)
assert.EqualError(t, err, "permission denied")
assert.Equal(t, 3, source.attempts)
}