FactsDB/factsdb/api.py

189 lines
6.3 KiB
Python

"""
REST API for FactsDB service
Provides endpoints for querying facts and managing the system
"""
from flask import Flask, jsonify, request, Response
from typing import Dict, Any, List
import json
from .config import Config
from .database import DatabaseManager
from .monitoring import get_metrics, get_metrics_json, start_uptime_monitor, increment_fact_extraction, increment_file_processing, increment_error
# Start uptime monitoring
uptime_thread = start_uptime_monitor()
def create_app() -> Flask:
"""Create and configure the Flask application"""
app = Flask(__name__)
config = Config()
db_manager = DatabaseManager(config.database)
@app.route('/health', methods=['GET'])
def health():
"""Health check endpoint"""
return jsonify({
'status': 'healthy',
'service': 'FactsDB'
})
@app.route('/tables', methods=['GET'])
def get_tables():
"""Get all available tables with record counts"""
try:
tables = db_manager.get_all_tables()
return jsonify({
'tables': tables,
'total_tables': len(tables)
})
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/tables/<table_name>', methods=['GET'])
def get_table_data(table_name: str):
"""Get all facts from a specific table"""
try:
facts = db_manager.query_table(table_name)
return jsonify({
'table_name': table_name,
'facts': facts,
'count': len(facts)
})
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/tables/<table_name>/query', methods=['POST'])
def query_table(table_name: str):
"""Query facts from a specific table with custom query"""
try:
data = request.get_json()
query = data.get('query', '') if data else ''
facts = db_manager.query_table(table_name, query)
return jsonify({
'table_name': table_name,
'facts': facts,
'count': len(facts)
})
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/tables/<table_name>/count', methods=['GET'])
def get_table_count(table_name: str):
"""Get record count for a specific table"""
try:
count = db_manager.get_table_record_count(table_name)
return jsonify({
'table_name': table_name,
'count': count
})
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/fact/<int:fact_id>', methods=['GET'])
def get_fact(fact_id: int):
"""Get a specific fact by ID"""
try:
with db_manager.get_connection() as conn:
cursor = conn.execute('''
SELECT * FROM facts WHERE id = ?
''', (fact_id,))
fact = cursor.fetchone()
if fact:
return jsonify(dict(fact))
else:
return jsonify({'error': 'Fact not found'}), 404
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/search', methods=['GET'])
def search():
"""Search across all tables"""
try:
query = request.args.get('q', '')
if not query:
return jsonify({'error': 'Search query required'}), 400
# Simple search implementation - in a real system this would be more sophisticated
results = []
# Get all tables
tables = db_manager.get_all_tables()
for table in tables:
table_name = table['table_name']
facts = db_manager.query_table(table_name)
for fact in facts:
# Search in key fields
search_content = f"{fact.get('title', '')} {fact.get('summary', '')} {fact.get('main_topic', '')}"
if query.lower() in search_content.lower():
results.append({
'table_name': table_name,
'fact': fact
})
return jsonify({
'query': query,
'results': results,
'count': len(results)
})
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/version', methods=['GET'])
def version():
"""Get service version"""
return jsonify({
'version': '1.0.0',
'service': 'FactsDB'
})
@app.route('/metrics', methods=['GET'])
def metrics():
"""Prometheus metrics endpoint"""
try:
metrics_text = get_metrics()
return Response(metrics_text, mimetype='text/plain')
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/metrics/json', methods=['GET'])
def metrics_json():
"""JSON metrics endpoint"""
try:
metrics_data = get_metrics_json()
return jsonify(metrics_data)
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
@app.route('/stats', methods=['GET'])
def stats():
"""Get detailed service statistics"""
try:
db_stats = db_manager.get_database_stats()
metrics_data = get_metrics_json()
return jsonify({
'database_stats': db_stats,
'metrics': metrics_data['metrics'],
'timestamp': metrics_data['timestamp']
})
except Exception as e:
increment_error()
return jsonify({'error': str(e)}), 500
return app
# Create a default app instance
app = create_app()
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)