How to decide between context. With a line or a simple timer?

In the Golang, I'm pretty new to the intent of passing contexts downstream to other methods and functions. I understand how context works, how it is used, how it stores its values, how it relates to the parent context and their behavior - I just don’t understand why to use context in the first place.

In a more specific example, which is the actual reason for this issue, in the company I work for, we identified some very lengthy requests that occur so often due to the case with the edge.

The obvious decision that we decided to take, given our limitations, until we take the time to fix the root cause, is to kill requests that take more than 5 minutes.

The method that launches our transactions accepts the context that is initially initiated in the API call. This context is passed before the transaction function. At this moment, I found 2 solutions to kill this request:

1) Using a new context:

  • Initiate a new context.WithTimeout(ctx, time.Duration( 5 * time.Minute) )

  • Watch the Done channel in go routine and kill the transaction when there is a signal

  • If the transaction completed successfully in a timely manner, simply cancel context and commit the transaction as expected.

2) Using Timer :

  • Create a Timer with a duration of 5 minutes
  • If time is up, kill the transaction
  • Retry the transaction.

Logically speaking, this is the same decision when and how to decide whether to use context with a set deadline or the good old Timer ?

+6
source share
1 answer

The answer is how context.Context and time.Timer deliver the signal (cancel).

context.Context gives you access to the channel using the Context.Done() method , which will be closed when the goroutines used should complete.

time.Timer gives you access to the channel in the Timer.C struct field , along which the value will be sent after a specified period of time (this value will be the current time, but it does not matter here).

Key points are highlighted there. The closure of the channel can be observed by any number of horus and an infinite number of times. Spec: Receive statement:

A receive operation on a closed channel can always begin immediately, giving the element type a value of zero after all previously sent values ​​have been received.

Thus, a Context can be used to suppress the signal to an arbitrary number of goroutines and places. A Timer can only be used to signal one target, one who receives a value from its channel. If several clients are listening or trying to get from their channel, only one of them will be lucky to receive it.

Also, if you use / work with code that already supports / expects context.Context , then this is not a question that should be used. Go 1.8 also added additional context support . There were significant additions to the database/sql package with context support; including DB.BeginTx() :

The provided context is used until the transaction is completed or rolled back. If the context is canceled, the sql package will roll back the transaction. Tx.Commit will return an error if the context provided by BeginTx is canceled.

This is the main use of context.Context : transferring the deadline and suppressing the signal along the API boundaries, and this is done in a safe way at the same time (since Context values ​​are immutable and channels are also safe for simultaneous use, data schedules cannot occur, by design, moreover: If I use channels correctly, should I use mutexes? ).

Related Blog Entries:

Go Go Blog: Go Concurrency Templates: Context

Context value traps and how to eliminate or reduce them in Go

Dave Cheney: context for cancellation

+2
source

Source: https://habr.com/ru/post/1015131/


All Articles