package usecase import ( "app-cloudep-member-server/internal/domain" "app-cloudep-member-server/internal/domain/usecase" mgo "app-cloudep-member-server/internal/model/mongo" "context" "math" "strconv" "strings" ) type GenerateUseCaseParam struct { GenerateUIDRepo mgo.AutoIdModel } type GenerateUseCase struct { generateUIDRepo mgo.AutoIdModel } func MustGenerateUseCase(param GenerateUseCaseParam) usecase.UIDGenerateUseCase { return &GenerateUseCase{ generateUIDRepo: param.GenerateUIDRepo, } } // Generate 利用 mongo 創立全局唯一的 ark id // TODO 如果之後有效能問題,扛在同一個 mongo 資料庫,在改成雪花算法 func (g GenerateUseCase) Generate(ctx context.Context) (string, error) { var data mgo.AutoId err := g.generateUIDRepo.Inc(ctx, &data) if err != nil { return "", err } uid := strconv.Itoa(int(domain.InitAutoId + data.Counter)) code, err := generateReferralCode(uid) if err != nil { return "", err } return code, nil } // generateReferralCode 從 UID 生成 referralCode func generateReferralCode(uid string) (string, error) { uidInt, err := strconv.ParseInt(uid, 10, 64) if err != nil { return "", err } maxReferralUIDBoundary := int64(math.Pow(float64(len(domain.ConvertTable)), float64(domain.DefaultReferralCodeLen))) if uidInt > maxReferralUIDBoundary { return "", usecase.UIDOutOfRangeErrorCodeError("uid encode out of range") } encoded := encodeToBase(uidInt, 10, domain.DefaultReferralCodeLen) return encoded, nil } func encodeToBase(num int64, base int, length int) string { result := "" for num > 0 { index := num % int64(base) result = domain.ConvertTable[index] + result num /= int64(base) } // makes sure the length fo result feats the input length if len(result) < length { result = strings.Repeat(domain.ConvertTable[0], length-len(result)) + result } return result }