105 lines
4.2 KiB
Go
105 lines
4.2 KiB
Go
package approval
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
approvalapp "github.com/break/junhong_cmp_fiber/internal/application/approval"
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
|
)
|
|
|
|
// DecisionDeliveryStore 持久化标准决策消费事实并管理处理租约。
|
|
type DecisionDeliveryStore struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewDecisionDeliveryStore 创建标准决策投递 Store。
|
|
func NewDecisionDeliveryStore(db *gorm.DB) *DecisionDeliveryStore {
|
|
return &DecisionDeliveryStore{db: db}
|
|
}
|
|
|
|
// Create 在审批状态事务中创建唯一标准决策投递事实。
|
|
func (s *DecisionDeliveryStore) Create(ctx context.Context, tx *gorm.DB, event approvalapp.TerminalDecisionEvent) error {
|
|
if tx == nil {
|
|
return errors.New(errors.CodeInternalError, "审批决策投递必须使用审批状态事务")
|
|
}
|
|
record := model.ApprovalDecisionDelivery{
|
|
InstanceID: event.InstanceID, Decision: event.Decision, EventID: event.EventID,
|
|
Status: constants.ApprovalDecisionDeliveryPending, CreatedAt: event.OccurredAt, UpdatedAt: event.OccurredAt,
|
|
}
|
|
if err := tx.WithContext(ctx).Create(&record).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "创建审批决策投递事实失败")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Claim 领取待处理、失败或租约已过期的标准决策。
|
|
func (s *DecisionDeliveryStore) Claim(
|
|
ctx context.Context,
|
|
eventID string,
|
|
owner string,
|
|
now time.Time,
|
|
duration time.Duration,
|
|
) (bool, error) {
|
|
if s == nil || s.db == nil || eventID == "" || owner == "" || duration <= 0 {
|
|
return false, errors.New(errors.CodeInternalError, "审批决策处理租约 Store 未完整配置")
|
|
}
|
|
result := s.db.WithContext(ctx).Model(&model.ApprovalDecisionDelivery{}).
|
|
Where("event_id = ? AND (status IN ? OR (status = ? AND lease_expires_at <= ?))",
|
|
eventID,
|
|
[]int{constants.ApprovalDecisionDeliveryPending, constants.ApprovalDecisionDeliveryFailed},
|
|
constants.ApprovalDecisionDeliveryProcessing, now).
|
|
Updates(map[string]any{
|
|
"status": constants.ApprovalDecisionDeliveryProcessing,
|
|
"lease_owner": owner, "lease_expires_at": now.Add(duration), "updated_at": now,
|
|
})
|
|
if result.Error != nil {
|
|
return false, errors.Wrap(errors.CodeDatabaseError, result.Error, "领取审批决策处理租约失败")
|
|
}
|
|
return result.RowsAffected == 1, nil
|
|
}
|
|
|
|
// MarkSucceeded 标记当前租约的业务消费者已幂等处理成功。
|
|
func (s *DecisionDeliveryStore) MarkSucceeded(ctx context.Context, eventID string, owner string, now time.Time) (bool, error) {
|
|
if s == nil || s.db == nil {
|
|
return false, errors.New(errors.CodeInternalError, "审批决策处理租约 Store 未配置")
|
|
}
|
|
result := s.db.WithContext(ctx).Model(&model.ApprovalDecisionDelivery{}).
|
|
Where("event_id = ? AND status = ? AND lease_owner = ?", eventID, constants.ApprovalDecisionDeliveryProcessing, owner).
|
|
Updates(map[string]any{
|
|
"status": constants.ApprovalDecisionDeliverySucceeded, "processed_at": now,
|
|
"lease_owner": nil, "lease_expires_at": nil, "last_error": "", "updated_at": now,
|
|
})
|
|
if result.Error != nil {
|
|
return false, errors.Wrap(errors.CodeDatabaseError, result.Error, "完成审批决策业务处理失败")
|
|
}
|
|
return result.RowsAffected == 1, nil
|
|
}
|
|
|
|
// MarkFailed 记录当前租约的安全失败摘要并释放租约等待重试。
|
|
func (s *DecisionDeliveryStore) MarkFailed(
|
|
ctx context.Context,
|
|
eventID string,
|
|
owner string,
|
|
now time.Time,
|
|
errorSummary string,
|
|
) (bool, error) {
|
|
if s == nil || s.db == nil {
|
|
return false, errors.New(errors.CodeInternalError, "审批决策处理租约 Store 未配置")
|
|
}
|
|
result := s.db.WithContext(ctx).Model(&model.ApprovalDecisionDelivery{}).
|
|
Where("event_id = ? AND status = ? AND lease_owner = ?", eventID, constants.ApprovalDecisionDeliveryProcessing, owner).
|
|
Updates(map[string]any{
|
|
"status": constants.ApprovalDecisionDeliveryFailed, "retry_count": gorm.Expr("retry_count + 1"),
|
|
"lease_owner": nil, "lease_expires_at": nil, "last_error": errorSummary, "updated_at": now,
|
|
})
|
|
if result.Error != nil {
|
|
return false, errors.Wrap(errors.CodeDatabaseError, result.Error, "记录审批决策业务处理失败")
|
|
}
|
|
return result.RowsAffected == 1, nil
|
|
}
|