收口审计治理与套餐任务进展

Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展
Confidence: medium
Scope-risk: broad
Directive: 后续修改需保持审计事件与业务事务边界一致
Tested: git diff --cached --check
Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
2026-08-05 14:30:54 +08:00
parent b3499adfca
commit 5e552d99bc
178 changed files with 16797 additions and 5674 deletions

View File

@@ -67,20 +67,26 @@ func (h *ApprovalRecoveryTaskHandler) recoverUnknown(ctx context.Context, now ti
if !claimed {
continue
}
spNo, err := h.contexts.FindSuccessfulSubmissionSPNo(ctx, record.InstanceID)
spNo, submissionIntegrationID, err := h.contexts.FindSuccessfulSubmissionSPNo(ctx, record.InstanceID)
if err != nil {
return err
}
integrationIDs := []string{submissionIntegrationID}
if spNo == "" {
spNo, err = h.findUniqueSPNo(ctx, record, now)
var recoveryIntegrationIDs []string
spNo, recoveryIntegrationIDs, err = h.findUniqueSPNo(ctx, record, now)
if err != nil {
return err
}
integrationIDs = append(integrationIDs, recoveryIntegrationIDs...)
}
if spNo == "" {
continue
}
recovered, err := h.contexts.RecoverSubmitted(ctx, record.InstanceID, spNo)
recovered, err := h.contexts.RecoverSubmitted(
ctx, record.InstanceID, spNo, integrationIDs,
constants.AuditActorScheduledJob, constants.ApprovalAuditActorRecoveryJob, constants.AuditSourceScheduler,
)
if err != nil {
return err
}
@@ -94,19 +100,20 @@ func (h *ApprovalRecoveryTaskHandler) recoverUnknown(ctx context.Context, now ti
}
// findUniqueSPNo 使用提交时间附近的固定窄窗口分页查询,并只接受唯一未关联候选。
func (h *ApprovalRecoveryTaskHandler) findUniqueSPNo(ctx context.Context, record ApprovalRecoveryRecord, now time.Time) (string, error) {
func (h *ApprovalRecoveryTaskHandler) findUniqueSPNo(ctx context.Context, record ApprovalRecoveryRecord, now time.Time) (string, []string, error) {
startTime := record.SubmissionAttemptedAt.Add(-constants.WeComApprovalRecoveryWindow)
endTime := record.SubmissionAttemptedAt.Add(constants.WeComApprovalRecoveryWindow)
if endTime.After(now) {
endTime = now
}
if !startTime.Before(endTime) {
return "", nil
return "", nil, nil
}
cursor := ""
seenCursors := make(map[string]struct{})
seenCandidates := make(map[string]struct{})
unbound := make([]string, 0, 2)
integrationIDs := make([]string, 0, 2)
for {
page, err := h.infos.List(ctx, ApprovalInfoQuery{
ApplicationID: record.ApplicationID, StartTime: startTime, EndTime: endTime,
@@ -114,11 +121,12 @@ func (h *ApprovalRecoveryTaskHandler) findUniqueSPNo(ctx context.Context, record
Cursor: cursor, Size: constants.WeComApprovalInfoMaxPageSize,
})
if err != nil {
return "", err
return "", nil, err
}
integrationIDs = append(integrationIDs, page.IntegrationID)
existing, err := h.contexts.ExistingSPNos(ctx, record.ApplicationID, page.SPNos)
if err != nil {
return "", err
return "", nil, err
}
for _, candidate := range page.SPNos {
if _, seen := seenCandidates[candidate]; seen {
@@ -128,7 +136,7 @@ func (h *ApprovalRecoveryTaskHandler) findUniqueSPNo(ctx context.Context, record
if _, exists := existing[candidate]; !exists {
unbound = append(unbound, candidate)
if len(unbound) > 1 {
return "", nil
return "", integrationIDs, nil
}
}
}
@@ -137,15 +145,15 @@ func (h *ApprovalRecoveryTaskHandler) findUniqueSPNo(ctx context.Context, record
break
}
if _, exists := seenCursors[next]; exists {
return "", errors.New(errors.CodeServiceUnavailable, "企业微信批量审批单号分页游标重复")
return "", nil, errors.New(errors.CodeServiceUnavailable, "企业微信批量审批单号分页游标重复")
}
seenCursors[next] = struct{}{}
cursor = next
}
if len(unbound) != 1 {
return "", nil
return "", integrationIDs, nil
}
return unbound[0], nil
return unbound[0], integrationIDs, nil
}
func (h *ApprovalRecoveryTaskHandler) enqueueDetailSync(ctx context.Context, applicationID uint, spNo string) error {