Hopsakee's picture
Upload folder using huggingface_hub
5fe3652 verified
"""Main entry point for the Fabric to Espanso conversion process."""
from typing import Optional
import sys
import signal
import logging
from contextlib import contextmanager
from src.fabrics_processor.database import initialize_qdrant_database
from src.fabrics_processor.file_change_detector import detect_file_changes
from src.fabrics_processor.database_updater import update_qdrant_database
from src.fabrics_processor.output_files_generator import generate_yaml_file
from src.fabrics_processor.logger import setup_logger
from src.fabrics_processor.config import config
from src.fabrics_processor.deduplicator import remove_duplicates
from src.fabrics_processor.exceptions import (
DatabaseConnectionError,
DatabaseInitializationError
)
# Setup logger
logger = setup_logger()
class GracefulExit(SystemExit):
"""Custom exception for graceful shutdown."""
pass
def signal_handler(signum, frame):
"""Handle shutdown signals gracefully."""
logger.info(f"Received signal {signum}. Initiating graceful shutdown...")
raise GracefulExit()
@contextmanager
def managed_qdrant_client():
"""Context manager for handling Qdrant client lifecycle."""
client = None
try:
client = initialize_qdrant_database()
yield client
finally:
if client:
logger.info("Closing Qdrant client connection...")
client.close()
logger.info("Qdrant client connection closed")
def process_changes(client) -> bool:
"""Process file changes and update database and YAML files.
Args:
client: Initialized Qdrant client
Returns:
bool: True if processing was successful, False otherwise
"""
try:
# Detect file changes
new_files, modified_files, deleted_files = detect_file_changes(client, config.fabric_patterns_folder)
# Log the results
if new_files:
logger.info(f"New files: {[file['filename'] for file in new_files]}")
if modified_files:
logger.info(f"Modified files: {[file['filename'] for file in modified_files]}")
if deleted_files:
logger.info(f"Deleted files: {deleted_files}")
# Track changes for summary
duplicates_removed = 0
# Update database if there are changes
if any([new_files, modified_files, deleted_files]):
logger.info("Changes detected. Updating database...")
update_qdrant_database(client, config.embedding.collection_name, new_files, modified_files, deleted_files)
# Deduplicate entries after updating the database
logger.info("Checking for and removing duplicate entries...")
duplicates_removed = remove_duplicates(client, config.embedding.collection_name)
if duplicates_removed > 0:
logger.info(f"Removed {duplicates_removed} duplicate entries from the database")
# Always generate output files to ensure consistency
generate_yaml_file(client, config.yaml_output_folder)
# Generate summary message
total_entries = len(client.scroll(collection_name=config.embedding.collection_name, limit=10000)[0])
summary_message = f"Database update summary: {len(new_files)} added, {len(modified_files)} modified, {len(deleted_files)} deleted, {duplicates_removed} duplicates removed. Total entries: {total_entries}"
logger.info(summary_message)
return True
except Exception as e:
logger.error(f"Error processing changes: {str(e)}", exc_info=True)
return False
def main() -> Optional[int]:
"""Main application entry point.
Returns:
Optional[int]: Exit code, None if successful, 1 if error
"""
# Setup signal handlers
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
logger.info("Fabric to Espanso conversion process started")
# Log configuration
logger.info(f"Using configuration:")
logger.info(f" Database URL: {config.database.url}")
logger.info(f" Fabric patterns folder: {config.fabric_patterns_folder}")
logger.info(f" YAML output folder: {config.yaml_output_folder}")
logger.info(f" Obsidian textgenerator markdown output folder: {config.markdown_output_folder}")
logger.info(f" Obsidian personal prompts input folder: {config.obsidian_input_folder}")
# Process changes with managed client
with managed_qdrant_client() as client:
if process_changes(client):
logger.info("Fabric to Espanso conversion completed successfully")
return None
else:
logger.error("Fabric to Espanso conversion completed with errors")
return 1
except GracefulExit:
logger.info("Gracefully shutting down...")
return None
except (DatabaseConnectionError, DatabaseInitializationError) as e:
logger.error(f"Database error: {str(e)}")
return 1
except Exception as e:
logger.error(f"Unexpected error: {str(e)}", exc_info=True)
return 1
if __name__ == "__main__":
sys.exit(main() or 0)