Mongodb 在Golang中运行cron,同时使用不同的数据库
我正在做一个基于SaaS的项目,商家可以在这个项目上订阅来建立他们的在线商店 项目概述 我正在使用Golang(后端)、Mongodb数据库服务和Angular4(前端)构建系统。我有多个商人可以建立他们的商店。每个商户都有自己的url(在url中将其企业名称作为子域)来连接到其数据库 对于路由,我在后端使用Golang的Gin框架 问题 我想为特定于商家的数据库运行cron作业。在这些cron作业中,有些操作需要连接到数据库。但在我的路由中,在调用API的路由之前,不会设置数据库。最终,cron无法使用正确的数据运行 代码 cron.goMongodb 在Golang中运行cron,同时使用不同的数据库,mongodb,go,cron,Mongodb,Go,Cron,我正在做一个基于SaaS的项目,商家可以在这个项目上订阅来建立他们的在线商店 项目概述 我正在使用Golang(后端)、Mongodb数据库服务和Angular4(前端)构建系统。我有多个商人可以建立他们的商店。每个商户都有自己的url(在url中将其企业名称作为子域)来连接到其数据库 对于路由,我在后端使用Golang的Gin框架 问题 我想为特定于商家的数据库运行cron作业。在这些cron作业中,有些操作需要连接到数据库。但在我的路由中,在调用API的路由之前,不会设置数据库。最终,cro
package cron
import (
"gopkg.in/robfig/cron.v2"
"controllers"
)
func RunCron(){
c := cron.New()
c.AddFunc("@every 0h1m0s", controllers.ExpireProviderInvitation)
c.Start()
}
func NewRouter() {
router := gin.Default()
router.Use(gin.Recovery())
router.Use(SetMerchantDatabase)
public := router.Group("/api/v1")
for _, route := range publicRoutes{
switch route.Method {
case "GET" : public.GET(route.Pattern, route.HandlerFunc)
case "POST" : public.POST(route.Pattern, route.HandlerFunc)
case "PUT" : public.PUT(route.Pattern, route.HandlerFunc)
case "DELETE": public.DELETE(route.Pattern, route.HandlerFunc)
default : public.GET(route.Pattern, func(c *gin.Context){
c.JSON(200, gin.H{
"result": "Specify a valid http method with this route.",
})
})
}
}
router.NoRoute(controllers.UnauthorizedAccessResponse)
router.Run(":8080")
}
func SetMerchantDatabase(c *gin.Context){
subdomain := strings.Split(c.Request.Host, ".")
if len(subdomain) > 0{
config.Database = subdomain[0]
config.CurrentBusinessName = subdomain[0]
}else{
errMsg := "Failed: Invalid domain in headers."
response := controllers.ResponseController{
config.FailureCode,
config.FailureFlag,
errMsg,
nil,
}
controllers.GetResponse(c, response)
c.Abort()
}
c.Next()
}
package main
import (
"cron"
)
func main(){
cron.RunCron()
NewRouter()
}
控制器功能
func ExpireProviderInvitation() {
bookingAcceptTimeSetting, _ := models.GetMerchantSetting(bson.M{"section": "providers", "option_name": "bookings_accept_time"})
if bookingAcceptTimeSetting.OptionValue != nil{
allInvitations, _ := models.GetAllBookingInvitations(bson.M{ "status": 0, "send_type": "invitation", "datetime": bson.M{"$le": float64(time.Now().Unix()) - bookingAcceptTimeSetting.OptionValue.(float64)} })
if len(allInvitations) > 0 {
for _, invitationData := range allInvitations {
_ = GetNextAvailableProvider(invitationData.Bid, invitationData.Pid)
}
}
}
}
路由器。开始
package cron
import (
"gopkg.in/robfig/cron.v2"
"controllers"
)
func RunCron(){
c := cron.New()
c.AddFunc("@every 0h1m0s", controllers.ExpireProviderInvitation)
c.Start()
}
func NewRouter() {
router := gin.Default()
router.Use(gin.Recovery())
router.Use(SetMerchantDatabase)
public := router.Group("/api/v1")
for _, route := range publicRoutes{
switch route.Method {
case "GET" : public.GET(route.Pattern, route.HandlerFunc)
case "POST" : public.POST(route.Pattern, route.HandlerFunc)
case "PUT" : public.PUT(route.Pattern, route.HandlerFunc)
case "DELETE": public.DELETE(route.Pattern, route.HandlerFunc)
default : public.GET(route.Pattern, func(c *gin.Context){
c.JSON(200, gin.H{
"result": "Specify a valid http method with this route.",
})
})
}
}
router.NoRoute(controllers.UnauthorizedAccessResponse)
router.Run(":8080")
}
func SetMerchantDatabase(c *gin.Context){
subdomain := strings.Split(c.Request.Host, ".")
if len(subdomain) > 0{
config.Database = subdomain[0]
config.CurrentBusinessName = subdomain[0]
}else{
errMsg := "Failed: Invalid domain in headers."
response := controllers.ResponseController{
config.FailureCode,
config.FailureFlag,
errMsg,
nil,
}
controllers.GetResponse(c, response)
c.Abort()
}
c.Next()
}
package main
import (
"cron"
)
func main(){
cron.RunCron()
NewRouter()
}
main.go
package cron
import (
"gopkg.in/robfig/cron.v2"
"controllers"
)
func RunCron(){
c := cron.New()
c.AddFunc("@every 0h1m0s", controllers.ExpireProviderInvitation)
c.Start()
}
func NewRouter() {
router := gin.Default()
router.Use(gin.Recovery())
router.Use(SetMerchantDatabase)
public := router.Group("/api/v1")
for _, route := range publicRoutes{
switch route.Method {
case "GET" : public.GET(route.Pattern, route.HandlerFunc)
case "POST" : public.POST(route.Pattern, route.HandlerFunc)
case "PUT" : public.PUT(route.Pattern, route.HandlerFunc)
case "DELETE": public.DELETE(route.Pattern, route.HandlerFunc)
default : public.GET(route.Pattern, func(c *gin.Context){
c.JSON(200, gin.H{
"result": "Specify a valid http method with this route.",
})
})
}
}
router.NoRoute(controllers.UnauthorizedAccessResponse)
router.Run(":8080")
}
func SetMerchantDatabase(c *gin.Context){
subdomain := strings.Split(c.Request.Host, ".")
if len(subdomain) > 0{
config.Database = subdomain[0]
config.CurrentBusinessName = subdomain[0]
}else{
errMsg := "Failed: Invalid domain in headers."
response := controllers.ResponseController{
config.FailureCode,
config.FailureFlag,
errMsg,
nil,
}
controllers.GetResponse(c, response)
c.Abort()
}
c.Next()
}
package main
import (
"cron"
)
func main(){
cron.RunCron()
NewRouter()
}
上述代码的解释
示例路线可以是:
Route{ "AddCustomer", "POST", "/customer", controllers.SaveCustomer },
示例API url可以是:
其中,“业务名称”是在调用API时设置的数据库。
我想在不调用API路由的情况下运行cron
替代方法
在Shell脚本中,我们可以通过点击url作为命令来运行cron。为此,我可以创建一个url,将其作为命令运行。但这是我的理论方法。我也不知道如何获得不同的商家数据库
我不确定这种方法是否有效。非常感谢您提供的任何帮助。您需要调整
SetMerchantDatabase
以独立于路由器工作。然后您也可以让它为Cron设置东西。您最好使用gofmt
。你的代码目前很难阅读。好吧,那么你的代码有很多错误。让中间件设置一个全局变量肯定会导致a)程序崩溃,b)随机访问错误的数据库。我向您保证,您的代码有缺陷。像您这样设置一个全局变量是很快的。如果两个请求同时发生,它们将发生冲突,您的程序将因数据竞争而崩溃。如果两个请求几乎同时发生,则其中一个可能会使用另一个的数据库配置。除非你打算让你的程序崩溃,或者使用错误的数据库,否则这些都是错误;将数据库选择绑定到请求处理会使创建cron作业变得不必要的困难。让shell脚本发出localhost GET请求更糟糕。您的请求处理程序和cron任务都应该从其他地方获得它们的DB连接;来自路由器的请求处理程序、来自命令行的cron任务、env或config文件。请求非现场资源的建议对于SO来说是离题的。@Filmzy,要独立于路由器工作SetMerchantDatabase
,我将如何获取数据库名称,因为现在它来自一个访问API的url。我可能需要从中获取数据库名称的url。我们不能使用shell scipt吗??我为此搜索了很多,但没有找到适合我要求的内容。你的程序设计得很糟糕。没有一个正确的方法来修复它,因为目前它是完全错误的。