Picci
Picci

Reputation: 17762

Making sure that only one request is processed at a time and other requests incoming are discarded

I have a goroutine, let's call it goProcessor, which processes requests coming in from other goroutines.

goProcessor can only process one request at a time. If a requests, let's call it req2, comes in while goProcessor is still processing the previous req1 request, req2 has to be discarded and will be simply lost.

I have implemented such logic using an unbuffered channel and the select statement, but I am not sure whether there could be a simpler more elegant way to accomplish what I want. A simple example of my solution is this

var c = make(chan string)

func main() {

    goRequest := func(request string, delay int) {
        time.Sleep(time.Duration(delay) * time.Second)
        fmt.Printf("Here I am request %v\n", request)
        select {
        case c <- request:
            fmt.Printf("%v sent\n", request)
        default:
            fmt.Printf("%v discarded\n", request)
        }
    }

    goProcessor := func() {
        for {
            msg := <-c
            fmt.Println("received", msg)
            time.Sleep(3 * time.Second)
            fmt.Println("processed", msg)
        }
    }

    go goRequest("First req", 1)
    go goRequest("Second req", 2)
    go goRequest("Third req", 5)
    go goProcessor()

    time.Sleep(10 * time.Second)

    fmt.Println("Main has finished")
}

Upvotes: 2

Views: 494

Answers (1)

icza
icza

Reputation: 417572

What you did is perfectly fine and clean. Only thing you could simplify on it is to use for range in goProcessor() like this:

for msg := range c {
    // ...
}

but other than that it's idiomatic.

A "TryLock" might come to mind to use here. There is no "TryLock" in the standard lib (there are 3rd party libs for that), but using it isn't simpler or more idiomatic in your case, you have to check if TryLock() returns true, and you have to unlock it. And you still need a channel to send the results to the processor, so your solution is simpler and cleaner.

Upvotes: 1

Related Questions