Start a single service.
(self, service_name: str, config: ServiceConfig)
| 246 | self.logger.warning(f"⚠️ Could not check/pull models: {e}") |
| 247 | |
| 248 | def start_service(self, service_name: str, config: ServiceConfig) -> bool: |
| 249 | """Start a single service.""" |
| 250 | if service_name in self.processes: |
| 251 | self.logger.warning(f"⚠️ {service_name} already running") |
| 252 | return True |
| 253 | |
| 254 | # Check if port is in use |
| 255 | if self.is_port_in_use(config.port): |
| 256 | self.logger.warning(f"⚠️ Port {config.port} already in use, skipping {service_name}") |
| 257 | return not config.required |
| 258 | |
| 259 | self.logger.info(f"🔄 Starting {service_name} on port {config.port}...") |
| 260 | |
| 261 | try: |
| 262 | # Setup environment |
| 263 | env = os.environ.copy() |
| 264 | if config.env: |
| 265 | env.update(config.env) |
| 266 | |
| 267 | # Start process |
| 268 | process = subprocess.Popen( |
| 269 | config.command, |
| 270 | cwd=config.cwd, |
| 271 | env=env, |
| 272 | stdout=subprocess.PIPE, |
| 273 | stderr=subprocess.STDOUT, |
| 274 | text=True, |
| 275 | bufsize=1, |
| 276 | universal_newlines=True |
| 277 | ) |
| 278 | |
| 279 | self.processes[service_name] = process |
| 280 | |
| 281 | # Start log monitoring thread |
| 282 | log_thread = threading.Thread( |
| 283 | target=self._monitor_service_logs, |
| 284 | args=(service_name, process), |
| 285 | daemon=True |
| 286 | ) |
| 287 | log_thread.start() |
| 288 | self.log_threads[service_name] = log_thread |
| 289 | |
| 290 | # Wait for startup |
| 291 | time.sleep(config.startup_delay) |
| 292 | |
| 293 | # Check if process is still running |
| 294 | if process.poll() is None: |
| 295 | self.logger.info(f"✅ {service_name} started successfully (PID: {process.pid})") |
| 296 | return True |
| 297 | else: |
| 298 | self.logger.error(f"❌ {service_name} failed to start") |
| 299 | return False |
| 300 | |
| 301 | except Exception as e: |
| 302 | self.logger.error(f"❌ Failed to start {service_name}: {e}") |
| 303 | return False |
| 304 | |
| 305 | def _monitor_service_logs(self, service_name: str, process: subprocess.Popen): |
no test coverage detected