Middleware (Go)
Add custom middleware for message processing pipelines.
Basic Middleware
func loggingMiddleware(next easyrmq.HandlerFunc) easyrmq.HandlerFunc {
return func(data []byte) error {
log.Printf("Processing message: %s", string(data))
err := next(data)
if err != nil {
log.Printf("Message processing failed: %v", err)
} else {
log.Printf("Message processed successfully")
}
return err
}
}
easyrmq.NewWorkerBuilder(easyrmq.ExchangeKindDirect).
WithPool(client).
WithExchange("order.events.v1").
Queue("order.process").
Middleware(loggingMiddleware).
Build(handleOrder)
Multiple Middleware
Chain multiple middleware functions:
easyrmq.NewWorkerBuilder(easyrmq.ExchangeKindDirect).
Queue("order.process").
Middleware(loggingMiddleware).
Middleware(metricsMiddleware).
Middleware(recoveryMiddleware).
Build(handleOrder)
Common Middleware Patterns
Logging Middleware
func loggingMiddleware(next easyrmq.HandlerFunc) easyrmq.HandlerFunc {
return func(data []byte) error {
start := time.Now()
log.Printf("Started processing message")
err := next(data)
duration := time.Since(start)
if err != nil {
log.Printf("Failed after %v: %v", duration, err)
} else {
log.Printf("Completed in %v", duration)
}
return err
}
}
Metrics Middleware
func metricsMiddleware(next easyrmq.HandlerFunc) easyrmq.HandlerFunc {
return func(data []byte) error {
start := time.Now()
err := next(data)
duration := time.Since(start)
if err != nil {
metrics.RecordFailure(duration)
} else {
metrics.RecordSuccess(duration)
}
return err
}
}
Recovery Middleware
func recoveryMiddleware(next easyrmq.HandlerFunc) easyrmq.HandlerFunc {
return func(data []byte) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic recovered: %v", r)
log.Printf("Panic in handler: %v", r)
}
}()
return next(data)
}
}
Validation Middleware
func validationMiddleware(next easyrmq.HandlerFunc) easyrmq.HandlerFunc {
return func(data []byte) error {
if len(data) == 0 {
return fmt.Errorf("empty message")
}
if len(data) > 1024*1024 {
return fmt.Errorf("message too large: %d bytes", len(data))
}
return next(data)
}
}
Best Practices
- Order matters: Place middleware in correct order (logging → validation → handler)
- Keep middleware focused: Each middleware should do one thing well
- Handle errors: Decide if errors should stop the chain or be logged
- Use context: Pass request-scoped values through middleware
- Test middleware: Test middleware independently and in combination