Skip to content

Commit 0c6d598

Browse files
authored
Start server before workload and registry ingestion (#49)
Speed up server startup by moving ingestion to background - Removed blocking registry and workload ingestion from server startup in `cli.py` - Server now starts immediately after configuration validation and database migration - Ingestion now happens asynchronously in the polling manager background thread - Eliminated artificial startup delay in `polling_manager.py` that was waiting for minimum polling interval - Background thread starts polling after 3-second grace period instead of waiting for initial ingestion to complete - Server is ready to accept connections in seconds instead of minutes - Ingestion failures no longer prevent server startup - polling will retry automatically This change transforms the startup from synchronous blocking model to asynchronous background processing, dramatically reducing time-to-ready while maintaining the same functionality through the existing polling mechanism.
1 parent 6aee590 commit 0c6d598

File tree

2 files changed

+1
-56
lines changed

2 files changed

+1
-56
lines changed

src/mcp_optimizer/cli.py

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import asyncio
21
import os
32
import signal
43
from pathlib import Path
@@ -10,9 +9,7 @@
109

1110
from mcp_optimizer.config import ConfigurationError, MCPOptimizerConfig, get_config
1211
from mcp_optimizer.configure_logging import configure_logging
13-
from mcp_optimizer.db.config import DatabaseConfig, run_migrations
14-
from mcp_optimizer.embeddings import EmbeddingManager
15-
from mcp_optimizer.ingestion import IngestionService
12+
from mcp_optimizer.db.config import run_migrations
1613
from mcp_optimizer.polling_manager import configure_polling, shutdown_polling
1714
from mcp_optimizer.server import initialize_server_components
1815
from mcp_optimizer.toolhive.toolhive_client import ToolhiveClient
@@ -218,54 +215,6 @@ def main(**kwargs: Any) -> None:
218215
initialize_server_components(config)
219216

220217
try:
221-
# Pass config values to components instead of using get_config()
222-
db_config = DatabaseConfig(database_url=config.async_db_url)
223-
embedding_manager = EmbeddingManager(
224-
model_name=config.embedding_model_name,
225-
enable_cache=config.enable_embedding_cache,
226-
threads=config.embedding_threads,
227-
fastembed_cache_path=config.fastembed_cache_path,
228-
)
229-
ingestion_service = IngestionService(
230-
db_config,
231-
embedding_manager,
232-
mcp_timeout=config.mcp_timeout,
233-
registry_ingestion_batch_size=config.registry_ingestion_batch_size,
234-
workload_ingestion_batch_size=config.workload_ingestion_batch_size,
235-
encoding=config.encoding,
236-
skipped_workloads=config.skipped_workloads,
237-
runtime_mode=config.runtime_mode,
238-
k8s_api_server_url=config.k8s_api_server_url,
239-
k8s_namespace=config.k8s_namespace,
240-
k8s_all_namespaces=config.k8s_all_namespaces,
241-
)
242-
243-
async def run_ingestion():
244-
"""Run ingestion tasks in a single event loop."""
245-
await ingestion_service.ingest_registry(toolhive_client=toolhive_client)
246-
await ingestion_service.ingest_workloads(toolhive_client=toolhive_client)
247-
# Dispose the database engine to prevent event loop conflicts
248-
# The server will create a new engine in its own event loop
249-
await db_config.close()
250-
251-
logger.info("Starting initial ingestion process")
252-
try:
253-
asyncio.run(run_ingestion())
254-
logger.info("Initial ingestion process completed")
255-
except Exception as e:
256-
# Import here to avoid circular dependency
257-
from mcp_optimizer.toolhive.toolhive_client import ToolhiveConnectionError
258-
259-
if isinstance(e, ToolhiveConnectionError):
260-
logger.critical(
261-
"Unable to connect to ToolHive after exhausting all retries. "
262-
"Please ensure ToolHive is running and accessible.",
263-
error=str(e),
264-
)
265-
raise click.ClickException(f"Failed to connect to ToolHive: {e}. Exiting.") from e
266-
# Re-raise other exceptions
267-
raise
268-
269218
# Configure polling manager for the server
270219
logger.info(
271220
"Configuring polling manager",

src/mcp_optimizer/polling_manager.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,6 @@ async def start_polling(self) -> None:
301301
# Store the event loop for later use by targeted polling
302302
self._loop = asyncio.get_running_loop()
303303

304-
startup_time_sec = min(self.workload_polling_interval, self.registry_polling_interval)
305-
logger.info("Delaying polling start to allow server startup", seconds=startup_time_sec)
306-
await asyncio.sleep(startup_time_sec)
307-
308304
logger.info(
309305
"Creating polling tasks",
310306
workload_interval_seconds=self.workload_polling_interval,

0 commit comments

Comments
 (0)