- 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>
95 lines
3.5 KiB
Go
95 lines
3.5 KiB
Go
package face
|
|
|
|
import "errors"
|
|
|
|
// Sentinel errors for face operations
|
|
var (
|
|
// Client errors
|
|
ErrNoFacesDetected = errors.New("no faces detected in image")
|
|
ErrImageTooSmall = errors.New("image too small for face detection")
|
|
ErrImageTooLarge = errors.New("image exceeds maximum size")
|
|
ErrInvalidImageFormat = errors.New("invalid image format")
|
|
ErrImageProcessingFailed = errors.New("failed to process image")
|
|
|
|
// Collection errors
|
|
ErrCollectionNotFound = errors.New("face collection not found")
|
|
ErrCollectionExists = errors.New("face collection already exists")
|
|
ErrCollectionCreationFailed = errors.New("failed to create face collection")
|
|
|
|
// Indexing errors
|
|
ErrIndexingFailed = errors.New("failed to index face")
|
|
ErrFaceAlreadyIndexed = errors.New("face already indexed")
|
|
|
|
// Search errors
|
|
ErrSearchFailed = errors.New("face search failed")
|
|
ErrNoMatchesFound = errors.New("no matching faces found")
|
|
|
|
// Configuration errors
|
|
ErrMissingRegion = errors.New("AWS region is required")
|
|
ErrMissingCollectionID = errors.New("collection ID is required")
|
|
ErrInvalidMaxFaces = errors.New("max faces must be positive")
|
|
ErrInvalidThreshold = errors.New("threshold must be between 0 and 100")
|
|
|
|
// Rate limiting errors
|
|
ErrRateLimitExceeded = errors.New("rate limit exceeded")
|
|
|
|
// AWS service errors
|
|
ErrAWSServiceError = errors.New("AWS Rekognition service error")
|
|
ErrAWSAccessDenied = errors.New("AWS access denied")
|
|
ErrAWSThrottling = errors.New("AWS request throttled")
|
|
ErrAWSInvalidImage = errors.New("invalid image for AWS Rekognition")
|
|
)
|
|
|
|
// FaceSearchError represents a structured error for face search operations
|
|
type FaceSearchError struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
Details string `json:"details,omitempty"`
|
|
}
|
|
|
|
// Error implements the error interface
|
|
func (e *FaceSearchError) Error() string {
|
|
return e.Message
|
|
}
|
|
|
|
// NewFaceSearchError creates a new FaceSearchError
|
|
func NewFaceSearchError(code, message, details string) *FaceSearchError {
|
|
return &FaceSearchError{
|
|
Code: code,
|
|
Message: message,
|
|
Details: details,
|
|
}
|
|
}
|
|
|
|
// Common error codes
|
|
const (
|
|
ErrorCodeNoFaces = "NO_FACES_DETECTED"
|
|
ErrorCodeInvalidImage = "INVALID_IMAGE"
|
|
ErrorCodeRateLimited = "RATE_LIMITED"
|
|
ErrorCodeCollectionError = "COLLECTION_ERROR"
|
|
ErrorCodeSearchFailed = "SEARCH_FAILED"
|
|
ErrorCodeIndexingFailed = "INDEXING_FAILED"
|
|
ErrorCodeInternalError = "INTERNAL_ERROR"
|
|
)
|
|
|
|
// User-facing error messages
|
|
var UserErrorMessages = map[error]string{
|
|
ErrNoFacesDetected: "No faces detected in the image. Please upload a photo with clear faces.",
|
|
ErrImageTooSmall: "Image is too small. Please upload a larger image (minimum 100x100 pixels).",
|
|
ErrImageTooLarge: "Image is too large. Please upload an image smaller than 10MB.",
|
|
ErrInvalidImageFormat: "Invalid image format. Please upload a JPEG, PNG, or WebP image.",
|
|
ErrCollectionNotFound: "Face collection not found. Please contact support.",
|
|
ErrRateLimitExceeded: "Search limit exceeded. Please try again later.",
|
|
ErrAWSServiceError: "An error occurred while processing your request. Please try again.",
|
|
ErrAWSAccessDenied: "Access denied. Please contact support.",
|
|
ErrAWSThrottling: "Service is busy. Please try again in a few moments.",
|
|
}
|
|
|
|
// GetUserMessage returns a user-friendly error message
|
|
func GetUserMessage(err error) string {
|
|
if msg, ok := UserErrorMessages[err]; ok {
|
|
return msg
|
|
}
|
|
return "An unexpected error occurred. Please try again."
|
|
}
|