- Added EveAI Client to project

- Improvements to EntitlementsDomain & Services
- Prechecks in Document domain
- Add audit information to LicenseUsage
This commit is contained in:
Josako
2025-05-17 15:56:14 +02:00
parent b4f7b210e0
commit 5c982fcc2c
260 changed files with 48683 additions and 43 deletions

View 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()