feat(admin): migrate core schema to single-pass model
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrInvalidAttemptTransition = errors.New("invalid purchase attempt status transition")
|
||||
|
||||
// AttemptStatus 只描述单趟领取的可恢复执行。真实提交结果独立由唯一围栏记录调和。
|
||||
type AttemptStatus string
|
||||
|
||||
const (
|
||||
AttemptStatusClaimed AttemptStatus = "CLAIMED"
|
||||
AttemptStatusOrdering AttemptStatus = "ORDERING"
|
||||
AttemptStatusFailed AttemptStatus = "FAILED"
|
||||
AttemptStatusFenced AttemptStatus = "FENCED"
|
||||
AttemptStatusAbandoned AttemptStatus = "ABANDONED"
|
||||
)
|
||||
|
||||
// AttemptFailureCode 是服务端可审计的固定失败摘要,不能承载页面正文或其他自由文本。
|
||||
type AttemptFailureCode string
|
||||
|
||||
const (
|
||||
AttemptFailureAuthorizationExpired AttemptFailureCode = "AUTHORIZATION_EXPIRED"
|
||||
AttemptFailureLeaseLost AttemptFailureCode = "LEASE_LOST"
|
||||
AttemptFailureGate1Rejected AttemptFailureCode = "GATE_1_REJECTED"
|
||||
AttemptFailureQuantityMismatch AttemptFailureCode = "QUANTITY_MISMATCH"
|
||||
AttemptFailureGate2Rejected AttemptFailureCode = "GATE_2_REJECTED"
|
||||
AttemptFailureGate3Rejected AttemptFailureCode = "GATE_3_REJECTED"
|
||||
AttemptFailureFenceRejected AttemptFailureCode = "FENCE_REJECTED"
|
||||
AttemptFailureSafeAborted AttemptFailureCode = "SAFE_ABORTED"
|
||||
)
|
||||
|
||||
type PurchaseAttempt struct {
|
||||
ID string
|
||||
TaskID string
|
||||
AuthorizationID string
|
||||
ClaimGeneration int
|
||||
Status AttemptStatus
|
||||
Gate1UnitPrice *string
|
||||
Gate2UnitPrice *string
|
||||
QuantityRead *int
|
||||
ConfirmAmount *string
|
||||
FailureCode *AttemptFailureCode
|
||||
StartedAt time.Time
|
||||
FinishedAt *time.Time
|
||||
}
|
||||
|
||||
// CanTransitionTo 只允许围栏前的领取恢复为安全失败;围栏后不再提供回退或重试路径。
|
||||
func (status AttemptStatus) CanTransitionTo(next AttemptStatus) bool {
|
||||
_, allowed := attemptTransitions[status][next]
|
||||
return allowed
|
||||
}
|
||||
|
||||
func TransitionAttempt(current, next AttemptStatus) (AttemptStatus, error) {
|
||||
if !current.CanTransitionTo(next) {
|
||||
return current, ErrInvalidAttemptTransition
|
||||
}
|
||||
return next, nil
|
||||
}
|
||||
|
||||
var attemptTransitions = map[AttemptStatus]map[AttemptStatus]struct{}{
|
||||
AttemptStatusClaimed: {
|
||||
AttemptStatusOrdering: {},
|
||||
AttemptStatusFailed: {},
|
||||
AttemptStatusAbandoned: {},
|
||||
},
|
||||
AttemptStatusOrdering: {
|
||||
AttemptStatusFenced: {},
|
||||
AttemptStatusFailed: {},
|
||||
AttemptStatusAbandoned: {},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user