feat(cron): implement IP ban maintenance tasks

Add IPBanManager to handle periodic background jobs including:
- Expiring outdated bans
- Syncing hit counts from Redis to DB
- Performing full Redis state synchronization

Additionally, update the service expiration logic to use system time
and add unit tests for CIDR normalization and overlap checking.
This commit is contained in:
zenfun
2026-01-04 01:28:43 +08:00
parent 63d43db39d
commit 830c6fa6e7
3 changed files with 217 additions and 1 deletions

View File

@@ -0,0 +1,61 @@
package cron
import (
"context"
"log/slog"
"github.com/ez-api/ez-api/internal/service"
)
// IPBanManager handles periodic IP ban maintenance tasks.
type IPBanManager struct {
service *service.IPBanService
logger *slog.Logger
}
// NewIPBanManager creates a new IPBanManager.
func NewIPBanManager(service *service.IPBanService) *IPBanManager {
return &IPBanManager{
service: service,
logger: slog.Default(),
}
}
// ExpireRunOnce checks for expired bans and marks them. Called by scheduler.
func (m *IPBanManager) ExpireRunOnce(ctx context.Context) {
if m == nil || m.service == nil {
return
}
count, err := m.service.ExpireOutdatedBans(ctx)
if err != nil {
m.logger.Error("failed to expire outdated IP bans", "err", err)
return
}
if count > 0 {
m.logger.Info("expired outdated IP bans", "count", count)
}
}
// HitSyncRunOnce syncs hit counts from Redis to database. Called by scheduler.
func (m *IPBanManager) HitSyncRunOnce(ctx context.Context) {
if m == nil || m.service == nil {
return
}
if err := m.service.SyncHitCounts(ctx); err != nil {
m.logger.Error("failed to sync IP ban hit counts", "err", err)
}
}
// FullSyncRunOnce performs a full sync of all active bans to Redis. Called by scheduler.
func (m *IPBanManager) FullSyncRunOnce(ctx context.Context) {
if m == nil || m.service == nil {
return
}
if err := m.service.SyncAllToRedis(ctx); err != nil {
m.logger.Error("failed to sync IP bans to Redis", "err", err)
}
}