import (
"time"
+ "sync/atomic"
)
type Limit struct {
ms_to_timeout int
bucket chan struct{}
pre_bucket_token_num int
+ wait_num int32
}
// create a Limit Object
time.Sleep(time.Duration(object.ms_in_period)*time.Millisecond)
object.pre_bucket_token_num = len(object.bucket)
}
+ close(object.bucket)
}(&object)
//make sure the bucket is full
// the func will return true if the request(call TO()) is up to limit and return false if not
func (l *Limit) TO() bool {
+ var AfterMS = func(ReadTimeout int) (c <-chan time.Time) {
+ if ReadTimeout > 0 {
+ c = time.NewTimer(time.Millisecond*time.Duration(ReadTimeout)).C
+ }
+ return
+ }
+
+ atomic.AddInt32(&l.wait_num, 1)
+ defer atomic.AddInt32(&l.wait_num, -1)
+
select {
- case <-l.bucket :;
- case <-time.After(time.Duration(l.ms_to_timeout)*time.Millisecond):return true;
+ case <-l.bucket:;
+ case <-AfterMS(l.ms_to_timeout):return true;
}
+
+
return false
}
+func (l *Limit) Close() {
+ l.maxNum_in_period = 0
+}
+
// return the token number of bucket at now
func (l *Limit) TK() int {
return len(l.bucket)
// return the token number of bucket at previous
func (l *Limit) PTK() int {
return l.pre_bucket_token_num
+}
+
+func (l *Limit) WNum() int32 {
+ return atomic.LoadInt32(&l.wait_num)
}
\ No newline at end of file
return errors.Is(e, context.DeadlineExceeded)
}
+func IsDnsErr(e error) bool {
+ return e != nil && strings.Contains(e.Error(), "lookup")
+}
+
func IsCancel(e error) bool {
return errors.Is(e, context.Canceled)
}
\ No newline at end of file