Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
270 views
in Technique[技术] by (71.8m points)

go - How to poll HTTP endpoint and update data source?

I am trying to do some CRUD operations which takes longer time. I have come up with the sample playground to demonstrate my problem:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func call(s int) {
    fmt.Println(s)
}

func get() int {
    num := rand.Intn(20-10) + 5
    return num
}

func main() {
    call(1)
    ticker := time.NewTicker(1000 * time.Millisecond)
    stop := make(chan bool, 1)
    check := make(chan string, 1)
    go func() {
        for {
            select {
            case <-stop:
                check <- "done" 
                    fmt.Println("stopped")
                return
            case <-ticker.C:
                randInt := get()
                if randInt == 11 {
                    call(randInt)
                    stop <- true
                } else {
                    call(randInt)
                }
            }
        }
    }()
    
    //fmt.Println(<-stop)
}
  1. It's a http request
  2. At the end of the request, I do return with 202 http then fire a go routine.
  3. Purpose of go routine, to check whether the requested entity is created/deleted/updated/failed than in progress
  4. Demo program runs until it gets random number 11 i.e similar to getting one of the desired status as in point 3.
  5. I feel that there could be a chance where random number never meets 11 for quite long time.(if range is 1 million) So I want to cancel the ticker after 10 func calls.

How do I do this?

Are correct things used i.e ticker, goroutine. Kindly suggest.

Unfortunately, I couldn't decode after referring several forums, posts. Confused more with context, timer and all.

question from:https://stackoverflow.com/questions/65939460/how-to-poll-http-endpoint-and-update-data-source

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In order to limit the number of tries, we simply need to count the attempts made, which is trivial with the existing for loop.

It appears with the stop channel that you intend to make this cancellable as well, but the usage here will not work as expected. You can use a context.Context for this, which can be later incorporated into other calls that accept a context. Otherwise a sync.WaitGroup is the expected method to wait for completion.

Waiting for the goroutine to return can be done with a channel, but you should not rely on sending a single value. As shown in your example, multiple readers (which may have been added later due to refactoring) will cause the other to not receive the signal. If you do use a channel, closing the channel is the canonical way to broadcast a signal.

Using that information, we can come up with this modified example: https://play.golang.org/p/hZiRXtMm-SB

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

maxAttempts := 5

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    ticker := time.NewTicker(1000 * time.Millisecond)

    call(1)

    for i := 1; ; i++ {
        if i >= maxAttempts {
            fmt.Println("too many tries")
            return
        }

        select {
        case <-ctx.Done():
            fmt.Println("cancelled")
            return

        case <-ticker.C:
            randInt := get()
            call(randInt)
            if randInt == 11 {
                fmt.Println("OK")
                return
            }
        }
    }
}()

wg.Wait()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...