1
0
forked from baron/baron-sso
Files
baron-sso/backend/internal/service/rp_usage_projector_worker.go

83 lines
2.0 KiB
Go

package service
import (
"baron-sso-backend/internal/domain"
"baron-sso-backend/internal/repository"
"context"
"log/slog"
"time"
)
type RPUsageProjectorWorker struct {
outbox repository.RPUsageOutboxRepository
projection domain.RPUsageProjectionRepository
interval time.Duration
batchSize int
}
func NewRPUsageProjectorWorker(outbox repository.RPUsageOutboxRepository, projection domain.RPUsageProjectionRepository) *RPUsageProjectorWorker {
return &RPUsageProjectorWorker{
outbox: outbox,
projection: projection,
interval: 5 * time.Second,
batchSize: 50,
}
}
func (w *RPUsageProjectorWorker) Start(ctx context.Context) {
if w == nil || w.outbox == nil || w.projection == nil {
return
}
ticker := time.NewTicker(w.interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
default:
w.processOnce(ctx)
}
select {
case <-ctx.Done():
return
case <-ticker.C:
}
}
}
func (w *RPUsageProjectorWorker) processOnce(ctx context.Context) {
events, err := w.outbox.ListReady(ctx, w.batchSize)
if err != nil {
slog.Warn("failed to list rp usage outbox", "error", err)
return
}
for _, event := range events {
if err := w.outbox.MarkProcessing(ctx, event.ID); err != nil {
slog.Warn("failed to mark rp usage event processing", "event_id", event.ID, "error", err)
continue
}
if err := w.projection.CreateRPUsageEvent(ctx, event); err != nil {
nextAttempt := time.Now().Add(backoffDuration(event.RetryCount))
_ = w.outbox.MarkFailed(ctx, event.ID, err.Error(), nextAttempt)
slog.Warn("failed to project rp usage event", "event_id", event.ID, "error", err)
continue
}
if err := w.outbox.MarkProcessed(ctx, event.ID); err != nil {
slog.Warn("failed to mark rp usage event processed", "event_id", event.ID, "error", err)
}
}
}
func backoffDuration(retryCount int) time.Duration {
if retryCount < 0 {
retryCount = 0
}
delay := time.Duration(retryCount+1) * time.Minute
if delay > 30*time.Minute {
return 30 * time.Minute
}
return delay
}