Add data ingestion service proxy routes and update configs
- Add proxy routes for data ingestion service in API gateway - Register data-ingestion-service in SERVICES config - Update docker-compose to include data-ingestion-service and sensor-service dependencies - Fix import typo in sensor-service (contextual -> contextlib) - Update FTP credentials and environment variables for data-ingestion-service
This commit is contained in:
@@ -9,7 +9,7 @@ import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from fastapi import FastAPI, HTTPException, Depends, WebSocket, WebSocketDisconnect, Query, BackgroundTasks
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from contextual import asynccontextmanager
|
||||
from contextlib import asynccontextmanager
|
||||
import logging
|
||||
from typing import List, Optional, Dict, Any
|
||||
import json
|
||||
@@ -20,7 +20,7 @@ from models import (
|
||||
)
|
||||
from database import connect_to_mongo, close_mongo_connection, get_database, connect_to_redis, get_redis
|
||||
from sensor_service import SensorService
|
||||
from room_service import RoomService
|
||||
from room_service import RoomService
|
||||
from analytics_service import AnalyticsService
|
||||
from websocket_manager import WebSocketManager
|
||||
|
||||
@@ -37,16 +37,16 @@ async def lifespan(app: FastAPI):
|
||||
logger.info("Sensor Service starting up...")
|
||||
await connect_to_mongo()
|
||||
await connect_to_redis()
|
||||
|
||||
|
||||
# Start background tasks
|
||||
asyncio.create_task(redis_subscriber_task())
|
||||
asyncio.create_task(room_metrics_aggregation_task())
|
||||
asyncio.create_task(data_cleanup_task())
|
||||
|
||||
|
||||
logger.info("Sensor Service startup complete")
|
||||
|
||||
|
||||
yield
|
||||
|
||||
|
||||
logger.info("Sensor Service shutting down...")
|
||||
await close_mongo_connection()
|
||||
logger.info("Sensor Service shutdown complete")
|
||||
@@ -88,10 +88,10 @@ async def health_check():
|
||||
try:
|
||||
db = await get_database()
|
||||
await db.command("ping")
|
||||
|
||||
|
||||
redis = await get_redis()
|
||||
await redis.ping()
|
||||
|
||||
|
||||
return HealthResponse(
|
||||
service="sensor-service",
|
||||
status="healthy",
|
||||
@@ -147,7 +147,7 @@ async def get_sensor(sensor_id: str, service: SensorService = Depends(get_sensor
|
||||
sensor = await service.get_sensor_details(sensor_id)
|
||||
if not sensor:
|
||||
raise HTTPException(status_code=404, detail="Sensor not found")
|
||||
|
||||
|
||||
return sensor
|
||||
except HTTPException:
|
||||
raise
|
||||
@@ -173,7 +173,7 @@ async def get_sensor_data(
|
||||
limit=limit,
|
||||
offset=offset
|
||||
)
|
||||
|
||||
|
||||
return DataResponse(
|
||||
data=data["readings"],
|
||||
total_count=data["total_count"],
|
||||
@@ -220,7 +220,7 @@ async def update_sensor(
|
||||
result = await service.update_sensor(sensor_id, update_data)
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="Sensor not found")
|
||||
|
||||
|
||||
return {
|
||||
"message": "Sensor updated successfully",
|
||||
"sensor_id": sensor_id,
|
||||
@@ -289,7 +289,7 @@ async def get_room(room_name: str, service: RoomService = Depends(get_room_servi
|
||||
room = await service.get_room_details(room_name)
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail="Room not found")
|
||||
|
||||
|
||||
return room
|
||||
except HTTPException:
|
||||
raise
|
||||
@@ -313,7 +313,7 @@ async def get_room_data(
|
||||
end_time=end_time,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
|
||||
return {
|
||||
"room": room_name,
|
||||
"room_metrics": data.get("room_metrics", []),
|
||||
@@ -385,7 +385,7 @@ async def export_data(
|
||||
sensor_ids=sensor_ids,
|
||||
format=format
|
||||
)
|
||||
|
||||
|
||||
return export_data
|
||||
except Exception as e:
|
||||
logger.error(f"Error exporting data: {e}")
|
||||
@@ -408,7 +408,7 @@ async def get_events(
|
||||
hours=hours,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
|
||||
return {
|
||||
"events": events,
|
||||
"count": len(events),
|
||||
@@ -429,11 +429,11 @@ async def ingest_sensor_data(
|
||||
try:
|
||||
# Process and store sensor data
|
||||
result = await service.ingest_sensor_data(sensor_data)
|
||||
|
||||
|
||||
# Schedule background tasks for analytics
|
||||
background_tasks.add_task(update_room_metrics, sensor_data)
|
||||
background_tasks.add_task(broadcast_sensor_data, sensor_data)
|
||||
|
||||
|
||||
return {
|
||||
"message": "Sensor data ingested successfully",
|
||||
"sensor_id": sensor_data.sensor_id,
|
||||
@@ -466,42 +466,42 @@ async def broadcast_sensor_data(sensor_data: SensorReading):
|
||||
async def redis_subscriber_task():
|
||||
"""Subscribe to Redis channels for real-time data"""
|
||||
logger.info("Starting Redis subscriber task")
|
||||
|
||||
|
||||
try:
|
||||
redis = await get_redis()
|
||||
pubsub = redis.pubsub()
|
||||
await pubsub.subscribe("energy_data", "sensor_events")
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
message = await pubsub.get_message(ignore_subscribe_messages=True, timeout=1.0)
|
||||
if message:
|
||||
# Process incoming message and broadcast to WebSocket clients
|
||||
await websocket_manager.broadcast_raw_data(message['data'])
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing Redis message: {e}")
|
||||
await asyncio.sleep(5)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Redis subscriber task failed: {e}")
|
||||
|
||||
async def room_metrics_aggregation_task():
|
||||
"""Periodically aggregate room-level metrics"""
|
||||
logger.info("Starting room metrics aggregation task")
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
db = await get_database()
|
||||
redis = await get_redis()
|
||||
room_service = RoomService(db, redis)
|
||||
|
||||
|
||||
# Aggregate metrics for all rooms
|
||||
await room_service.aggregate_all_room_metrics()
|
||||
|
||||
|
||||
# Sleep for 5 minutes between aggregations
|
||||
await asyncio.sleep(300)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in room metrics aggregation: {e}")
|
||||
await asyncio.sleep(600) # Wait longer on error
|
||||
@@ -509,23 +509,23 @@ async def room_metrics_aggregation_task():
|
||||
async def data_cleanup_task():
|
||||
"""Periodic cleanup of old data"""
|
||||
logger.info("Starting data cleanup task")
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
db = await get_database()
|
||||
service = SensorService(db, None)
|
||||
|
||||
|
||||
# Clean up data older than 90 days
|
||||
cleanup_date = datetime.utcnow() - timedelta(days=90)
|
||||
await service.cleanup_old_data(cleanup_date)
|
||||
|
||||
|
||||
# Sleep for 24 hours between cleanups
|
||||
await asyncio.sleep(86400)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in data cleanup task: {e}")
|
||||
await asyncio.sleep(7200) # Wait 2 hours on error
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8007)
|
||||
uvicorn.run(app, host="0.0.0.0", port=8007)
|
||||
|
||||
Reference in New Issue
Block a user