File size: 3,066 Bytes
42f12bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""
Evaluation API notification with retry logic
Sends deployment metadata to evaluation endpoint
"""

import requests
import time
import logging

logger = logging.getLogger(__name__)

def notify_evaluation_api(
    evaluation_url: str,
    email: str,
    task: str,
    round: int,
    nonce: str,
    repo_url: str,
    commit_sha: str,
    pages_url: str,
    max_retries: int = 5
) -> bool:
    """
    Notify evaluation API with deployment details
    Implements exponential backoff retry logic
    
    Args:
        evaluation_url: Evaluation API endpoint
        email: Student email
        task: Task identifier
        round: Round number (1 or 2)
        nonce: Security nonce from request
        repo_url: GitHub repository URL
        commit_sha: Latest commit SHA
        pages_url: GitHub Pages URL
        max_retries: Maximum retry attempts
    
    Returns:
        True if notification successful, False otherwise
    """
    
    payload = {
        "email": email,
        "task": task,
        "round": round,
        "nonce": nonce,
        "repo_url": repo_url,
        "commit_sha": commit_sha,
        "pages_url": pages_url
    }
    
    headers = {
        "Content-Type": "application/json"
    }
    
    # Exponential backoff: 1, 2, 4, 8, 16 seconds
    for attempt in range(max_retries):
        try:
            logger.info(f"Notifying evaluation API (attempt {attempt + 1}/{max_retries})...")
            logger.info(f"URL: {evaluation_url}")
            logger.info(f"Payload: {payload}")
            
            response = requests.post(
                evaluation_url,
                json=payload,
                headers=headers,
                timeout=30
            )
            
            if response.status_code == 200:
                logger.info(f"✓ Evaluation API returned HTTP 200")
                logger.info(f"Response: {response.text}")
                return True
            else:
                logger.warning(f"Evaluation API returned HTTP {response.status_code}")
                logger.warning(f"Response: {response.text}")
                
                # Don't retry on 4xx errors (client errors)
                if 400 <= response.status_code < 500:
                    logger.error("Client error - not retrying")
                    return False
                
        except requests.exceptions.Timeout:
            logger.warning(f"Request timeout on attempt {attempt + 1}")
            
        except requests.exceptions.ConnectionError as e:
            logger.warning(f"Connection error on attempt {attempt + 1}: {e}")
            
        except Exception as e:
            logger.error(f"Unexpected error on attempt {attempt + 1}: {e}")
        
        # Exponential backoff (except on last attempt)
        if attempt < max_retries - 1:
            wait_time = 2 ** attempt
            logger.info(f"Retrying in {wait_time} seconds...")
            time.sleep(wait_time)
    
    logger.error(f"✗ Failed to notify evaluation API after {max_retries} attempts")
    return False