refactor: simplify redis recommendation concurrency

- replace fan-in channel recommendation searches with errgroup-based execution
- return SearchResult directly from Redis recommendation helper functions
- fallback leading-dot recommendation input to initial token suggestions
- remove unused recommendLenType parameter from fuzzy member set validation
- clean up small model selection and naming issues
This commit is contained in:
douxu 2026-07-08 14:41:13 +08:00
parent f9824e2b24
commit d8668afa46
5 changed files with 157 additions and 202 deletions

View File

@ -2,6 +2,8 @@
package handler
import (
"fmt"
"modelRT/constants"
"modelRT/database"
"modelRT/logger"
@ -152,6 +154,8 @@ func validateBatchImportParams(params map[string]any) bool {
func validateTestTaskParams(params map[string]any) bool {
// Test task has optional parameters, all are valid
// sleep_duration defaults to 60 seconds if not provided
// TODO Add more validation logic for test task parameters if needed
fmt.Println(params)
return true
}

View File

@ -90,6 +90,6 @@ func (s *ShortAttrInfo) IsLocal() bool {
}
// GetAttrValue define return the attribute value
func (l *ShortAttrInfo) GetAttrValue() any {
return l.AttrValue
func (s *ShortAttrInfo) GetAttrValue() any {
return s.AttrValue
}

View File

@ -1,3 +1,4 @@
// Package model define model struct of model runtime service
package model
import (
@ -7,11 +8,12 @@ import (
// SelectModelByType define select the data structure for parsing based on the input model type
func SelectModelByType(modelType int) BasicModelInterface {
if modelType == constants.BusbarType {
switch modelType {
case constants.BusbarType:
return &orm.BusbarSection{}
} else if modelType == constants.AsyncMotorType {
case constants.AsyncMotorType:
return &orm.AsyncMotor{}
} else if modelType == constants.DemoType {
case constants.DemoType:
return &orm.Demo{}
}
return nil

View File

@ -7,6 +7,7 @@ import (
"fmt"
"math"
"strings"
"sync"
"modelRT/constants"
"modelRT/diagram"
@ -16,6 +17,7 @@ import (
"github.com/RediSearch/redisearch-go/v2/redisearch"
redigo "github.com/gomodule/redigo/redis"
"github.com/redis/go-redis/v9"
"golang.org/x/sync/errgroup"
)
// SearchResult define struct to store redis query recommend search result
@ -36,12 +38,44 @@ func InitAutocompleterWithPool(pool *redigo.Pool) {
ac = redisearch.NewAutocompleterFromPool(pool, constants.RedisSearchDictName)
}
type recommendSearchJob func() SearchResult
func runRecommendSearches(ctx context.Context, logMsg string, filterCompNSPath bool, jobs ...recommendSearchJob) map[string]SearchResult {
results := make(map[string]SearchResult)
var mu sync.Mutex
var group errgroup.Group
for _, job := range jobs {
job := job
group.Go(func() error {
result := job()
if result.Err != nil {
return fmt.Errorf("%s: %w", result.RecommendType, result.Err)
}
if filterCompNSPath && result.RecommendType == constants.CompNSPathRecommendHierarchyType {
result.QueryDatas = filterLocalNSPathResults(result.QueryDatas)
}
mu.Lock()
results[result.RecommendType.String()] = result
mu.Unlock()
return nil
})
}
if err := group.Wait(); err != nil {
logger.Error(ctx, logMsg, "error", err)
}
return results
}
// levelOneRedisSearch 处理第一段输入的搜索, 例如 grid 或本地 nspath。
func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, searchInput string, searchRedisKey string, fanInChan chan SearchResult) {
func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, searchInput string, searchRedisKey string) (result SearchResult) {
defer func() {
if r := recover(); r != nil {
logger.Error(ctx, "searchFunc panicked", "panic", r)
fanInChan <- SearchResult{
result = SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
@ -54,64 +88,59 @@ func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy const
if err != nil {
logger.Error(ctx, "redis membership check failed", "key", searchRedisKey, "member", searchInput, "op", "SIsMember", "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
// the input key is the complete hierarchical value
if exists {
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: []string{"."},
IsFuzzy: false,
Err: nil,
}
return
}
// process fuzzy search result
recommends, offset, err := runFuzzySearch(ctx, rdb, searchInput, "", hierarchy, recommendLenType)
if err != nil {
logger.Error(ctx, fmt.Sprintf("fuzzy search failed for %s hierarchical", util.GetLevelStrByRdsKey(searchRedisKey)), "search_input", searchInput, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
if len(recommends) > 0 {
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: recommends,
IsFuzzy: true,
Offset: offset,
Err: nil,
}
return
}
recommends, err = fallbackAllCurrentLevel(ctx, rdb, hierarchy)
if err != nil {
logger.Error(ctx, "fallback all keys at current level failed", "hierarchy", hierarchy, "search_input", searchInput, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: true,
IsFallback: true,
Err: err,
}
return
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: recommends,
IsFuzzy: true,
@ -124,165 +153,102 @@ func levelOneRedisSearch(ctx context.Context, rdb *redis.Client, hierarchy const
// RedisSearchRecommend define func of redis search by input string and return recommend results
func RedisSearchRecommend(ctx context.Context, input string) map[string]SearchResult {
rdb := diagram.GetRedisClientInstance()
finalizeResults := func(results map[string]SearchResult) map[string]SearchResult {
finalizeResults := func(normalizeInput string, results map[string]SearchResult) map[string]SearchResult {
results = suppressFallbackResultsWhenConcreteHitExists(results)
return normalizeRecommendResults(input, results)
return normalizeRecommendResults(normalizeInput, results)
}
if input == "" {
fanInChan := make(chan SearchResult, 2)
// return all grid tagname
go getAllKeyByGridLevel(ctx, rdb, fanInChan)
// return all component nspath
go getAllKeyByNSPathLevel(ctx, rdb, fanInChan)
results := make(map[string]SearchResult)
for range 2 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "return all keys at the special level from redis failed", "recommend_type", result.RecommendType, "error", result.Err)
continue
}
if result.RecommendType == constants.CompNSPathRecommendHierarchyType {
result.QueryDatas = filterLocalNSPathResults(result.QueryDatas)
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
if input == "" || shouldFallbackToInitialRecommend(input) {
results := runRecommendSearches(ctx, "return all keys at the special level from redis failed", true,
func() SearchResult {
return getAllKeyByGridLevel(ctx, rdb)
},
func() SearchResult {
return getAllKeyByNSPathLevel(ctx, rdb)
},
)
return finalizeResults("", results)
}
inputSlice := strings.Split(input, ".")
inputSliceLen := len(inputSlice)
fanInChan := make(chan SearchResult, 4)
switch inputSliceLen {
case 1:
searchInput := inputSlice[0]
// grid tagname search
go levelOneRedisSearch(ctx, rdb, constants.GridRecommendHierarchyType, constants.FullRecommendLength, searchInput, constants.RedisAllGridSetKey, fanInChan)
// component nspath search
go levelOneRedisSearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.IsLocalRecommendLength, searchInput, constants.RedisAllCompNSPathSetKey, fanInChan)
results := make(map[string]SearchResult)
// TODO 后续根据支持的数据标识语法长度,进行值的变更
for range 2 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "exec redis fuzzy search by key failed", "recommend_type", result.RecommendType, "error", result.Err)
continue
}
if result.RecommendType == constants.CompNSPathRecommendHierarchyType {
result.QueryDatas = filterLocalNSPathResults(result.QueryDatas)
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "exec redis fuzzy search by key failed", true,
func() SearchResult {
return levelOneRedisSearch(ctx, rdb, constants.GridRecommendHierarchyType, constants.FullRecommendLength, searchInput, constants.RedisAllGridSetKey)
},
func() SearchResult {
return levelOneRedisSearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.IsLocalRecommendLength, searchInput, constants.RedisAllCompNSPathSetKey)
},
)
return finalizeResults(input, results)
case 2:
// zone tagname search
go handleLevelFuzzySearch(ctx, rdb, constants.ZoneRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllZoneSetKey, inputSlice, fanInChan)
// component tagname search
go handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllCompTagSetKey, inputSlice, fanInChan)
// measurement tagname search by token4-token7 shorthand
go handleNSPathMeasSearch(ctx, rdb, inputSlice, fanInChan)
results := make(map[string]SearchResult)
for range 3 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
continue
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.ZoneRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllZoneSetKey, inputSlice)
},
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllCompTagSetKey, inputSlice)
},
func() SearchResult {
return handleNSPathMeasSearch(ctx, rdb, inputSlice)
},
)
return finalizeResults(input, results)
case 3:
// station tanname search
go handleLevelFuzzySearch(ctx, rdb, constants.StationRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllStationSetKey, inputSlice, fanInChan)
// config search
go handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice, fanInChan)
results := make(map[string]SearchResult)
for range 2 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
continue
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.StationRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllStationSetKey, inputSlice)
},
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice)
},
)
return finalizeResults(input, results)
case 4:
// component nspath search
go handleLevelFuzzySearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompNSPathSetKey, inputSlice, fanInChan)
// measurement tagname search
go handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice, fanInChan)
results := make(map[string]SearchResult)
for range 2 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
continue
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.CompNSPathRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompNSPathSetKey, inputSlice)
},
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.IsLocalRecommendLength, constants.RedisAllConfigSetKey, inputSlice)
},
)
return finalizeResults(input, results)
case 5:
// component tagname search
go handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompTagSetKey, inputSlice, fanInChan)
results := make(map[string]SearchResult)
for range 1 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
continue
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.CompTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllCompTagSetKey, inputSlice)
},
)
return finalizeResults(input, results)
case 6:
// config search
go handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllConfigSetKey, inputSlice, fanInChan)
results := make(map[string]SearchResult)
for range 1 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
continue
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.ConfigRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllConfigSetKey, inputSlice)
},
)
return finalizeResults(input, results)
case 7:
// measurement tagname search
go handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllMeasTagSetKey, inputSlice, fanInChan)
results := make(map[string]SearchResult)
for range 1 {
result := <-fanInChan
if result.Err != nil {
logger.Error(ctx, "query all keys at the special level from redis failed", "query_key", result.RecommendType, "error", result.Err)
continue
}
results[result.RecommendType.String()] = result
}
return finalizeResults(results)
results := runRecommendSearches(ctx, "query all keys at the special level from redis failed", false,
func() SearchResult {
return handleLevelFuzzySearch(ctx, rdb, constants.MeasTagRecommendHierarchyType, constants.FullRecommendLength, constants.RedisAllMeasTagSetKey, inputSlice)
},
)
return finalizeResults(input, results)
default:
logger.Error(ctx, "unsupport length of search input", "input_len", inputSliceLen)
return nil
}
}
func shouldFallbackToInitialRecommend(input string) bool {
return strings.HasPrefix(input, ".")
}
// suppressFallbackResultsWhenConcreteHitExists 有明确命中时丢弃兜底结果, 避免返回过宽推荐。
func suppressFallbackResultsWhenConcreteHitExists(results map[string]SearchResult) map[string]SearchResult {
hasConcreteHit := false
@ -494,23 +460,22 @@ func getAllSetKeyByHierarchy(hierarchy constants.RecommendHierarchyType) (string
}
// getAllKeyByGridLevel 返回所有 grid tag, 用于空输入时的初始推荐。
func getAllKeyByGridLevel(ctx context.Context, rdb *redis.Client, fanInChan chan SearchResult) {
func getAllKeyByGridLevel(ctx context.Context, rdb *redis.Client) SearchResult {
setKey := constants.RedisAllGridSetKey
hierarchy := constants.GridRecommendHierarchyType
members, err := rdb.SMembers(ctx, setKey).Result()
if err != nil && err != redigo.ErrNil {
logger.Error(ctx, "get all members from redis by special key failed", "key", setKey, "op", "SMembers", "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: members,
IsFuzzy: false,
@ -519,23 +484,22 @@ func getAllKeyByGridLevel(ctx context.Context, rdb *redis.Client, fanInChan chan
}
// getAllKeyByNSPathLevel 返回所有组件 nspath, 用于空输入时的初始推荐。
func getAllKeyByNSPathLevel(ctx context.Context, rdb *redis.Client, fanInChan chan SearchResult) {
func getAllKeyByNSPathLevel(ctx context.Context, rdb *redis.Client) SearchResult {
queryKey := constants.RedisAllCompNSPathSetKey
hierarchy := constants.CompNSPathRecommendHierarchyType
members, err := rdb.SMembers(ctx, queryKey).Result()
if err != nil && err != redigo.ErrNil {
logger.Error(ctx, "get all members by special key failed", "key", queryKey, "op", "SMembers", "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: members,
IsFuzzy: false,
@ -611,7 +575,7 @@ func getSpecificKeyByLength(hierarchy constants.RecommendHierarchyType, keyPrefi
}
// handleNSPathMeasSearch 处理 nspath.measurement 的简写搜索路径。
func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice []string, fanInChan chan SearchResult) {
func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice []string) SearchResult {
hierarchy := constants.MeasTagRecommendHierarchyType
nsPath := inputSlice[0]
searchInput := inputSlice[1]
@ -619,22 +583,20 @@ func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice [
nsPathExists, err := rdb.SIsMember(ctx, constants.RedisAllCompNSPathSetKey, nsPath).Result()
if err != nil {
logger.Error(ctx, "check nspath exist from redis set failed", "key", constants.RedisAllCompNSPathSetKey, "nspath", nsPath, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
if !nsPathExists {
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: []string{},
IsFuzzy: false,
Err: nil,
}
return
}
queryKey := fmt.Sprintf(constants.RedisSpecCompNSPathMeasSetKey, nsPath)
@ -642,57 +604,52 @@ func handleNSPathMeasSearch(ctx context.Context, rdb *redis.Client, inputSlice [
members, err := rdb.SMembers(ctx, queryKey).Result()
if err != nil && err != redis.Nil {
logger.Error(ctx, "query measurement tags by nspath failed", "key", queryKey, "nspath", nsPath, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: combineNSPathMeasResults(nsPath, members),
IsFuzzy: false,
Err: nil,
}
return
}
measTagExists, err := rdb.SIsMember(ctx, queryKey, searchInput).Result()
if err != nil {
logger.Error(ctx, "check measurement tag exist from nspath set failed", "key", queryKey, "meas_tag", searchInput, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
if measTagExists {
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: []string{""},
IsFuzzy: false,
Err: nil,
}
return
}
recommends, offset, err := runNSPathMeasFuzzySearch(ctx, nsPath, searchInput)
if err != nil {
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: true,
Err: err,
}
return
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: recommends,
IsFuzzy: true,
@ -760,7 +717,7 @@ func splitLastToken(term string) (string, string) {
}
// handleLevelFuzzySearch 处理第二层及以后层级的精确、模糊和兜底推荐。
func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, redisSetKey string, inputSlice []string, fanInChan chan SearchResult) {
func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, redisSetKey string, inputSlice []string) SearchResult {
inputSliceLen := len(inputSlice)
searchInputIndex := inputSliceLen - 1
searchInput := inputSlice[searchInputIndex]
@ -783,36 +740,33 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
keyExists, err := rdb.SIsMember(ctx, redisSetKey, specificalKey).Result()
if err != nil {
logger.Error(ctx, "check key exist from redis set failed ", "key", redisSetKey, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
if !keyExists {
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: []string{},
IsFuzzy: false,
Err: nil,
}
return
}
}
members, err := queryMemberFromSpecificsLevel(ctx, rdb, hierarchy, specificalKey)
if err != nil && err != redis.Nil {
logger.Error(ctx, "query members from redis by special key failed", "key", specificalKey, "member", searchInput, "op", "SMember", "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
recommandResults := combineQueryResultByInput(hierarchy, recommendLenType, inputSlice, members)
@ -838,25 +792,23 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
}
recommandResults = secondConfirmResults
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: recommandResults,
IsFuzzy: false,
Err: nil,
}
return
}
keyExists, err := rdb.SIsMember(ctx, redisSetKey, searchInput).Result()
if err != nil {
logger.Error(ctx, "check key exist from redis set failed ", "key", redisSetKey, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
if keyExists {
@ -867,26 +819,24 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
QueryData = []string{"."}
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: QueryData,
IsFuzzy: false,
Err: nil,
}
return
}
// start redis fuzzy search
recommends, offset, err := runFuzzySearch(ctx, rdb, searchInput, searchPrefix, hierarchy, recommendLenType)
if err != nil {
logger.Error(ctx, "fuzzy search failed by hierarchy", "hierarchy", hierarchy, "search_input", searchInput, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: false,
Err: err,
}
return
}
isFallback := false
@ -895,20 +845,19 @@ func handleLevelFuzzySearch(ctx context.Context, rdb *redis.Client, hierarchy co
recommends, err = fallbackCurrentLevelByInput(ctx, rdb, hierarchy, inputSlice)
if err != nil {
logger.Error(ctx, "fallback all keys at current level failed", "hierarchy", hierarchy, "search_input", searchInput, "error", err)
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: nil,
IsFuzzy: true,
IsFallback: true,
Err: err,
}
return
}
isFallback = true
offset = 0
}
fanInChan <- SearchResult{
return SearchResult{
RecommendType: hierarchy,
QueryDatas: recommends,
IsFuzzy: true,
@ -992,7 +941,7 @@ func runFuzzySearch(ctx context.Context, rdb *redis.Client, searchInput string,
}
if termHierarchyLen == compareHierarchyLen && termPrefix == comparePrefix && strings.HasPrefix(termLastPart, searchInput) {
exists, err := fuzzyRecommendMemberExists(ctx, rdb, hierarchy, recommendLenType, comparePrefix, termLastPart)
exists, err := fuzzyRecommendMemberExists(ctx, rdb, hierarchy, comparePrefix, termLastPart)
if err != nil || !exists {
logger.Info(ctx, "fuzzy recommend term not found in specific redis set",
"hierarchy", hierarchy,
@ -1034,8 +983,8 @@ func fuzzyRecommendOffset(searchPrefix string, searchInput string) int {
}
// fuzzyRecommendMemberExists 校验模糊候选末级 token 是否存在于对应 Redis set。
func fuzzyRecommendMemberExists(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, recommendLenType string, comparePrefix string, termLastPart string) (bool, error) {
setKey, ok := fuzzyRecommendMemberSetKey(hierarchy, recommendLenType, comparePrefix)
func fuzzyRecommendMemberExists(ctx context.Context, rdb *redis.Client, hierarchy constants.RecommendHierarchyType, comparePrefix string, termLastPart string) (bool, error) {
setKey, ok := fuzzyRecommendMemberSetKey(hierarchy, comparePrefix)
if !ok {
return true, nil
}
@ -1043,7 +992,7 @@ func fuzzyRecommendMemberExists(ctx context.Context, rdb *redis.Client, hierarch
}
// fuzzyRecommendMemberSetKey 返回模糊候选校验时应使用的 Redis set key。
func fuzzyRecommendMemberSetKey(hierarchy constants.RecommendHierarchyType, recommendLenType string, comparePrefix string) (string, bool) {
func fuzzyRecommendMemberSetKey(hierarchy constants.RecommendHierarchyType, comparePrefix string) (string, bool) {
switch hierarchy {
case constants.GridRecommendHierarchyType:
return constants.RedisAllGridSetKey, true

View File

@ -6,8 +6,8 @@ import (
"time"
)
// GenNanoTsStr define func to generate nanosecond timestamp string by current time
func GenNanoTsStr() string {
// GenNanoTSStr define func to generate nanosecond timestamp string by current time
func GenNanoTSStr() string {
now := time.Now()
nanoseconds := now.UnixNano()
timestampStr := strconv.FormatInt(nanoseconds, 10)