Advanced Features¶
Advanced features provide powerful capabilities for complex dependency injection scenarios, including resource management, diagnostics, performance optimization, and thread safety.
🎯 Overview¶
InjectQ's advanced features help you:
- Manage resources - Automatic cleanup and lifecycle management
- Diagnose issues - Debug dependency resolution and detect problems
- Optimize performance - Lazy loading, caching, and efficient resolution
- Ensure thread safety - Safe concurrent dependency injection
- Handle circular dependencies - Detect and resolve dependency cycles
- Profile performance - Monitor and analyze DI performance
Advanced Features Categories¶
# Resource Management
@injectq.resource
class DatabaseConnection:
def __init__(self):
self.connection = None
async def initialize(self):
self.connection = await create_connection()
async def cleanup(self):
if self.connection:
await self.connection.close()
# Diagnostics
container = InjectQ()
container.enable_diagnostics()
# Analyze dependency graph
graph = container.analyze_dependencies()
print(f"Circular dependencies: {graph.cycles}")
# Performance Optimization
@injectq.lazy
class ExpensiveService:
def __init__(self):
# Heavy initialization
time.sleep(1)
# Thread Safety
container = ThreadSafeContainer()
# Safe for concurrent access
📁 Advanced Features Structure¶
This section covers:
- Resource Management - Automatic resource lifecycle management
- Diagnostics - Debugging and dependency analysis tools
- Performance Optimization - Lazy loading, caching, and optimization techniques
- Thread Safety - Concurrent access and synchronization
- Circular Dependencies - Detection and resolution strategies
- Profiling - Performance monitoring and analysis
🚀 Quick Start¶
Basic Resource Management¶
from injectq import resource, InjectQ
@resource
class DatabasePool:
def __init__(self):
self.pool = None
async def initialize(self):
self.pool = await create_database_pool()
async def dispose(self):
if self.pool:
await self.pool.close()
def main():
container = InjectQ()
container.bind(DatabasePool, DatabasePool())
# Use container
async with container:
db_pool = container.get(DatabasePool)
# Resource automatically managed
Basic Diagnostics¶
container = InjectQ()
container.enable_diagnostics()
# Bind services
container.bind(IService, Service())
# Analyze dependencies
report = container.generate_diagnostic_report()
print(report)
# Output:
# Dependency Graph Analysis:
# - Total services: 5
# - Circular dependencies: 0
# - Resolution time: 0.002s
# - Memory usage: 1.2MB
Basic Performance Optimization¶
from injectq import lazy, cached
@lazy
class ExpensiveService:
def __init__(self):
# Heavy initialization - only when first accessed
self.data = load_large_dataset()
@cached
class ComputationService:
def heavy_calculation(self, input_data):
# Result cached for same input
return perform_expensive_calculation(input_data)
container = InjectQ()
container.bind(ExpensiveService, ExpensiveService())
container.bind(ComputationService, ComputationService())
# First access triggers initialization
service = container.get(ExpensiveService) # Lazy loading
# Subsequent calls use cached result
result1 = container.get(ComputationService).heavy_calculation(data)
result2 = container.get(ComputationService).heavy_calculation(data)
assert result1 is result2 # Cached
🎨 Advanced Patterns¶
Resource Lifecycle Management¶
@resource
class ConnectionManager:
def __init__(self, config: DatabaseConfig):
self.config = config
self.connections = {}
async def get_connection(self, name: str):
if name not in self.connections:
self.connections[name] = await create_connection(self.config)
return self.connections[name]
async def dispose(self):
for conn in self.connections.values():
await conn.close()
self.connections.clear()
# Usage with automatic cleanup
async def handle_request(container):
conn_manager = container.get(ConnectionManager)
async with container.resource_scope():
conn = await conn_manager.get_connection("main")
# Connection automatically returned to pool on scope exit
Diagnostic Monitoring¶
container = InjectQ()
container.enable_diagnostics()
# Monitor resolution performance
with container.monitor_resolution():
service = container.get(IService)
# Get performance metrics
metrics = container.get_resolution_metrics()
print(f"Average resolution time: {metrics.avg_time}")
print(f"Peak memory usage: {metrics.peak_memory}")
print(f"Cache hit rate: {metrics.cache_hit_rate}")
# Detect potential issues
issues = container.detect_issues()
for issue in issues:
print(f"Issue: {issue.description}")
print(f"Severity: {issue.severity}")
print(f"Suggestion: {issue.suggestion}")
Thread-Safe Operations¶
from injectq import ThreadSafeContainer
container = ThreadSafeContainer()
# Safe for concurrent access
@singleton
class SharedCache:
def __init__(self):
self.data = {}
self.lock = threading.Lock()
def get(self, key):
with self.lock:
return self.data.get(key)
def set(self, key, value):
with self.lock:
self.data[key] = value
container.bind(SharedCache, SharedCache())
# Concurrent usage
def worker_thread(container, thread_id):
cache = container.get(SharedCache)
cache.set(f"thread_{thread_id}", f"data_{thread_id}")
threads = [threading.Thread(target=worker_thread, args=(container, i))
for i in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
# All data safely stored
cache = container.get(SharedCache)
assert len(cache.data) == 10
🔧 Configuration and Setup¶
Advanced Container Configuration¶
from injectq import InjectQ, ContainerConfig
config = ContainerConfig(
# Diagnostics
enable_diagnostics=True,
diagnostic_level="detailed",
# Performance
enable_caching=True,
cache_size=1000,
lazy_loading=True,
# Thread safety
thread_safe=True,
max_threads=10,
# Resource management
auto_dispose_resources=True,
resource_timeout=30.0,
# Circular dependency detection
detect_circular_deps=True,
circular_dep_strategy="fail_fast"
)
container = InjectQ(config)
Module-Based Advanced Setup¶
from injectq import Module
class AdvancedFeaturesModule(Module):
def configure(self, binder):
# Resource management
binder.bind_resource(DatabasePool())
binder.bind_resource(CacheManager())
# Lazy services
binder.bind_lazy(ExpensiveService)
# Cached services
binder.bind_cached(ComputationService)
# Thread-safe services
binder.bind_thread_safe(SharedStateService)
class MonitoringModule(Module):
def configure(self, binder):
# Diagnostic services
binder.bind(IDiagnosticsService, DiagnosticsService())
binder.bind(IPerformanceMonitor, PerformanceMonitor())
# Profiling services
binder.bind(IProfiler, ProfilerService())
# Create container with advanced features
container = InjectQ()
container.install(AdvancedFeaturesModule())
container.install(MonitoringModule())
🚨 Common Advanced Scenarios¶
High-Performance Applications¶
# Optimized for performance
container = InjectQ(ContainerConfig(
enable_caching=True,
lazy_loading=True,
thread_safe=True,
cache_size=5000
))
@cached(ttl=300) # 5-minute cache
class APICache:
async def fetch_data(self, endpoint):
# Expensive API call
return await http_client.get(endpoint)
@lazy
class MLModel:
def __init__(self):
# Load 2GB model - only when needed
self.model = load_ml_model()
# Usage
api_cache = container.get(APICache)
data = await api_cache.fetch_data("/api/data") # Cached
ml_model = container.get(MLModel) # Lazy loaded
prediction = ml_model.predict(input_data)
Complex Resource Management¶
@resource
class ResourcePool:
def __init__(self):
self.available = set()
self.in_use = set()
self.lock = asyncio.Lock()
async def acquire(self):
async with self.lock:
if not self.available:
resource = await self.create_resource()
self.available.add(resource)
resource = self.available.pop()
self.in_use.add(resource)
return resource
async def release(self, resource):
async with self.lock:
self.in_use.remove(resource)
self.available.add(resource)
async def dispose(self):
async with self.lock:
all_resources = self.available | self.in_use
for resource in all_resources:
await self.cleanup_resource(resource)
# Automatic resource management
async def process_request(container):
pool = container.get(ResourcePool)
async with container.resource_scope():
resource = await pool.acquire()
try:
# Use resource
result = await process_with_resource(resource)
return result
finally:
await pool.release(resource)
Diagnostic-Driven Development¶
container = InjectQ()
container.enable_diagnostics()
# Development-time diagnostics
if os.getenv("ENV") == "development":
container.enable_detailed_logging()
container.enable_performance_monitoring()
# Analyze application startup
with container.monitor_initialization():
# Bind all services
container.install(AllModules())
# Generate diagnostic report
report = container.generate_report()
if report.has_issues():
print("Diagnostic Issues Found:")
for issue in report.issues:
print(f"- {issue.level}: {issue.message}")
if issue.suggestion:
print(f" Suggestion: {issue.suggestion}")
# Performance analysis
metrics = container.get_performance_metrics()
if metrics.avg_resolution_time > 0.1: # 100ms
print("Warning: Slow dependency resolution detected")
print(f"Average time: {metrics.avg_resolution_time}s")
📊 Performance and Monitoring¶
Performance Metrics¶
# Track performance
container = InjectQ()
container.enable_performance_monitoring()
# Application usage
for _ in range(1000):
service = container.get(IService)
result = service.do_work()
# Get performance report
report = container.get_performance_report()
print(f"Total resolutions: {report.total_resolutions}")
print(f"Average time: {report.avg_resolution_time}")
print(f"Cache hit rate: {report.cache_hit_rate}")
print(f"Memory usage: {report.memory_usage}")
Health Checks¶
class HealthCheckService:
def __init__(self, container: InjectQ):
self.container = container
async def check_health(self):
results = {}
# Check container health
results["container"] = await self.check_container_health()
# Check service health
results["services"] = await self.check_service_health()
# Check resource health
results["resources"] = await self.check_resource_health()
return results
async def check_container_health(self):
try:
# Test basic resolution
test_service = self.container.get(IService)
return {"status": "healthy", "message": "Container operational"}
except Exception as e:
return {"status": "unhealthy", "message": str(e)}
async def check_service_health(self):
services_to_check = [IService, IDatabase, ICache]
results = {}
for service_type in services_to_check:
try:
service = self.container.get(service_type)
# Test service functionality
await service.ping() # Assuming services have ping method
results[service_type.__name__] = "healthy"
except Exception as e:
results[service_type.__name__] = f"unhealthy: {e}"
return results
# Usage
health_service = HealthCheckService(container)
health = await health_service.check_health()
if health["container"]["status"] != "healthy":
print("Container health issue detected!")
# Alert system
🎯 Summary¶
Advanced features provide powerful capabilities for complex applications:
- Resource management - Automatic lifecycle management and cleanup
- Diagnostics - Debugging tools and dependency analysis
- Performance optimization - Lazy loading, caching, and efficient resolution
- Thread safety - Safe concurrent access and synchronization
- Circular dependency handling - Detection and resolution strategies
- Profiling - Performance monitoring and analysis
Key features: - Automatic resource cleanup and lifecycle management - Comprehensive diagnostic and debugging tools - Performance optimization through lazy loading and caching - Thread-safe concurrent operations - Circular dependency detection and resolution - Detailed performance profiling and monitoring
Best practices: - Use resource management for proper cleanup - Enable diagnostics in development - Optimize performance with lazy loading and caching - Ensure thread safety for concurrent applications - Monitor and profile performance regularly - Use health checks for system monitoring
Ready to dive into resource management?