Files
cellbot/internal/engine/middleware.go
lafay 44fe05ff62 chore: update dependencies and improve bot configuration
- Upgrade Go version to 1.24.0 and update toolchain.
- Update various dependencies in go.mod and go.sum, including:
  - Upgrade `fasthttp/websocket` to v1.5.12
  - Upgrade `fsnotify/fsnotify` to v1.9.0
  - Upgrade `valyala/fasthttp` to v1.58.0
  - Add new dependencies for `bytedance/sonic` and `google/uuid`.
- Refactor bot configuration in config.toml to support multiple bot protocols, including "milky" and "onebot11".
- Modify internal configuration structures to accommodate new bot settings.
- Enhance event dispatcher with metrics tracking and asynchronous processing capabilities.
- Implement WebSocket connection management with heartbeat and reconnection logic.
- Update server handling for bot management and event publishing.
2026-01-05 00:40:09 +08:00

284 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package engine
import (
"context"
"sync"
"time"
"cellbot/internal/protocol"
"go.uber.org/zap"
"golang.org/x/time/rate"
)
// LoggingMiddleware 日志中间件
type LoggingMiddleware struct {
logger *zap.Logger
}
// NewLoggingMiddleware 创建日志中间件
func NewLoggingMiddleware(logger *zap.Logger) *LoggingMiddleware {
return &LoggingMiddleware{
logger: logger.Named("middleware.logging"),
}
}
// Process 处理事件
func (m *LoggingMiddleware) Process(ctx context.Context, event protocol.Event, next func(context.Context, protocol.Event) error) error {
start := time.Now()
m.logger.Info("Event received",
zap.String("type", string(event.GetType())),
zap.String("detail_type", event.GetDetailType()),
zap.String("self_id", event.GetSelfID()))
err := next(ctx, event)
m.logger.Info("Event processed",
zap.String("type", string(event.GetType())),
zap.Duration("duration", time.Since(start)),
zap.Error(err))
return err
}
// RateLimitMiddleware 限流中间件
type RateLimitMiddleware struct {
limiters map[string]*rate.Limiter
mu sync.RWMutex
logger *zap.Logger
rps int // 每秒请求数
burst int // 突发容量
}
// NewRateLimitMiddleware 创建限流中间件
func NewRateLimitMiddleware(logger *zap.Logger, rps, burst int) *RateLimitMiddleware {
if rps <= 0 {
rps = 100
}
if burst <= 0 {
burst = rps * 2
}
return &RateLimitMiddleware{
limiters: make(map[string]*rate.Limiter),
logger: logger.Named("middleware.ratelimit"),
rps: rps,
burst: burst,
}
}
// Process 处理事件
func (m *RateLimitMiddleware) Process(ctx context.Context, event protocol.Event, next func(context.Context, protocol.Event) error) error {
// 根据事件类型获取限流器
key := string(event.GetType())
m.mu.RLock()
limiter, exists := m.limiters[key]
m.mu.RUnlock()
if !exists {
m.mu.Lock()
limiter = rate.NewLimiter(rate.Limit(m.rps), m.burst)
m.limiters[key] = limiter
m.mu.Unlock()
}
// 等待令牌
if err := limiter.Wait(ctx); err != nil {
m.logger.Warn("Rate limit exceeded",
zap.String("event_type", key),
zap.Error(err))
return err
}
return next(ctx, event)
}
// RetryMiddleware 重试中间件
type RetryMiddleware struct {
logger *zap.Logger
maxRetries int
delay time.Duration
}
// NewRetryMiddleware 创建重试中间件
func NewRetryMiddleware(logger *zap.Logger, maxRetries int, delay time.Duration) *RetryMiddleware {
if maxRetries <= 0 {
maxRetries = 3
}
if delay <= 0 {
delay = time.Second
}
return &RetryMiddleware{
logger: logger.Named("middleware.retry"),
maxRetries: maxRetries,
delay: delay,
}
}
// Process 处理事件
func (m *RetryMiddleware) Process(ctx context.Context, event protocol.Event, next func(context.Context, protocol.Event) error) error {
var err error
for i := 0; i <= m.maxRetries; i++ {
if i > 0 {
m.logger.Info("Retrying event",
zap.String("event_type", string(event.GetType())),
zap.Int("attempt", i),
zap.Int("max_retries", m.maxRetries))
// 指数退避
backoff := m.delay * time.Duration(1<<uint(i-1))
select {
case <-time.After(backoff):
case <-ctx.Done():
return ctx.Err()
}
}
err = next(ctx, event)
if err == nil {
if i > 0 {
m.logger.Info("Event succeeded after retry",
zap.String("event_type", string(event.GetType())),
zap.Int("attempts", i+1))
}
return nil
}
m.logger.Warn("Event processing failed",
zap.String("event_type", string(event.GetType())),
zap.Int("attempt", i+1),
zap.Error(err))
}
m.logger.Error("Event failed after all retries",
zap.String("event_type", string(event.GetType())),
zap.Int("total_attempts", m.maxRetries+1),
zap.Error(err))
return err
}
// TimeoutMiddleware 超时中间件
type TimeoutMiddleware struct {
logger *zap.Logger
timeout time.Duration
}
// NewTimeoutMiddleware 创建超时中间件
func NewTimeoutMiddleware(logger *zap.Logger, timeout time.Duration) *TimeoutMiddleware {
if timeout <= 0 {
timeout = 30 * time.Second
}
return &TimeoutMiddleware{
logger: logger.Named("middleware.timeout"),
timeout: timeout,
}
}
// Process 处理事件
func (m *TimeoutMiddleware) Process(ctx context.Context, event protocol.Event, next func(context.Context, protocol.Event) error) error {
ctx, cancel := context.WithTimeout(ctx, m.timeout)
defer cancel()
done := make(chan error, 1)
go func() {
done <- next(ctx, event)
}()
select {
case err := <-done:
return err
case <-ctx.Done():
m.logger.Warn("Event processing timeout",
zap.String("event_type", string(event.GetType())),
zap.Duration("timeout", m.timeout))
return ctx.Err()
}
}
// RecoveryMiddleware 恢复中间件捕获panic
type RecoveryMiddleware struct {
logger *zap.Logger
}
// NewRecoveryMiddleware 创建恢复中间件
func NewRecoveryMiddleware(logger *zap.Logger) *RecoveryMiddleware {
return &RecoveryMiddleware{
logger: logger.Named("middleware.recovery"),
}
}
// Process 处理事件
func (m *RecoveryMiddleware) Process(ctx context.Context, event protocol.Event, next func(context.Context, protocol.Event) error) (err error) {
defer func() {
if r := recover(); r != nil {
m.logger.Error("Recovered from panic",
zap.Any("panic", r),
zap.String("event_type", string(event.GetType())))
err = protocol.ErrNotImplemented // 或者自定义错误
}
}()
return next(ctx, event)
}
// MetricsMiddleware 指标中间件
type MetricsMiddleware struct {
logger *zap.Logger
eventCounts map[string]int64
eventTimes map[string]time.Duration
mu sync.RWMutex
}
// NewMetricsMiddleware 创建指标中间件
func NewMetricsMiddleware(logger *zap.Logger) *MetricsMiddleware {
return &MetricsMiddleware{
logger: logger.Named("middleware.metrics"),
eventCounts: make(map[string]int64),
eventTimes: make(map[string]time.Duration),
}
}
// Process 处理事件
func (m *MetricsMiddleware) Process(ctx context.Context, event protocol.Event, next func(context.Context, protocol.Event) error) error {
start := time.Now()
err := next(ctx, event)
duration := time.Since(start)
eventType := string(event.GetType())
m.mu.Lock()
m.eventCounts[eventType]++
m.eventTimes[eventType] += duration
m.mu.Unlock()
return err
}
// GetMetrics 获取指标
func (m *MetricsMiddleware) GetMetrics() map[string]interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
metrics := make(map[string]interface{})
for eventType, count := range m.eventCounts {
avgTime := m.eventTimes[eventType] / time.Duration(count)
metrics[eventType] = map[string]interface{}{
"count": count,
"avg_time": avgTime.String(),
}
}
return metrics
}
// LogMetrics 记录指标
func (m *MetricsMiddleware) LogMetrics() {
metrics := m.GetMetrics()
m.logger.Info("Event metrics", zap.Any("metrics", metrics))
}