Best Practices
- Optimize database queries to minimize load
- Implement pagination for large data sets
- Use async/await for I/O-bound operations
- Monitor and optimize database indexes
- Implement connection pooling for database connections
- Consider partitioning strategies for large tables
- Optimize geospatial queries using appropriate PostGIS functions
- Use TimescaleDB hypertables for efficient time-series data storage and querying
Database Optimization
- Use appropriate indexes for frequently queried fields
- Optimize SQL queries for performance
- Use database connection pooling
- Implement caching for frequently accessed data
- Monitor query performance and set up alerts for slow queries
- Use EXPLAIN ANALYZE to identify performance bottlenecks
API Optimization
- Use async/await for I/O-bound operations
- Implement pagination for endpoints that return large datasets
- Use appropriate HTTP status codes and headers
- Implement rate limiting for public APIs
- Use connection pooling for external API calls
Resource Management
- Close database connections and file handles properly
- Use context managers for resource cleanup
- Monitor memory usage and optimize memory-intensive operations
- Implement proper connection pooling for database access
Security Guidelines
- Never store sensitive information in code repositories
- Use environment variables for configuration
- Implement proper authentication and authorization
- Validate all user inputs using SQLModel
- Protect against common web vulnerabilities (XSS, CSRF, SQL injection)
- Use HTTPS for all communications
- Implement rate limiting to prevent abuse
- Regularly update dependencies to address security vulnerabilities
- Apply principle of least privilege for database access
- Implement data encryption for sensitive information
- Validate all user inputs using Pydantic models (within SQLModel).
- Implement strict type checking for API parameters.
- Use parameterized queries to prevent SQL injection.
Authentication and Authorization
- Implement API key authentication as specified in requirement #21.
- Validate API keys for all protected endpoints.
- Implement role-based access control for different user types.
Data Protection
- Encrypt sensitive data in transit and at rest.
- Implement proper error handling to avoid leaking sensitive information.
- Follow the principle of least privilege for database access.
Error Handling and Logging Standards
Error Hierarchy:
- Define a custom exception hierarchy for different error types
- Use specific exception types for different error scenarios
Custom Exception Examples
# Base exception for all application-specific errors
class InfDBError(Exception):
"""Base exception for all InfDB-specific errors."""
def __init__(self, message, details=None):
super().__init__(message)
self.details = details
# Domain-specific exceptions
class DatabaseConnectionError(InfDBError):
"""Raised when a database connection cannot be established."""
pass
class GeospatialError(InfDBError):
"""Base exception for geospatial-related errors."""
pass
class InvalidCoordinateError(GeospatialError):
"""Raised when invalid coordinates are provided."""
pass
# Usage example
try:
# Some operation that might fail
result = repository.get_raster_center(building_id, resolution)
if not result:
raise InvalidCoordinateError(
f"No raster found for building {building_id} at resolution {resolution}",
details={"building_id": building_id, "resolution": resolution}
)
except InvalidCoordinateError as e:
# Handle the specific error
logger.error(f"Coordinate error: {str(e)}", extra={"details": e.details})
raise HTTPException(status_code=404, detail=str(e))
except DatabaseConnectionError as e:
# Handle database connection errors
logger.critical(f"Database connection failed: {str(e)}")
raise HTTPException(status_code=503, detail="Service temporarily unavailable")
except InfDBError as e:
# Handle any other application-specific errors
logger.error(f"Application error: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
except Exception as e:
# Handle unexpected errors
logger.exception(f"Unexpected error: {str(e)}")
raise HTTPException(status_code=500, detail="An unexpected error occurred")
Error Messages
- Provide clear, actionable error messages.
- Include relevant context in error messages.
- Use structured error responses for API endpoints:
{
"error": "Invalid weather parameter",
"details": "Parameter 'temperature' is not available for the specified date range."
}
Logging
- Use the Python
logging module for all logging
- Configure appropriate log levels
- Include relevant context in log messages (user ID, request ID, etc.)
- Structure logs for easy parsing and analysis
- Avoid logging sensitive information
Logging Levels:
- DEBUG: Detailed information for debugging
- INFO: Confirmation that things are working as expected
- WARNING: Indication that something unexpected happened
- ERROR: Due to a more serious problem, the software couldn't perform some function
- CRITICAL: A serious error indicating the program may be unable to continue running
{timestamp} [{level}] {module}: {message} {context}