Home > Blockchain >  "golang.org/x/time/rate" and Context
"golang.org/x/time/rate" and Context

Time:07-07

What's the purpose of passing the context to Wait() function in the example below?

Let's say there is a limiter that allow 3 requests per second.

Does it mean that limiter will not be a shared resource in the sense that, for each "Process" function call, it will have it's own limiter instance and scope, is that right? If it's not the case? How can I achieve it?

Struct

type MyClass struct {
    limiter *rate.Limiter
}

func NewMyClass() (*MyClass, error) {
    return &MyClass{limiter: rate.NewLimiter(rate.Limit(3), 1)}, nil
}

func (m *MyClass) Process(ctx context.Context) error {
    err := m.limiter.Wait(ctx)
    if err != nil {
        return err
    }
    //more code
}

Example

m, _ := s3Storage.NewMyClass()
    
    ctx1 := context.TODO()
    m.Process(ctx1)
    m.Process(ctx1)
    m.Process(ctx1)

    ctx2 := context.TODO()
    m.Process(ctx2)

CodePudding user response:

The context defines the lifetime of the call, so if the context is cancelled, then the wait call will be cancelled as well. As an example, try changing the context from context.TODO() to context.WithTimeout() with a very small timeout and observe the effect on the Wait() call. The official docs do a good job of explaining the context and semantics behind context.

CodePudding user response:

First, you need to understand the different purposes of the rate.Limiter and context.Context types. The Limiter allows you to control the rate at which concurrent processes are executed. The Context allows to terminate a process or group of processes if there is no point in them continuing (eg timeout, lost connection, user-cancellation...). These are simplifications so read the doco for more info.

To answer your questions:

What's the purpose of passing the context to Wait() function in the example?

There is no purpose as the TODO context is never cancelled.

Does it mean the limiter will not be a shared resource...?

No, it is shared. You only have one MyClass instance which only has one Limiter.

If not ... how can I achieve it?

There is no point in having a limiter on each Process function call, since one call will never exceed your limit of 3.

I think you want multiple different sets of rate-limited calls to Process, and so probably just need multiple instances of MyClass, each with it's own Limiter.

I'm not sure exactly what you are trying to do, but as an example a typical use of a rate limiter is to restrict the number of processes by user or by connection. Similarly, a context may be associated with all the processes attached to a single connection, so that if the connection dies everything can be neatly cleaned up. So a possible scenario is that you have a Connection type that has a Limiter and a Context.

I hope this makes sense.

  • Related