- Added EveAI Client to project
- Improvements to EntitlementsDomain & Services - Prechecks in Document domain - Add audit information to LicenseUsage
This commit is contained in:
152
eveai_client/platform/main.py
Normal file
152
eveai_client/platform/main.py
Normal file
@@ -0,0 +1,152 @@
|
||||
import webview
|
||||
import threading
|
||||
import time
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import requests
|
||||
import atexit
|
||||
from eveai_client.platform.app import create_app
|
||||
|
||||
|
||||
class EveAIClient:
|
||||
"""Main client class that orchestrates all platform components."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the EveAI client."""
|
||||
self.port = 7001 # Default port
|
||||
self.host = "127.0.0.1" # Only listen on localhost for security
|
||||
self.app = create_app()
|
||||
self.window = None
|
||||
self.server_process = None
|
||||
|
||||
# Register cleanup at exit to ensure server is terminated
|
||||
atexit.register(self.cleanup)
|
||||
|
||||
def _run_server(self):
|
||||
"""Run Gunicorn server in a separate process."""
|
||||
# Set environment variables if needed
|
||||
env = os.environ.copy()
|
||||
|
||||
# Construct the command
|
||||
cmd = [
|
||||
"gunicorn",
|
||||
"--workers", "1",
|
||||
"--threads", "4",
|
||||
"--bind", f"{self.host}:{self.port}",
|
||||
"--timeout", "120",
|
||||
"wsgi:app"
|
||||
]
|
||||
|
||||
# Start the server as a subprocess
|
||||
self.server_process = subprocess.Popen(
|
||||
cmd,
|
||||
env=env,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# Log server output
|
||||
for line in iter(self.server_process.stdout.readline, ""):
|
||||
print(f"[Server] {line.strip()}")
|
||||
|
||||
def _wait_for_server(self, timeout=30):
|
||||
"""Wait for server to be ready by polling the endpoint."""
|
||||
url = f"http://{self.host}:{self.port}/"
|
||||
start_time = time.time()
|
||||
|
||||
while time.time() - start_time < timeout:
|
||||
try:
|
||||
response = requests.get(url, timeout=1)
|
||||
if response.status_code == 200:
|
||||
print(f"Server at {url} is ready!")
|
||||
return True
|
||||
except requests.RequestException:
|
||||
print("Waiting for server to start...")
|
||||
time.sleep(1)
|
||||
|
||||
print(f"Server did not start within {timeout} seconds")
|
||||
return False
|
||||
|
||||
def _on_window_closing(self):
|
||||
"""Handle window closing event."""
|
||||
print("Window closing, shutting down server...")
|
||||
self.cleanup()
|
||||
return True # Allow window to close
|
||||
|
||||
def start(self):
|
||||
"""Start the EveAI client application."""
|
||||
# Start Gunicorn server in a separate thread
|
||||
server_thread = threading.Thread(target=self._run_server)
|
||||
server_thread.daemon = True
|
||||
server_thread.start()
|
||||
|
||||
# Wait for the server to be ready to accept connections
|
||||
if not self._wait_for_server():
|
||||
print("Failed to start server, exiting...")
|
||||
self.cleanup()
|
||||
return
|
||||
|
||||
print(f"Starting webview with URL: http://{self.host}:{self.port}")
|
||||
|
||||
# Create and show the main window
|
||||
self.window = webview.create_window(
|
||||
self.app.config['WINDOW_TITLE'],
|
||||
f'http://{self.host}:{self.port}',
|
||||
width=self.app.config['WINDOW_WIDTH'],
|
||||
height=self.app.config['WINDOW_HEIGHT'],
|
||||
min_size=(self.app.config['WINDOW_MIN_WIDTH'], self.app.config['WINDOW_MIN_HEIGHT']),
|
||||
)
|
||||
|
||||
# Set window close handler
|
||||
self.window.events.closing += self._on_window_closing
|
||||
|
||||
print("Webview window created, starting webview...")
|
||||
webview.start(debug=True)
|
||||
print("Webview closed.")
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up resources before shutdown."""
|
||||
# Terminate the server process
|
||||
if self.server_process:
|
||||
print("Shutting down server...")
|
||||
try:
|
||||
# Only terminate the specific server process, not its parent
|
||||
self.server_process.terminate()
|
||||
|
||||
# Wait for termination with timeout
|
||||
try:
|
||||
self.server_process.wait(timeout=5)
|
||||
print("Server process terminated gracefully.")
|
||||
except subprocess.TimeoutExpired:
|
||||
print("Server didn't terminate gracefully, forcing kill...")
|
||||
self.server_process.kill()
|
||||
try:
|
||||
self.server_process.wait(timeout=2)
|
||||
print("Server process killed.")
|
||||
except subprocess.TimeoutExpired:
|
||||
print("Failed to kill server process.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during server cleanup: {e}")
|
||||
|
||||
self.server_process = None
|
||||
|
||||
# Additional cleanup for any resources, cache, etc.
|
||||
print("Cleanup complete.")
|
||||
|
||||
|
||||
def main():
|
||||
"""Application entry point."""
|
||||
client = EveAIClient()
|
||||
try:
|
||||
client.start()
|
||||
finally:
|
||||
# This ensures cleanup runs even if start() raises an exception
|
||||
client.cleanup()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user