Mongodb 在Golang中运行cron,同时使用不同的数据库

Mongodb 在Golang中运行cron,同时使用不同的数据库,mongodb,go,cron,Mongodb,Go,Cron,我正在做一个基于SaaS的项目,商家可以在这个项目上订阅来建立他们的在线商店 项目概述 我正在使用Golang(后端)、Mongodb数据库服务和Angular4(前端)构建系统。我有多个商人可以建立他们的商店。每个商户都有自己的url(在url中将其企业名称作为子域)来连接到其数据库 对于路由,我在后端使用Golang的Gin框架 问题 我想为特定于商家的数据库运行cron作业。在这些cron作业中,有些操作需要连接到数据库。但在我的路由中,在调用API的路由之前,不会设置数据库。最终,cro

我正在做一个基于SaaS的项目,商家可以在这个项目上订阅来建立他们的在线商店

项目概述

我正在使用Golang(后端)、Mongodb数据库服务和Angular4(前端)构建系统。我有多个商人可以建立他们的商店。每个商户都有自己的url(在url中将其企业名称作为子域)来连接到其数据库

对于路由,我在后端使用Golang的Gin框架

问题

我想为特定于商家的数据库运行cron作业。在这些cron作业中,有些操作需要连接到数据库。但在我的路由中,在调用API的路由之前,不会设置数据库。最终,cron无法使用正确的数据运行

代码

cron.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()
} 
控制器功能

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吗??我为此搜索了很多,但没有找到适合我要求的内容。你的程序设计得很糟糕。没有一个正确的方法来修复它,因为目前它是完全错误的。