chore: 初始开源发布
iotlcm-worker-svr:异步执行中枢(RabbitMQ 消费者 + 全量同步编排)。 - Go module:iotlcm-worker-svr → git.5iot.com/iotlcm-public/iotlcm-worker-svr(214 文件) - 凭据与内部标识脱敏:MySQL/Redis 凭据、私网与生产 IP、内网域名、 库名 xiujie_admin → iotlcm、哨兵名占位 - 159 处真实手机号 → 合法 11 位编造号(保留号段与后 4 位,维持互异, 不破坏「校验 MSISDN 格式」等测试断言) - 移除内部资产:CI 触发器、Jenkins 触发测试文档、预演门禁与镜像 digest 记录 - Dockerfile 改用公共基础镜像(golang:1.25-alpine → alpine:3.23), 移除写死的 git 凭据 - README 重写(架构/全量同步模型/配置/已知失败),补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes 已知:3 个测试包在源仓同一提交上同样失败(client/upstream、 service/allocate、service/inbound),属既有缺陷,本仓未引入亦未修复。
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
package allocate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/consts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/dao"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/model/entity"
|
||||
)
|
||||
|
||||
func (r *Repository) loadParentTaskTx(ctx context.Context, tx gdb.TX, parent *entity.BatchMain) (*Task, error) {
|
||||
var batchDetails []*entity.BatchDetail
|
||||
if err := tx.Ctx(ctx).Model(dao.BatchDetail.Table()).
|
||||
Where("batch_no IN (SELECT batch_no FROM batch_main WHERE source_batch_no = ? AND batch_type = ? AND tenant_id = ?)", parent.BatchNo, consts.BatchTypeAllocate, parent.TenantId).
|
||||
Where(dao.BatchDetail.Columns().BatchType, consts.BatchTypeAllocate).
|
||||
OrderAsc(dao.BatchDetail.Columns().RowNo).
|
||||
OrderAsc(dao.BatchDetail.Columns().BatchNo).
|
||||
OrderAsc(dao.BatchDetail.Columns().Id).
|
||||
Scan(&batchDetails); err != nil {
|
||||
return nil, gerror.Wrap(err, "load allocate parent details failed")
|
||||
}
|
||||
if len(batchDetails) == 0 {
|
||||
return nil, gerror.New("allocate parent has no child details")
|
||||
}
|
||||
|
||||
task := &Task{
|
||||
Batch: Batch{
|
||||
ID: parent.Id, BatchNo: parent.BatchNo, BatchType: consts.BatchTypeAllocate,
|
||||
TenantID: parent.TenantId, TargetDeptID: targetDeptIDFromBatch(parent),
|
||||
CreatedDept: parent.CreatedDept, CreatedBy: parent.CreatedBy,
|
||||
StartTime: parent.StartTime, BatchInfo: parent.BatchInfo,
|
||||
},
|
||||
Details: make([]*Detail, 0, len(batchDetails)),
|
||||
TargetsByID: make(map[int64]*Target), TargetsByKey: make(map[string]*Target), TargetsByName: make(map[string][]*Target),
|
||||
}
|
||||
cardIDs := make([]int64, 0, len(batchDetails))
|
||||
targetIDs := make([]int64, 0, len(batchDetails))
|
||||
cardIDByDetailID := make(map[int64]int64, len(batchDetails))
|
||||
for _, batchDetail := range batchDetails {
|
||||
if batchDetail == nil {
|
||||
continue
|
||||
}
|
||||
detail := &Detail{OriginalSnapshot: batchDetail.Snapshot, ID: batchDetail.Id, BatchNo: batchDetail.BatchNo, RowNo: batchDetail.RowNo, DetailStatus: batchDetail.DetailStatus, ICCID: strings.TrimSpace(batchDetail.ItemId), Reason: strings.TrimSpace(batchDetail.ErrorReason)}
|
||||
if detail.DetailStatus != consts.BatchDetailStatusSuccess && detail.Reason == "" {
|
||||
detail.Reason = "子批次明细尚未全部验证成功"
|
||||
}
|
||||
if snapshot := batchDetail.Snapshot; snapshot != nil {
|
||||
detail.Remark = firstSnapshot(snapshot, "remark")
|
||||
detail.MSISDN = firstSnapshot(snapshot, "MSISDN", "msisdn")
|
||||
detail.IMSI = firstSnapshot(snapshot, "IMSI", "imsi")
|
||||
detail.TargetDeptID = snapshot.Get("targetDeptId").Int64()
|
||||
detail.TargetDeptKey = firstSnapshot(snapshot, "targetDeptKey", "target_dept_key")
|
||||
detail.TargetDeptName = firstSnapshot(snapshot, "targetDeptName", "target_dept_name")
|
||||
if cardID := snapshot.Get("cardId").Int64(); cardID > 0 {
|
||||
cardIDs = append(cardIDs, cardID)
|
||||
cardIDByDetailID[batchDetail.Id] = cardID
|
||||
} else if detail.Reason == "" {
|
||||
detail.Reason = "卡片快照缺少有效卡片ID"
|
||||
}
|
||||
}
|
||||
if detail.TargetDeptID > 0 {
|
||||
targetIDs = append(targetIDs, detail.TargetDeptID)
|
||||
}
|
||||
task.Details = append(task.Details, detail)
|
||||
}
|
||||
|
||||
cardsByID := make(map[int64]*entity.TSimCardInfo, len(cardIDs))
|
||||
cardIDs = uniqueInt64s(cardIDs)
|
||||
sort.Slice(cardIDs, func(i, j int) bool { return cardIDs[i] < cardIDs[j] })
|
||||
for start := 0; start < len(cardIDs); start += allocateCardQueryBatchSize {
|
||||
end := min(start+allocateCardQueryBatchSize, len(cardIDs))
|
||||
var cards []*entity.TSimCardInfo
|
||||
if err := tx.Ctx(ctx).Model(dao.TSimCardInfo.Table()).Safe().
|
||||
Where(dao.TSimCardInfo.Columns().TenantId, parent.TenantId).
|
||||
WhereIn(dao.TSimCardInfo.Columns().Id, cardIDs[start:end]).
|
||||
LockUpdate().Scan(&cards); err != nil {
|
||||
return nil, gerror.Wrap(err, "lock allocate parent cards failed")
|
||||
}
|
||||
for _, card := range cards {
|
||||
if card != nil {
|
||||
cardsByID[card.Id] = card
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetsByID := make(map[int64]*Target, len(targetIDs))
|
||||
targetIDs = uniqueInt64s(targetIDs)
|
||||
sort.Slice(targetIDs, func(i, j int) bool { return targetIDs[i] < targetIDs[j] })
|
||||
for start := 0; start < len(targetIDs); start += allocateCardQueryBatchSize {
|
||||
end := min(start+allocateCardQueryBatchSize, len(targetIDs))
|
||||
var depts []*entity.SysDept
|
||||
if err := tx.Ctx(ctx).Model(dao.SysDept.Table()).
|
||||
Where(dao.SysDept.Columns().TenantId, parent.TenantId).
|
||||
Where(dao.SysDept.Columns().ParentId, parent.CreatedDept).
|
||||
Where(dao.SysDept.Columns().Status, "0").
|
||||
WhereNull(dao.SysDept.Columns().DeletedAt).
|
||||
WhereIn(dao.SysDept.Columns().DeptId, targetIDs[start:end]).
|
||||
LockUpdate().Scan(&depts); err != nil {
|
||||
return nil, gerror.Wrap(err, "lock allocate parent targets failed")
|
||||
}
|
||||
for _, dept := range depts {
|
||||
if dept == nil {
|
||||
continue
|
||||
}
|
||||
target := &Target{DeptID: dept.DeptId, ParentID: dept.ParentId, DeptKey: strings.TrimSpace(dept.DeptKey), DeptName: strings.TrimSpace(dept.DeptName)}
|
||||
targetsByID[target.DeptID] = target
|
||||
task.TargetsByID[target.DeptID] = target
|
||||
if target.DeptKey != "" {
|
||||
task.TargetsByKey[target.DeptKey] = target
|
||||
}
|
||||
if target.DeptName != "" {
|
||||
task.TargetsByName[target.DeptName] = append(task.TargetsByName[target.DeptName], target)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, detail := range task.Details {
|
||||
if detail == nil {
|
||||
continue
|
||||
}
|
||||
if detail.Target == nil {
|
||||
detail.Target = targetsByID[detail.TargetDeptID]
|
||||
}
|
||||
cardID := cardIDByDetailID[detail.ID]
|
||||
if card := cardsByID[cardID]; card != nil {
|
||||
detail.Card = &Card{ID: card.Id, ICCID: strings.TrimSpace(card.Iccid), MSISDN: strings.TrimSpace(card.Msisdn), IMSI: strings.TrimSpace(card.Imsi), DeptID: card.DeptId, AllocationBatchNo: strings.TrimSpace(card.AllocationBatchNo), PackageStatus: card.PackageStatus, BossCardStatus: card.BossCardStatus, FlowPkgEndAt: card.FlowPkgEndAt}
|
||||
}
|
||||
}
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func uniqueInt64s(values []int64) []int64 {
|
||||
seen := make(map[int64]struct{}, len(values))
|
||||
unique := make([]int64, 0, len(values))
|
||||
for _, value := range values {
|
||||
if _, exists := seen[value]; exists {
|
||||
continue
|
||||
}
|
||||
seen[value] = struct{}{}
|
||||
unique = append(unique, value)
|
||||
}
|
||||
return unique
|
||||
}
|
||||
Reference in New Issue
Block a user