- Client interface and MockClient for testing - Service layer with IndexPhoto and SearchFaces methods - CacheService interface and MemoryCache implementation - Configuration with environment variable support - Error types and user-facing messages - Unit tests for service layer Co-Authored-By: Paperclip <noreply@paperclip.ing>
103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
package face
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Config holds configuration for the face service
|
|
type Config struct {
|
|
// AWS Configuration
|
|
Region string
|
|
CollectionID string
|
|
|
|
// Face Detection Configuration
|
|
MaxFaces int
|
|
Threshold float64
|
|
QualityFilter string
|
|
|
|
// Cache Configuration
|
|
CacheTTL time.Duration
|
|
SearchCacheTTL time.Duration
|
|
PhotoCacheTTL time.Duration
|
|
|
|
// Rate Limiting
|
|
GuestRateLimit int
|
|
GuestRateWindowMin int
|
|
AuthRateLimit int
|
|
AuthRateWindowMin int
|
|
|
|
// Image Optimization
|
|
MaxImageSize int
|
|
ResizeWidth int
|
|
ResizeHeight int
|
|
ImageQuality int
|
|
}
|
|
|
|
// DefaultConfig returns default configuration
|
|
func DefaultConfig() *Config {
|
|
return &Config{
|
|
Region: getEnv("AWS_REGION", "us-east-1"),
|
|
CollectionID: getEnv("REKOGNITION_COLLECTION", "hatch-faces"),
|
|
MaxFaces: getEnvInt("REKOGNITION_MAX_FACES", 10),
|
|
Threshold: getEnvFloat("REKOGNITION_THRESHOLD", 80.0),
|
|
QualityFilter: getEnv("REKOGNITION_QUALITY_FILTER", "AUTO"),
|
|
CacheTTL: 5 * time.Minute,
|
|
SearchCacheTTL: 5 * time.Minute,
|
|
PhotoCacheTTL: 24 * time.Hour,
|
|
GuestRateLimit: getEnvInt("RATE_LIMIT_GUEST_SEARCHES", 20),
|
|
GuestRateWindowMin: getEnvInt("RATE_LIMIT_GUEST_WINDOW_MINUTES", 15),
|
|
AuthRateLimit: getEnvInt("RATE_LIMIT_AUTH_SEARCHES", 100),
|
|
AuthRateWindowMin: getEnvInt("RATE_LIMIT_AUTH_WINDOW_MINUTES", 1),
|
|
MaxImageSize: 10 * 1024 * 1024, // 10MB
|
|
ResizeWidth: 1024,
|
|
ResizeHeight: 1024,
|
|
ImageQuality: 85,
|
|
}
|
|
}
|
|
|
|
// Validate checks if the configuration is valid
|
|
func (c *Config) Validate() error {
|
|
if c.Region == "" {
|
|
return ErrMissingRegion
|
|
}
|
|
if c.CollectionID == "" {
|
|
return ErrMissingCollectionID
|
|
}
|
|
if c.MaxFaces <= 0 {
|
|
return ErrInvalidMaxFaces
|
|
}
|
|
if c.Threshold < 0 || c.Threshold > 100 {
|
|
return ErrInvalidThreshold
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Helper functions for environment variables
|
|
|
|
func getEnv(key, defaultValue string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvInt(key string, defaultValue int) int {
|
|
if value := os.Getenv(key); value != "" {
|
|
if intValue, err := strconv.Atoi(value); err == nil {
|
|
return intValue
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvFloat(key string, defaultValue float64) float64 {
|
|
if value := os.Getenv(key); value != "" {
|
|
if floatValue, err := strconv.ParseFloat(value, 64); err == nil {
|
|
return floatValue
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|