Gin.context изменяется при переходе в goroutine? - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь использовать gin для обработки HTTP-запросов, у меня есть обработчик, который принимает запрос, например

r.DELETE("/workspaces/:id", DoSomething)

Delete - это функция, работа которой заключается в том, чтобы вызвать действие "Destroy", которое может занять некоторое время. а затем выполните действие «Удалить».

Я также не хочу, чтобы пользовательский интерфейс блокировался, поэтому я хочу, чтобы объединение действий «Уничтожить» и «Удалить» выполнялось в асинхронном режиме.

Это моя реализация DoSomething.

func DoSomething(C *gin.Context){
    CallDestroy(c)
    go func(c){
        timeout := time.After(30 * time.Minute)
        ticker := time.NewTicker(10 * time.Second)

        for {
            select {
            // Got a timeout! fail with a timeout error
            case <-timeout:
                return
            // Got a tick, we should check on doSomething()
            case <-ticker.C:
                status := PoolForCompletion(c)
                if status.Status == "FAILED" {
                    logger.Error("Detroy activity failed")
                    return
                } else {
                    status := Delete(c)
                    return
                }
            }
        }
    }(c)
}

Для операции «Удалить» нужен идентификатор, который я извлекаю в реализации Удалить из params.

c.params("id")
fmt.Println(c.params("id")

Проблема, с которой я сталкиваюсь, заключается в смешении идентификаторов в рабочей области удаления.

Таким образом, теоретически для каждого вызова DoSomething удаление будет запускаться с уникальным идентификатором. Предположим, я делаю последовательные вызовы с параметрами 1,2,3. Так что в логах я должен увидеть 1,2,3.

Но то, что я вижу, это 1,3,3 или 1,2,2.

Я изучил контекстную документацию и узнал, что я использую указатель gin.context. Поэтому я также попытался использовать

C.Copy()
func DoSomething(C *gin.Context){
    CallDestroy(c.Copy())
    go func(c){
        timeout := time.After(30 * time.Minute)
        ticker := time.NewTicker(10 * time.Second)

        for {
            select {
            // Got a timeout! fail with a timeout error
            case <-timeout:
                return
            // Got a tick, we should check on doSomething()
            case <-ticker.C:
                status := PoolForCompletion(c.Copy())
                if status.Status == "FAILED" {
                    logger.Error("Detroy activity failed")
                    return
                } else {
                    status := Delete(c.Copy())
                    return
                }
            }
        }
    }(c.Copy())
}

Для создания копии контекста. Тем не менее, я получаю такое же поведение. Насколько я понимаю, контекст будет изолирован для всех запросов и не изменится в процедурах, даже если я не использую копию.

...