我正在try 在我的项目中实施Asynq,这是一个著名的Golang作业(job)调度器,目前我对缺乏有关任务本身内部可能的具体场景的文档感到非常困惑.请注意,互联网上甚至没有任何痕迹,这让我认为我想要解决这个问题的方式可能是非常错误的.
通常,我会在main.go
中设置一个数据库连接,并通过依赖项注入与所有内容进行通信.
clients := services.Clients{
Db: dbClient,
Redis: redisClient,
// and many more
}
// In my case I use GraphQL to handle requests
srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &resolvers.Resolver{
Services: &catalogue, // some services I need to use depending the request
Clients: &clients, // here we communicate the database, etc.
}}))
正如您所看到的,我实际上可以将clients
传达给我的请求处理程序(解析器),并在那里过上幸福的生活,查询数据库.
设置Asynq时,客户端是这样的
asynqClient := asynq.NewClient(asynq.RedisClientOpt{
Addr: os.Getenv("REDIS_ENDPOINT"),
DB: 0, // will use the default one
Password: os.Getenv("REDIS_PASSWORD"),
})
defer asynqClient.Close()
tsk, err := tasks.NewPing("pong")
if err != nil {
fmt.Printf("%s", err)
panic(err)
}
_, err = asynqClient.Enqueue(tsk)
if err != nil {
fmt.Printf("%s", err)
panic(err)
}
我已经在tasks.go
中抽象了ping代码
package tasks
import (
"context"
"encoding/json"
"log"
"github.com/hibiken/asynq"
)
// A list of task types.
const (
TypePing = "misc:ping"
)
type pingTaskPayload struct {
Test string
}
func NewPing(test string) (*asynq.Task, error) {
payload, err := json.Marshal(pingTaskPayload{Test: test})
if err != nil {
return nil, err
}
return asynq.NewTask(TypePing, payload), nil
}
func HandlePing(ctx context.Context, t *asynq.Task) error {
var p pingTaskPayload
if err := json.Unmarshal(t.Payload(), &p); err != nil {
return err
}
log.Printf(" [*] Ping received with arguments: %s", p.Test)
return nil
}
你指挥它,它会穿过Redis并在另一边被接住.
asynqServer := asynq.NewServer(
asynq.RedisClientOpt{
Addr: os.Getenv("REDIS_ENDPOINT"),
DB: 0, // will use the default one
Password: os.Getenv("REDIS_PASSWORD"),
},
asynq.Config{Concurrency: 10},
)
mux := asynq.NewServeMux()
mux.HandleFunc(tasks.TypePing, tasks.HandlePing)
go asynqServer.Run(mux)
正如您所看到的,任何地方都没有空间注入任何东西.依赖关系在哪里?为什么它不建议以某种方式将其传达给任务?每个人如何使用它?getting started人从未引用任何依赖性.
理想情况下,我想使用mux.HandleFunc
并将一堆客户端(例如DB连接)提供给tasks.HandlePing
目前,我看到的唯一"可行"解决方案是将我的服务器设置为main
的全局值,以便从系统中的任何地方获取,这是我不想这样做的.我想要一个明确的依赖注入模式.
如何以干净的方式将我的依赖项(clients
个,包括数据库)传达给Asynq?我避免在这里设置全球性是错误的吗?
我已经广泛搜索了几个小时.就像没有人问过自己传递依赖项的问题一样,而且这个库非常有名,所以我可能在某种程度上做错了什么.