猿问

同时等待两个结果并超时

使用案例


我想对数据库并行运行两个查询,并在最多 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 毫秒)内返回。我目前正在使用等待组来等待结果,但我不知道stats上下文完成后如何返回。


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


    select {

    case wg.Wait()

        return stats

    case <-ctx.Done()

        return stats

    }


小怪兽爱吃肉
浏览 94回答 1
1回答

烙印99

您计划选择的方式看起来ctx.Done()是正确的。在我看来,你处理可变状态的方式是错误的。尝试这样的事情:&nbsp;var state = State{}&nbsp;select {&nbsp; &nbsp; case type <- typeChan&nbsp; &nbsp; &nbsp; &nbsp; stats.Type = type&nbsp; &nbsp; &nbsp; &nbsp; if (stats.OrderCount != nil) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return stats&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; case count <- countChan&nbsp; &nbsp; &nbsp; &nbsp; stats.OrderCount = count&nbsp; &nbsp; &nbsp; &nbsp; if (stats.Type != nil) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return stats&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; case <-ctx.Done()&nbsp; &nbsp; &nbsp; &nbsp; return stats&nbsp; &nbsp; }现在你的函数应该是这样的:go func() {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; orderCount, err := s.Storage.GetOrderCount(ctx, customerUUID)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return // Here you probably want to have errChan&nbsp; &nbsp; }&nbsp; &nbsp; if orderCount == 0 {&nbsp; &nbsp; &nbsp; &nbsp; countChan <- "NA"&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; countChan <- strconv.Itoa(orderCount)&nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}()这一切都有点粗略,因为您的示例非常复杂,但应该为您提供遵循的方向。
随时随地看视频慕课网APP

相关分类

Go
我要回答