syncmaster4 / startup.py
aseelflihan's picture
Initial clean upload
f93a960
#!/usr/bin/env python3
"""
Startup Script for SyncMaster
ู†ู‚ุทุฉ ุฏุฎูˆู„ ู…ูˆุญุฏุฉ ุชุถู…ู† ุชุดุบูŠู„ ุฌู…ูŠุน ุงู„ู…ูƒูˆู†ุงุช ุงู„ู…ุทู„ูˆุจุฉ
"""
import os
import sys
import time
import logging
import subprocess
import signal
import atexit
from pathlib import Path
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
class SyncMasterLauncher:
def __init__(self):
self.recorder_process = None
self.streamlit_process = None
self.cleanup_registered = False
def setup_cleanup(self):
"""Setup cleanup handlers"""
if not self.cleanup_registered:
atexit.register(self.cleanup)
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGTERM, self.signal_handler)
self.cleanup_registered = True
def signal_handler(self, signum, frame):
"""Handle termination signals"""
logging.info(f"Received signal {signum}, cleaning up...")
self.cleanup()
sys.exit(0)
def cleanup(self):
"""Clean up all processes"""
logging.info("๐Ÿงน Cleaning up processes...")
if self.recorder_process and self.recorder_process.poll() is None:
try:
self.recorder_process.terminate()
self.recorder_process.wait(timeout=5)
logging.info("โœ… Recorder server terminated")
except:
try:
self.recorder_process.kill()
logging.info("โš ๏ธ Recorder server killed")
except:
pass
if self.streamlit_process and self.streamlit_process.poll() is None:
try:
self.streamlit_process.terminate()
self.streamlit_process.wait(timeout=5)
logging.info("โœ… Streamlit server terminated")
except:
try:
self.streamlit_process.kill()
logging.info("โš ๏ธ Streamlit server killed")
except:
pass
def start_recorder_server(self):
"""Start the recorder server"""
try:
logging.info("๐Ÿš€ Starting recorder server...")
self.recorder_process = subprocess.Popen(
[sys.executable, 'recorder_server.py'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# Wait for server to start
time.sleep(3)
# Check if process is running
if self.recorder_process.poll() is None:
# Verify server is responding
try:
import requests
response = requests.get('http://localhost:5001/record', timeout=5)
if response.status_code == 200:
logging.info("โœ… Recorder server started successfully on port 5001")
return True
else:
logging.warning(f"โš ๏ธ Recorder server responded with status: {response.status_code}")
except Exception as e:
logging.warning(f"โš ๏ธ Could not verify recorder server: {e}")
# Server process is running even if verification failed
return True
else:
logging.error("โŒ Recorder server process failed to start")
return False
except Exception as e:
logging.error(f"โŒ Failed to start recorder server: {e}")
return False
def start_streamlit_app(self, port=5050, host="0.0.0.0"):
"""Start the Streamlit application"""
try:
logging.info(f"๐Ÿš€ Starting Streamlit app on {host}:{port}...")
cmd = [
sys.executable, '-m', 'streamlit', 'run', 'app.py',
'--server.port', str(port),
'--server.address', host,
'--server.headless', 'true',
'--browser.gatherUsageStats', 'false'
]
self.streamlit_process = subprocess.Popen(cmd)
# Wait a bit for Streamlit to start
time.sleep(5)
if self.streamlit_process.poll() is None:
logging.info(f"โœ… Streamlit app started successfully on http://{host}:{port}")
return True
else:
logging.error("โŒ Streamlit app failed to start")
return False
except Exception as e:
logging.error(f"โŒ Failed to start Streamlit app: {e}")
return False
def launch_integrated(self):
"""Launch with integrated server (recommended for HuggingFace)"""
logging.info("๐Ÿš€ Launching SyncMaster with integrated server...")
self.setup_cleanup()
# Start Streamlit with integrated server
try:
# Import to trigger integrated server startup
import app
# Run Streamlit
import streamlit.web.cli as stcli
import sys
# Set command line arguments for Streamlit
sys.argv = [
"streamlit", "run", "app.py",
"--server.port", "5050",
"--server.address", "0.0.0.0",
"--server.headless", "true",
"--browser.gatherUsageStats", "false"
]
# Run Streamlit CLI
stcli.main()
except Exception as e:
logging.error(f"โŒ Failed to launch integrated mode: {e}")
return False
def launch_separate(self):
"""Launch with separate processes (development mode)"""
logging.info("๐Ÿš€ Launching SyncMaster with separate processes...")
self.setup_cleanup()
# Start recorder server first
if not self.start_recorder_server():
logging.error("โŒ Failed to start recorder server, aborting...")
return False
# Start Streamlit app
if not self.start_streamlit_app():
logging.error("โŒ Failed to start Streamlit app, aborting...")
self.cleanup()
return False
logging.info("โœ… All services started successfully!")
logging.info("๐ŸŒ Access the application at: http://localhost:5050")
logging.info("๐ŸŽ™๏ธ Recorder API available at: http://localhost:5001")
try:
# Keep the main process alive
while True:
time.sleep(1)
# Check if processes are still running
if self.recorder_process and self.recorder_process.poll() is not None:
logging.error("โŒ Recorder server process died")
break
if self.streamlit_process and self.streamlit_process.poll() is not None:
logging.error("โŒ Streamlit app process died")
break
except KeyboardInterrupt:
logging.info("๐Ÿ‘‹ Shutting down...")
finally:
self.cleanup()
def main():
"""Main entry point"""
launcher = SyncMasterLauncher()
# Check if running in HuggingFace or similar environment
if os.getenv('SPACE_ID') or '--integrated' in sys.argv:
# Use integrated mode for cloud deployments
launcher.launch_integrated()
else:
# Use separate processes for local development
launcher.launch_separate()
if __name__ == "__main__":
main()