package utils import ( "context" "fmt" "net/textproto" "os" "strings" "github.com/google/uuid" "github.com/pkg/errors" ) const ( UnifiedPattern = "unified_pattern_" // 为了只注册一个handler到asynq,所有的task type都要加上这个前缀来做模糊匹配 ) // ExtendUnifiedPattern 给任务type追加通用前缀。为了让每个队列固定挂载一个统一的handler func ExtendUnifiedPattern(queue, taskType string) (string, error) { if strings.Contains(queue, ".") || strings.Contains(taskType, ".") { return "", errors.Errorf("cannot contain '.': %s/%s", queue, taskType) } return UnifiedPattern + queue + "." + taskType, nil } // TrimUnifiedPattern 将任务type去除通用前缀,返回AddTask时真正传入的type func TrimUnifiedPattern(taskType string) string { subs := strings.SplitN(taskType, ".", 2) if len(subs) == 2 { return subs[1] } else { // 走到这里其实是出问题了,会造成任务找不到handler // 在extendUnifiedPattern兜底了,理论上不应该走到这里 panic(fmt.Sprintf("found no '.' in task type: %s", taskType)) } } // GenDefaultQueuePrefix 默认队列前缀:环境、服务名、灰度,用于灰度能力支持、环境安全、服务间隔离(连同一redis时) func GenDefaultQueuePrefix() string { var prefixes []string if env := os.Getenv("PROJECT_ENV"); env != "" { prefixes = append(prefixes, env) } else { prefixes = append(prefixes, "unkonwn_env") } if service := os.Getenv("PROJECT_NAME"); service != "" { prefixes = append(prefixes, service) } else { prefixes = append(prefixes, "unkonwn_service") } if gray := os.Getenv("GRAY"); gray == "1" { prefixes = append(prefixes, "gray") } if os.Getenv("LOCAL_DEBUG") == "1" { // 开发本地debug模式,更严格的隔离,加入hostname hostname, _ := os.Hostname() prefixes = append(prefixes, "local_debug", hostname) } return strings.Join(prefixes, ".") + "." } // BaseContext 向context中注入logger包WithCtx需要的请求ID、请求者,方便串联同一次任务执行的日志 func BaseContext() context.Context { ctx := context.Background() key := textproto.CanonicalMIMEHeaderKey("Xc-Req-Id") ctx = context.WithValue(ctx, key, uuid.NewString()) key = "caller" ctx = context.WithValue(ctx, key, "me-xcasynq") return ctx }