草庐IT

go - 超时同时等待两个结果

coder 2024-07-06 原文

用例

我想对数据库并行运行两个查询,并在最长 600 毫秒的时间后返回,无论我已经获取到那个点。我正在努力实现此要求的并发性。

代码

func (s *Service) GetCustomerStats(ctx context.Context, customerUUID string) *CustomerStats {
    stats := &CustomerStats{
        CustomerUUID: customerUUID,
        Type:         "ERROR",
        OrderCount:   "ERROR",
    }

    var wg sync.WaitGroup
    var mu sync.Mutex

    // Get order count
    wg.Add(1)
    go func() {
        defer wg.Done()
        orderCount, err := s.Storage.GetOrderCount(ctx, customerUUID)
        if err != nil {
            return
        }

        mu.Lock()
        stats.OrderCount = strconv.Itoa(orderCount)
        if orderCount == 0 {
            stats.OrderCount = "NA"
        }
        mu.Unlock()
    }()

    // Get customer type
    wg.Add(1)
    go func() {
        defer wg.Done()
        type, err := s.Storage.GetCustomerType(ctx, customerUUID)
        if err != nil {
            return
        }

        mu.Lock()
        stats.Type = strconv.Itoa(type)
        mu.Unlock()
    }()

    wg.Wait()

    return stats
}

问题

我传递给该函数的上下文定义了 600 毫秒的超时。我将它传递给存储库,数据库驱动程序也使用它,但它不保证它会在那段时间内响应,因为它确实安排了一些重试。

但是我必须确保此函数在传递的上下文超时(600 毫秒)内返回。我目前正在使用 WaitGroup 来等待结果,但我不知道如何在上下文完成后返回 stats

基本上我正在寻找这样的东西。我的研究表明我可能应该使用表示工作已完成的 channel ,但我不确定我将如何实现它以便它是简单的代码。

    select {
    case wg.Wait()
        return stats
    case <-ctx.Done()
        return stats
    }

最佳答案

您计划在 ctx.Done() 上选择的方式看起来是正确的。
在我看来,错误的是处理可变状态的方式。

尝试这样的事情:

 var state = State{}
 select {
    case type <- typeChan
        stats.Type = type
        if (stats.OrderCount != nil) {
           return stats
        }
    case count <- countChan
        stats.OrderCount = count
        if (stats.Type != nil) {
           return stats
        }
    case <-ctx.Done()
        return stats
    }

现在你的函数应该是这样的:

go func() {        
    orderCount, err := s.Storage.GetOrderCount(ctx, customerUUID)
    if err != nil {
        return // Here you probably want to have errChan
    }

    if orderCount == 0 {
        countChan <- "NA"
    } else {
        countChan <- strconv.Itoa(orderCount)
    }        
}()

这有点粗略,因为你的例子很复杂,但应该给你遵循的方向。

关于go - 超时同时等待两个结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57398261/

有关go - 超时同时等待两个结果的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  3. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  4. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  5. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

  6. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  7. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  8. Ruby 在 n *milli* 秒后超时一段代码 - 2

    在Ruby中,我需要在n毫秒秒后暂停一段代码的执行。我知道RubyTimeout库支持秒的超时:http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/index.html这可能吗? 最佳答案 只需为超时使用十进制值。n毫秒的示例:Timeout::timeout(n/1000.0){sleep(100)} 关于Ruby在n*milli*秒后超时一段代码,我们在StackOverflow上找到一个类似的问题: https:

  9. arrays - 如何在下面的示例中将两个值数组分组为 n 个值数组? - 2

    我已经有很多两个值数组,例如下面的例子ary=[[1,2],[2,3],[1,3],[4,5],[5,6],[4,7],[7,8],[4,8]]我想把它们分组到[1,2,3],[4,5],[5,6],[4,7,8]因为意思是1和2有关系,2和3有关系,1和3有关系,所以1,2,3都有关系我如何通过ruby​​库或任何算法来做到这一点? 最佳答案 这是基本Bron–Kerboschalgorithm的Ruby实现:classGraphdefinitialize(edges)@edges=edgesenddeffind_maximum_

  10. ruby - 使用 ruby​​ gem net-ssh-multi 同时在多个服务器上执行 sudo 命令 - 2

    在previousquestion中我想出了如何在多个服务器上启动经过密码验证的sshsession来运行单个命令。现在我需要能够执行“sudo”命令。问题是,net-ssh-multi没有分配sudo需要运行的伪终端(pty),导致以下错误:[127.0.0.1:stderr]sudo:sorry,youmusthaveattytorunsudo根据documentation,可以通过调用channel对象的方法来分配伪终端,但是,以下代码不起作用:它会生成上面的“notty”错误:require'net/ssh'require'net/ssh/multi'Net::SSH::Mul

随机推荐