Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions backend/app/config/settings.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Model Exports Path
MODEL_EXPORTS_PATH = "app/models/ONNX_Exports"

# Microservice URLs
SYNC_MICROSERVICE_URL = "http://localhost:52124"

CONFIDENCE_PERCENT = 0.6
# Object Detection Models:
SMALL_OBJ_DETECTION_MODEL = f"{MODEL_EXPORTS_PATH}/YOLOv11_Small.onnx"
Expand All @@ -23,3 +20,4 @@
DATABASE_PATH = "app/database/PictoPy.db"
THUMBNAIL_IMAGES_PATH = "./images/thumbnails"
IMAGES_PATH = "./images"
BACKEND_URL = "http://localhost:52123"
97 changes: 97 additions & 0 deletions backend/app/routes/watcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import asyncio
from fastapi import APIRouter, HTTPException
from app.utils.watcher import (
watcher_util_start_folder_watcher,
watcher_util_stop_folder_watcher,
watcher_util_restart_folder_watcher,
watcher_util_is_watcher_running,
watcher_util_get_watcher_info,
)
from app.schemas.watcher import (
WatcherStatusResponse,
WatcherControlResponse,
)

router = APIRouter()


@router.get("/status", response_model=WatcherStatusResponse)
async def get_watcher_status():
"""Get folder watcher status."""
try:
watcher_info = await asyncio.to_thread(watcher_util_get_watcher_info)
return WatcherStatusResponse(**watcher_info)
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Error getting watcher status: {str(e)}"
)


@router.post("/restart", response_model=WatcherControlResponse)
async def restart_watcher():
"""Restart the folder watcher with fresh data from database."""
try:
success = await asyncio.to_thread(watcher_util_restart_folder_watcher)
watcher_info = await asyncio.to_thread(watcher_util_get_watcher_info)
if success:
return WatcherControlResponse(
success=True,
message="Folder watcher restarted successfully",
watcher_info=WatcherStatusResponse(**watcher_info),
)
else:
return WatcherControlResponse(
success=False,
message="Failed to restart folder watcher",
watcher_info=WatcherStatusResponse(**watcher_info),
)
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Error restarting watcher: {str(e)}"
)


@router.post("/stop", response_model=WatcherControlResponse)
async def stop_watcher():
"""Stop the folder watcher."""
try:
await asyncio.to_thread(watcher_util_stop_folder_watcher)
watcher_info = await asyncio.to_thread(watcher_util_get_watcher_info)
return WatcherControlResponse(
success=True,
message="Folder watcher stopped",
watcher_info=WatcherStatusResponse(**watcher_info),
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error stopping watcher: {str(e)}")


@router.post("/start", response_model=WatcherControlResponse)
async def start_watcher():
"""Start the folder watcher."""
try:
is_running = await asyncio.to_thread(watcher_util_is_watcher_running)
if is_running:
watcher_info = await asyncio.to_thread(watcher_util_get_watcher_info)
return WatcherControlResponse(
success=False,
message="Watcher is already running",
watcher_info=WatcherStatusResponse(**watcher_info),
)

success = await asyncio.to_thread(watcher_util_start_folder_watcher)
watcher_info = await asyncio.to_thread(watcher_util_get_watcher_info)
if success:
return WatcherControlResponse(
success=True,
message="Folder watcher started successfully",
watcher_info=WatcherStatusResponse(**watcher_info),
)
else:
return WatcherControlResponse(
success=False,
message="Failed to start folder watcher",
watcher_info=WatcherStatusResponse(**watcher_info),
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error starting watcher: {str(e)}")
33 changes: 33 additions & 0 deletions backend/app/schemas/watcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from pydantic import BaseModel
from typing import List, Optional


class WatchedFolder(BaseModel):
"""Schema for a watched folder."""

id: str
path: str


class WatcherStatusResponse(BaseModel):
"""Watcher status endpoint response schema."""

is_running: bool
folders_count: int
thread_alive: bool
thread_id: Optional[int]
watched_folders: List[WatchedFolder]


class WatcherControlResponse(BaseModel):
"""Schema for watcher control operations (start/stop/restart)."""

success: bool
message: str
watcher_info: WatcherStatusResponse


class WatcherErrorResponse(BaseModel):
"""Schema for watcher error responses."""

detail: str
26 changes: 8 additions & 18 deletions backend/app/utils/API.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
import requests
from app.config.settings import SYNC_MICROSERVICE_URL
import logging

logger = logging.getLogger(__name__)


def API_util_restart_sync_microservice_watcher():
"""
Send a POST request to restart the sync microservice watcher.
Restart the folder watcher (now integrated into the backend).

Returns:
bool: True if request was successful, False otherwise
bool: True if restart was successful, False otherwise
"""
try:
url = f"{SYNC_MICROSERVICE_URL}/watcher/restart"
response = requests.post(url, timeout=30)

if response.status_code == 200:
logger.info("Successfully restarted sync microservice watcher")
from app.utils.watcher import watcher_util_restart_folder_watcher
success = watcher_util_restart_folder_watcher()
if success:
logger.info("Successfully restarted folder watcher")
return True
else:
logger.warning(
f"Failed to restart sync microservice watcher. Status code: {response.status_code}"
)
logger.warning("Failed to restart folder watcher")
return False

except requests.exceptions.RequestException as e:
logger.error(f"Error communicating with sync microservice: {e}")
return False
except Exception as e:
logger.error(f"Unexpected error restarting sync microservice watcher: {e}")
logger.error(f"Unexpected error restarting folder watcher: {e}")
return False
Loading