182 lines
6.4 KiB
Markdown
182 lines
6.4 KiB
Markdown
# Caching Implementation for Performance Optimization
|
|
|
|
This document describes the simple caching implementation added to improve authentication middleware performance in the ACC Server Manager.
|
|
|
|
## Problem Identified
|
|
|
|
The authentication middleware was experiencing performance issues due to database queries on every request:
|
|
- `HasPermission()` method was hitting the database for every permission check
|
|
- User authentication data was being retrieved from database repeatedly
|
|
- No caching mechanism for frequently accessed authentication data
|
|
|
|
## Solution Implemented
|
|
|
|
### Simple Permission Caching
|
|
|
|
Added lightweight caching to the authentication middleware using the existing cache infrastructure:
|
|
|
|
**Location**: `local/middleware/auth.go`
|
|
|
|
**Key Features**:
|
|
- **Permission Result Caching**: Cache permission check results for 10 minutes
|
|
- **Existing Cache Integration**: Uses the already available `InMemoryCache` system
|
|
- **Minimal Code Changes**: Simple addition to existing middleware without major refactoring
|
|
|
|
### Implementation Details
|
|
|
|
#### Cache Key Strategy
|
|
```go
|
|
cacheKey := fmt.Sprintf("permission:%s:%s", userID, permission)
|
|
```
|
|
|
|
#### Cache Flow
|
|
1. **Cache Check First**: Check if permission result exists in cache
|
|
2. **Database Fallback**: If cache miss, query database via membership service
|
|
3. **Cache Result**: Store result in cache with 10-minute TTL
|
|
4. **Return Result**: Return cached or fresh result
|
|
|
|
#### Core Method
|
|
```go
|
|
func (m *AuthMiddleware) hasPermissionCached(ctx context.Context, userID, permission string) (bool, error) {
|
|
cacheKey := fmt.Sprintf("permission:%s:%s", userID, permission)
|
|
|
|
// Try cache first
|
|
if cached, found := m.cache.Get(cacheKey); found {
|
|
if hasPermission, ok := cached.(bool); ok {
|
|
return hasPermission, nil
|
|
}
|
|
}
|
|
|
|
// Cache miss - check with service
|
|
has, err := m.membershipService.HasPermission(ctx, userID, permission)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// Cache result for 10 minutes
|
|
m.cache.Set(cacheKey, has, 10*time.Minute)
|
|
return has, nil
|
|
}
|
|
```
|
|
|
|
## Performance Benefits
|
|
|
|
### Expected Improvements
|
|
- **Reduced Database Load**: Permission checks avoid database queries after first access
|
|
- **Faster Response Times**: Cached permission lookups are significantly faster
|
|
- **Better Scalability**: System can handle more concurrent users with same database load
|
|
- **Minimal Memory Overhead**: Only boolean values cached with automatic expiration
|
|
|
|
### Cache Effectiveness
|
|
- **High Hit Ratio Expected**: Users typically access same resources repeatedly
|
|
- **10-Minute TTL**: Balances performance with data freshness
|
|
- **Per-User Per-Permission**: Granular caching for precise invalidation
|
|
|
|
## Configuration
|
|
|
|
### Cache TTL
|
|
```go
|
|
cacheTTL := 10 * time.Minute // Permission cache duration
|
|
```
|
|
|
|
### Cache Key Format
|
|
```go
|
|
"permission:{userID}:{permissionName}"
|
|
```
|
|
|
|
Examples:
|
|
- `permission:user123:ServerView`
|
|
- `permission:user456:ServerCreate`
|
|
- `permission:admin789:SystemManage`
|
|
|
|
## Integration
|
|
|
|
### Dependencies
|
|
- **Existing Cache System**: Uses `local/utl/cache/cache.go`
|
|
- **No New Dependencies**: Leverages already available infrastructure
|
|
- **Minimal Changes**: Only authentication middleware modified
|
|
|
|
### Backward Compatibility
|
|
- **Transparent Operation**: No changes required to existing controllers
|
|
- **Same API**: Permission checking interface remains unchanged
|
|
- **Graceful Degradation**: Falls back to database if cache fails
|
|
|
|
## Usage Examples
|
|
|
|
### Automatic Caching
|
|
```go
|
|
// In controller with HasPermission middleware
|
|
routeGroup.Get("/servers", auth.HasPermission(model.ServerView), controller.GetServers)
|
|
|
|
// First request: Database query + cache store
|
|
// Subsequent requests (within 10 minutes): Cache hit, no database query
|
|
```
|
|
|
|
### Manual Cache Invalidation
|
|
```go
|
|
// If needed (currently not implemented but can be added)
|
|
auth.InvalidateUserPermissions(userID)
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
### Built-in Logging
|
|
- **Cache Hits**: Debug logs when permission found in cache
|
|
- **Cache Misses**: Debug logs when querying database
|
|
- **Cache Operations**: Debug logs for cache storage operations
|
|
|
|
### Log Examples
|
|
```
|
|
[DEBUG] [AUTH_CACHE] Permission user123:ServerView found in cache: true
|
|
[DEBUG] [AUTH_CACHE] Permission user456:ServerCreate cached: true
|
|
```
|
|
|
|
## Maintenance
|
|
|
|
### Cache Invalidation
|
|
- **Automatic Expiration**: 10-minute TTL handles most cases
|
|
- **User Changes**: Permission changes take effect after cache expiration
|
|
- **Role Changes**: New permissions available after cache expiration
|
|
|
|
### Memory Management
|
|
- **Automatic Cleanup**: Cache system handles expired entry removal
|
|
- **Low Memory Impact**: Boolean values have minimal memory footprint
|
|
- **Bounded Growth**: TTL prevents unlimited cache growth
|
|
|
|
## Future Enhancements
|
|
|
|
### Potential Improvements (if needed)
|
|
1. **User Data Caching**: Cache full user objects in addition to permissions
|
|
2. **Role-Based Invalidation**: Invalidate cache when user roles change
|
|
3. **Configurable TTL**: Make cache duration configurable
|
|
4. **Cache Statistics**: Add basic hit/miss ratio logging
|
|
|
|
### Implementation Considerations
|
|
- **Keep It Simple**: Current implementation prioritizes simplicity over features
|
|
- **Monitor Performance**: Measure actual performance impact before adding complexity
|
|
- **Business Requirements**: Add features only when business case is clear
|
|
|
|
## Testing
|
|
|
|
### Recommended Tests
|
|
1. **Permission Caching**: Verify permissions are cached correctly
|
|
2. **Cache Expiration**: Confirm permissions expire after TTL
|
|
3. **Database Fallback**: Ensure database queries work when cache fails
|
|
4. **Concurrent Access**: Test cache behavior under concurrent requests
|
|
|
|
### Performance Testing
|
|
- **Before/After Comparison**: Measure response times with and without caching
|
|
- **Load Testing**: Verify performance under realistic user loads
|
|
- **Database Load**: Monitor database query reduction
|
|
|
|
## Conclusion
|
|
|
|
This simple caching implementation provides significant performance benefits with minimal complexity:
|
|
|
|
- **Solves Core Problem**: Reduces database load for permission checks
|
|
- **Simple Implementation**: Uses existing infrastructure without major changes
|
|
- **Low Risk**: Minimal code changes reduce chance of introducing bugs
|
|
- **Easy Maintenance**: Simple cache strategy is easy to understand and maintain
|
|
- **Immediate Benefits**: Performance improvement available immediately
|
|
|
|
The implementation follows the principle of "simple solutions first" - addressing the performance bottleneck with the minimum viable solution that can be enhanced later if needed. |