refactor: merge retry target type into http (max_retries=0 = fire-and-forget)
All checks were successful
check / check (push) Successful in 1m46s
All checks were successful
check / check (push) Successful in 1m46s
This commit is contained in:
@@ -133,7 +133,8 @@ type Engine struct {
|
||||
workers int
|
||||
|
||||
// circuitBreakers stores a *CircuitBreaker per target ID. Only used
|
||||
// for retry targets — HTTP, database, and log targets do not need
|
||||
// for HTTP targets with MaxRetries > 0 — fire-and-forget HTTP targets
|
||||
// (MaxRetries == 0), database targets, and log targets do not need
|
||||
// circuit breakers because they either fire once or are local ops.
|
||||
circuitBreakers sync.Map
|
||||
}
|
||||
@@ -829,9 +830,7 @@ func (e *Engine) sweepWebhookRetries(ctx context.Context, webhookID string) {
|
||||
func (e *Engine) processDelivery(ctx context.Context, webhookDB *gorm.DB, d *database.Delivery, task *DeliveryTask) {
|
||||
switch d.Target.Type {
|
||||
case database.TargetTypeHTTP:
|
||||
e.deliverHTTP(ctx, webhookDB, d)
|
||||
case database.TargetTypeRetry:
|
||||
e.deliverRetry(ctx, webhookDB, d, task)
|
||||
e.deliverHTTP(ctx, webhookDB, d, task)
|
||||
case database.TargetTypeDatabase:
|
||||
e.deliverDatabase(webhookDB, d)
|
||||
case database.TargetTypeLog:
|
||||
@@ -845,47 +844,43 @@ func (e *Engine) processDelivery(ctx context.Context, webhookDB *gorm.DB, d *dat
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Engine) deliverHTTP(_ context.Context, webhookDB *gorm.DB, d *database.Delivery) {
|
||||
func (e *Engine) deliverHTTP(_ context.Context, webhookDB *gorm.DB, d *database.Delivery, task *DeliveryTask) {
|
||||
cfg, err := e.parseHTTPConfig(d.Target.Config)
|
||||
if err != nil {
|
||||
e.log.Error("invalid HTTP target config",
|
||||
"target_id", d.TargetID,
|
||||
"error", err,
|
||||
)
|
||||
e.recordResult(webhookDB, d, 1, false, 0, "", err.Error(), 0)
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusFailed)
|
||||
return
|
||||
}
|
||||
|
||||
statusCode, respBody, duration, err := e.doHTTPRequest(cfg, &d.Event)
|
||||
|
||||
success := err == nil && statusCode >= 200 && statusCode < 300
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
e.recordResult(webhookDB, d, 1, success, statusCode, respBody, errMsg, duration)
|
||||
|
||||
if success {
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusDelivered)
|
||||
} else {
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusFailed)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Engine) deliverRetry(_ context.Context, webhookDB *gorm.DB, d *database.Delivery, task *DeliveryTask) {
|
||||
cfg, err := e.parseHTTPConfig(d.Target.Config)
|
||||
if err != nil {
|
||||
e.log.Error("invalid retry target config",
|
||||
"target_id", d.TargetID,
|
||||
"error", err,
|
||||
)
|
||||
e.recordResult(webhookDB, d, task.AttemptNum, false, 0, "", err.Error(), 0)
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusFailed)
|
||||
return
|
||||
}
|
||||
|
||||
maxRetries := d.Target.MaxRetries
|
||||
|
||||
// Fire-and-forget mode: max_retries == 0 means attempt once with no
|
||||
// circuit breaker and no retry scheduling.
|
||||
if maxRetries == 0 {
|
||||
statusCode, respBody, duration, reqErr := e.doHTTPRequest(cfg, &d.Event)
|
||||
|
||||
success := reqErr == nil && statusCode >= 200 && statusCode < 300
|
||||
errMsg := ""
|
||||
if reqErr != nil {
|
||||
errMsg = reqErr.Error()
|
||||
}
|
||||
|
||||
e.recordResult(webhookDB, d, 1, success, statusCode, respBody, errMsg, duration)
|
||||
|
||||
if success {
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusDelivered)
|
||||
} else {
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusFailed)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Retry mode: max_retries > 0 — use circuit breaker and exponential backoff.
|
||||
|
||||
// Check the circuit breaker for this target before attempting delivery.
|
||||
cb := e.getCircuitBreaker(task.TargetID)
|
||||
if !cb.Allow() {
|
||||
@@ -910,12 +905,12 @@ func (e *Engine) deliverRetry(_ context.Context, webhookDB *gorm.DB, d *database
|
||||
|
||||
// Attempt delivery immediately — backoff is handled by the timer
|
||||
// that triggered this call, not by polling.
|
||||
statusCode, respBody, duration, err := e.doHTTPRequest(cfg, &d.Event)
|
||||
statusCode, respBody, duration, reqErr := e.doHTTPRequest(cfg, &d.Event)
|
||||
|
||||
success := err == nil && statusCode >= 200 && statusCode < 300
|
||||
success := reqErr == nil && statusCode >= 200 && statusCode < 300
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
if reqErr != nil {
|
||||
errMsg = reqErr.Error()
|
||||
}
|
||||
|
||||
e.recordResult(webhookDB, d, attemptNum, success, statusCode, respBody, errMsg, duration)
|
||||
@@ -929,11 +924,6 @@ func (e *Engine) deliverRetry(_ context.Context, webhookDB *gorm.DB, d *database
|
||||
// Delivery failed — record failure in circuit breaker
|
||||
cb.RecordFailure()
|
||||
|
||||
maxRetries := d.Target.MaxRetries
|
||||
if maxRetries <= 0 {
|
||||
maxRetries = 5 // default
|
||||
}
|
||||
|
||||
if attemptNum >= maxRetries {
|
||||
e.updateDeliveryStatus(webhookDB, d, database.DeliveryStatusFailed)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user