diff --git a/gitlab/models/gitlab.py b/gitlab/models/gitlab.py index b0f62885..e41a031a 100644 --- a/gitlab/models/gitlab.py +++ b/gitlab/models/gitlab.py @@ -19,7 +19,11 @@ def _compute_display_name(self): def get_server_connection(self): self.ensure_one() - gl = gitlab.Gitlab(url=self.url, private_token=self.private_token) + gl = gitlab.Gitlab( + url=self.url, + private_token=self.private_token, + retry_transient_errors=True, + ) if self.debug: gl.enable_debug() return gl diff --git a/membership_activity_gitlab/models/project_project.py b/membership_activity_gitlab/models/project_project.py index 2ca87f50..529b0dda 100644 --- a/membership_activity_gitlab/models/project_project.py +++ b/membership_activity_gitlab/models/project_project.py @@ -1,11 +1,33 @@ import re from datetime import datetime, timezone +from functools import wraps import dateutil from dateutil.relativedelta import relativedelta from odoo import api, exceptions, fields, models +from odoo.addons.queue_job.exception import RetryableJobError + +from gitlab import GitlabError + + +def use_gitlab(method): + @wraps(method) + def _wrap(self, *args, **kwargs): + # Gitlab (gitlab.com) can sometimes return 502 or 504 + try: + return method(self, *args, **kwargs) + except GitlabError as e: + if e.response_code in (502, 504): # Bad gateway or Gateway Timeout + raise RetryableJobError( + e.error_message, + seconds=60, # Retry after 1 minute + ) from e + raise e + + return _wrap + class Project(models.Model): _inherit = "project.project" @@ -53,6 +75,7 @@ def get_gitlab_commits(self): 1, project.gitlab_id.per_page, since, until ) + @use_gitlab def get_gitlab_commits_iterated(self, page, per_page, since, until): self.ensure_one() gl = self.gitlab_id.get_server_connection() @@ -103,6 +126,7 @@ def get_gitlab_merge_requests(self): 1, project.gitlab_id.per_page, since, until ) + @use_gitlab def get_gitlab_merge_requests_iterated(self, page, per_page, since, until): self.ensure_one() gl = self.gitlab_id.get_server_connection() @@ -159,6 +183,7 @@ def get_gitlab_issues(self): 1, project.gitlab_id.per_page, since, until ) + @use_gitlab def get_gitlab_issues_iterated(self, page, per_page, since, until): self.ensure_one() gl = self.gitlab_id.get_server_connection() @@ -215,6 +240,7 @@ def get_gitlab_notes(self): 1, project.gitlab_id.per_page, since, until ) + @use_gitlab def get_gitlab_notes_iterated(self, page, per_page, since, until): self.ensure_one() gl = self.gitlab_id.get_server_connection() @@ -274,6 +300,7 @@ def get_gitlab_approvals(self): 1, project.gitlab_id.per_page, since, until ) + @use_gitlab def get_gitlab_approvals_iterated(self, page, per_page, since, until): self.ensure_one() gl = self.gitlab_id.get_server_connection() diff --git a/membership_activity_gitlab/tests/__init__.py b/membership_activity_gitlab/tests/__init__.py new file mode 100644 index 00000000..15d04594 --- /dev/null +++ b/membership_activity_gitlab/tests/__init__.py @@ -0,0 +1 @@ +from . import test_gitlab diff --git a/membership_activity_gitlab/tests/test_gitlab.py b/membership_activity_gitlab/tests/test_gitlab.py new file mode 100644 index 00000000..0c773594 --- /dev/null +++ b/membership_activity_gitlab/tests/test_gitlab.py @@ -0,0 +1,40 @@ +from unittest.mock import patch + +from odoo.tests.common import TransactionCase + +from odoo.addons.membership_activity_gitlab.models.project_project import use_gitlab +from odoo.addons.queue_job.exception import RetryableJobError + +from gitlab import GitlabError + + +class TestGitlab(TransactionCase): + def test_retryable_error_on_502(self): + """Test that a RetryableJobError is raised when a 502 error occurs.""" + + # Mock get_gitlab_commits_iterated to raise a GitlabError with a 502 response code + project = self.env["project.project"].create( + { + "name": "Test Project", + "gitlab_id": self.env["gitlab"] + .create( + { + "url": "https://gitlab.com", + "private_token": "fake_token", + } + ) + .id, + } + ) + + @use_gitlab + def mock_get_gitlab_commits_iterated(self, page, per_page, since, until): + raise GitlabError("Bad Gateway", response_code=502) + + with patch( + "odoo.addons.membership_activity_gitlab.models." + "project_project.Project.get_gitlab_commits_iterated", + new=mock_get_gitlab_commits_iterated, + ): + with self.assertRaises(RetryableJobError): + project.get_gitlab_commits_iterated(1, 100, "2024-01-01", "2024-01-31")