package controllers import ( "errors" "strconv" "strings" "time" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/ops/logs/internal/impl" "git.apinb.com/ops/logs/internal/models" "github.com/gin-gonic/gin" ) func ListAlertOutbox(ctx *gin.Context) { status := strings.TrimSpace(ctx.Query("status")) page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) size, _ := strconv.Atoi(ctx.DefaultQuery("page_size", "50")) if page < 1 { page = 1 } if size < 1 || size > 500 { size = 50 } offset := (page - 1) * size q := impl.DBService.Model(&models.AlertOutbox{}) if status != "" { q = q.Where("status = ?", status) } var total int64 _ = q.Count(&total).Error var rows []models.AlertOutbox if err := q.Order("id desc").Offset(offset).Limit(size).Find(&rows).Error; err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, gin.H{ "total": total, "page": page, "page_size": size, "items": rows, }) } func RetryAlertOutbox(ctx *gin.Context) { id, err := parseID(ctx) if err != nil { infra.Response.Error(ctx, errors.New("invalid id")) return } var row models.AlertOutbox if err := impl.DBService.First(&row, id).Error; err != nil { infra.Response.Error(ctx, err) return } // 手工重试时,无论失败原因如何都重置为 pending 并立即可被 worker 消费。 if err := impl.DBService.Model(&models.AlertOutbox{}).Where("id = ?", id).Updates(map[string]interface{}{ "status": "pending", "next_retry_at": time.Now(), "last_error": "", }).Error; err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, gin.H{ "id": id, "status": "pending", }) }