File size: 4,885 Bytes
5d7acbc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python3
"""
Main API Server for Self-Healing ML Pipelines

Integrates all API endpoints including the Human Veto endpoint.
This server is ALWAYS AVAILABLE as a safety mechanism for human operators.

Usage:
    python api_server.py --port 8080
    
Author: Self-Healing ML Pipelines Team
License: MIT
"""

import argparse
import sys
import threading
from pathlib import Path

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))

from http.server import HTTPServer
from api.human_veto_endpoint import HumanVetoAPI, VetoStore


class MainAPIServer:
    """
    Main API Server that hosts all endpoints for the Self-Healing ML Pipeline.
    
    This server ensures the Human Veto endpoint is ALWAYS AVAILABLE,
    even when the main pipeline is not running.
    """
    
    def __init__(self, host: str = '0.0.0.0', port: int = 8080, storage_path: str = None):
        self.host = host
        self.port = port
        self.storage_path = storage_path
        self.human_veto_api: HumanVetoAPI = None
        self.server: HTTPServer = None
        self._running = False
        
    def start(self, blocking: bool = True):
        """Start the main API server with all endpoints."""
        
        # Initialize the Human Veto API (ALWAYS AVAILABLE)
        self.human_veto_api = HumanVetoAPI(
            host=self.host,
            port=self.port,
            storage_path=self.storage_path
        )
        
        print(f"\n{'='*70}")
        print(f"πŸš€ Self-Healing ML Pipeline API Server")
        print(f"{'='*70}")
        print(f"   Host: {self.host}")
        print(f"   Port: {self.port}")
        print(f"\nπŸ“‘ Available Endpoints:")
        print(f"   ─────────────────────────────────────────────────────")
        print(f"   HUMAN VETO ENDPOINT (Always Available):")
        print(f"   GET    /api/v1/human-veto          - List pending vetoes")
        print(f"   POST   /api/v1/human-veto          - Submit new veto")
        print(f"   PUT    /api/v1/human-veto/<id>     - Approve/Reject veto")
        print(f"   DELETE /api/v1/human-veto/<id>     - Cancel veto request")
        print(f"   GET    /api/v1/human-veto/history  - Get veto history")
        print(f"   ─────────────────────────────────────────────────────")
        print(f"   HEALTH CHECK:")
        print(f"   GET    /health                     - Service health status")
        print(f"   ─────────────────────────────────────────────────────")
        print(f"   WEB UI:")
        print(f"   GET    /                           - Human Veto Dashboard")
        print(f"{'='*70}")
        print(f"βœ… Human Veto Endpoint is ALWAYS AVAILABLE for override")
        print(f"{'='*70}\n")
        
        # Start the server
        self.human_veto_api.start(blocking=blocking)
        self._running = True
        
    def stop(self):
        """Stop the API server."""
        if self.human_veto_api:
            self.human_veto_api.stop()
        self._running = False
        print("βœ… API Server stopped")
        
    def is_running(self) -> bool:
        """Check if server is running."""
        return self._running


def main():
    parser = argparse.ArgumentParser(
        description='Self-Healing ML Pipeline API Server',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
    python api_server.py --port 8080
    python api_server.py --host 127.0.0.1 --port 9000
    python api_server.py --storage /path/to/veto_store.json

The Human Veto endpoint will be available at:
    http://localhost:8080/api/v1/human-veto

Web Dashboard available at:
    http://localhost:8080/
        """
    )
    
    parser.add_argument(
        '--host',
        type=str,
        default='0.0.0.0',
        help='Host address to bind to (default: 0.0.0.0)'
    )
    
    parser.add_argument(
        '--port',
        type=int,
        default=8080,
        help='Port to listen on (default: 8080)'
    )
    
    parser.add_argument(
        '--storage',
        type=str,
        default=None,
        help='Path to veto store JSON file'
    )
    
    args = parser.parse_args()
    
    server = MainAPIServer(
        host=args.host,
        port=args.port,
        storage_path=args.storage
    )
    
    try:
        server.start(blocking=True)
    except KeyboardInterrupt:
        print("\nπŸ‘‹ Received shutdown signal...")
        server.stop()
    except Exception as e:
        print(f"❌ Server error: {e}")
        sys.exit(1)


if __name__ == '__main__':
    main()