|
1 | 1 | import logging |
2 | 2 | from collections.abc import AsyncIterator |
| 3 | +from datetime import UTC, datetime, timedelta |
3 | 4 | from functools import cache |
4 | 5 | from typing import Collection, Iterable |
5 | 6 |
|
|
13 | 14 |
|
14 | 15 | logger = logging.getLogger(__name__) |
15 | 16 |
|
| 17 | +VISIBILITY_TIMEOUT = timedelta(minutes=5) |
| 18 | + |
16 | 19 |
|
17 | 20 | class ReviewProcessingError(Exception): |
18 | 21 | """Custom exception for permanent errors during review processing that should not trigger retries.""" |
19 | 22 |
|
20 | 23 |
|
| 24 | +class RevisionNotYetPublicError(Exception): |
| 25 | + """The revision is not yet public but was recently created. |
| 26 | +
|
| 27 | + This is a transient error — Cloud Tasks should retry after backoff. |
| 28 | + """ |
| 29 | + |
| 30 | + |
21 | 31 | @cache |
22 | 32 | def get_code_review_tool(): |
23 | 33 | from bugbug.tools.code_review import CodeReviewTool |
@@ -50,6 +60,13 @@ async def process_review( |
50 | 60 | raise ValueError(f"Unsupported platform: {review_request.platform}") |
51 | 61 |
|
52 | 62 | if not patch.is_accessible() or not patch.is_public(): |
| 63 | + age = datetime.now(UTC) - review_request.created_at |
| 64 | + if age < VISIBILITY_TIMEOUT: |
| 65 | + raise RevisionNotYetPublicError( |
| 66 | + f"Revision D{review_request.revision_id} is not public. " |
| 67 | + "But the review request was created recently, so this may be a visibility delay." |
| 68 | + ) |
| 69 | + |
53 | 70 | raise ReviewProcessingError( |
54 | 71 | "Unable to access the revision. This may be because " |
55 | 72 | "the revision is private or has restricted visibility." |
|
0 commit comments