feat: integrate external scheduler for prefetch task registration

Add SchedulerClient to communicate with external scheduler service for
registering volatile prefetch tasks discovered during HybridRAG searches.

- Add scheduler_client.py with full REST API for task CRUD operations
- Add scheduler_url config setting (default: http://scheduler:8090)
- Update consolidation service to use scheduler for prefetch registration
- Add scheduler health checks to startup/shutdown lifecycle

When HybridRAG classifies web content as prefetch-worthy, it now creates
scheduled tasks that periodically refresh the volatile cache via the
external scheduler service.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-29 20:42:37 +01:00
co-authored by Claude Opus 4.5
parent c01033505b
commit 910b289c9e
4 changed files with 425 additions and 20 deletions
+46
View File
@@ -24,6 +24,7 @@ from src.clients.ollama_client import OllamaClient
from src.clients.content_extractor import ContentExtractor
from src.clients.paperless_client import PaperlessClient
from src.clients.settings_client import SettingsClient
from src.clients.scheduler_client import SchedulerClient
from src.apis import (
OpenMeteoProvider,
AggregatedNewsProvider,
@@ -202,6 +203,22 @@ def get_settings_client() -> SettingsClient:
return client
@lru_cache
def get_scheduler_client() -> SchedulerClient:
"""
Get scheduler service client singleton.
Returns:
Initialized SchedulerClient for task management
Note: Used for registering prefetch tasks discovered during HybridRAG searches
"""
settings = get_settings()
client = SchedulerClient(base_url=settings.scheduler_url)
logger.debug(f"Created Scheduler client: {settings.scheduler_url}")
return client
# =============================================================================
# External API Providers
# =============================================================================
@@ -320,6 +337,7 @@ RedisDep = Annotated[aioredis.Redis, Depends(get_redis_client)]
ContentExtractorDep = Annotated[ContentExtractor, Depends(get_content_extractor)]
PaperlessDep = Annotated[PaperlessClient, Depends(get_paperless_client)]
SettingsClientDep = Annotated[SettingsClient, Depends(get_settings_client)]
SchedulerDep = Annotated[SchedulerClient, Depends(get_scheduler_client)]
# External API provider dependencies
WeatherProviderDep = Annotated[OpenMeteoProvider, Depends(get_weather_provider)]
@@ -392,6 +410,17 @@ async def startup_clients():
else:
logger.info("○ System settings not configured")
# Check Scheduler availability
try:
scheduler = get_scheduler_client()
is_healthy = await scheduler.health_check()
if is_healthy:
logger.info(f"✓ Scheduler ready: {settings.scheduler_url}")
else:
logger.warning("✗ Scheduler not responding")
except Exception as e:
logger.error(f"✗ Scheduler health check failed: {e}")
# Qdrant, Wiki.js, SearXNG are lazy-initialized
logger.info("Service clients startup complete")
@@ -461,6 +490,14 @@ async def shutdown_clients():
except Exception as e:
logger.error(f"Error closing settings client: {e}")
# Close scheduler client
try:
scheduler = get_scheduler_client()
await scheduler.close()
logger.info("✓ Scheduler client closed")
except Exception as e:
logger.error(f"Error closing scheduler client: {e}")
logger.info("Service clients shutdown complete")
@@ -556,6 +593,14 @@ async def check_service_health() -> dict:
else:
health["system_settings"] = None # Not configured
# Scheduler
try:
scheduler = get_scheduler_client()
health["scheduler"] = await scheduler.health_check()
except Exception as e:
logger.error(f"Scheduler health check failed: {e}")
health["scheduler"] = False
return health
@@ -600,6 +645,7 @@ def get_consolidation_service() -> "ConsolidationService":
ingestion_service=get_ingestion_service(),
volatile_service=get_volatile_cache_service(),
settings_client=get_settings_client(),
scheduler_client=get_scheduler_client(),
)