github.com/searKing/golang/go@v1.2.74/time/rate/example_test.go (about)

     1  package rate_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"runtime"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/searKing/golang/go/time/rate"
    12  )
    13  
    14  func ExampleNewFullBurstLimiter() {
    15  	const (
    16  		burst = 3
    17  	)
    18  	limiter := rate.NewFullBurstLimiter(burst)
    19  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    20  	defer cancel()
    21  
    22  	// expect dropped, as limiter is initialized with full tokens(3)
    23  	limiter.PutToken()
    24  
    25  	for i := 0; ; i++ {
    26  		//fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339))
    27  		fmt.Printf("Wait %03d, tokens left: %d\n", i, limiter.Tokens())
    28  		err := limiter.Wait(ctx)
    29  		if err != nil {
    30  			fmt.Printf("err: %s\n", err.Error())
    31  			return
    32  		}
    33  		fmt.Printf("Got %03d, tokens left: %d\n", i, limiter.Tokens())
    34  
    35  		// actor mocked by gc
    36  		runtime.GC()
    37  
    38  		if i == 0 {
    39  			// refill one token
    40  			limiter.PutToken()
    41  		}
    42  	}
    43  	// Output:
    44  	// Wait 000, tokens left: 3
    45  	// Got 000, tokens left: 2
    46  	// Wait 001, tokens left: 3
    47  	// Got 001, tokens left: 2
    48  	// Wait 002, tokens left: 2
    49  	// Got 002, tokens left: 1
    50  	// Wait 003, tokens left: 1
    51  	// Got 003, tokens left: 0
    52  	// Wait 004, tokens left: 0
    53  	// err: context deadline exceeded
    54  }
    55  
    56  func ExampleNewEmptyBurstLimiter() {
    57  	const (
    58  		burst       = 3
    59  		concurrency = 2
    60  	)
    61  	limiter := rate.NewEmptyBurstLimiter(burst)
    62  	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
    63  	defer cancel()
    64  
    65  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
    66  
    67  	// expect not allowed, as limiter is initialized with empty tokens(0)
    68  	if limiter.Allow() {
    69  		fmt.Printf("allow passed\n")
    70  	} else {
    71  		fmt.Printf("allow refused\n")
    72  	}
    73  	// fill one token
    74  	limiter.PutToken()
    75  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
    76  
    77  	// expect allowed, as limiter is filled with one token(1)
    78  	if limiter.Allow() {
    79  		fmt.Printf("allow passed\n")
    80  	} else {
    81  		fmt.Printf("allow refused\n")
    82  	}
    83  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
    84  
    85  	var mu sync.Mutex
    86  	var wg sync.WaitGroup
    87  	for i := 0; i < concurrency; i++ {
    88  		wg.Add(1)
    89  		go func() {
    90  			defer wg.Done()
    91  			//fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339))
    92  			mu.Lock()
    93  			fmt.Printf("Wait 1 Token, tokens left: %d\n", limiter.Tokens())
    94  			mu.Unlock()
    95  			err := limiter.Wait(ctx)
    96  			if err != nil {
    97  				mu.Lock()
    98  				fmt.Printf("err: %s\n", err.Error())
    99  				mu.Unlock()
   100  				return
   101  			}
   102  
   103  			mu.Lock()
   104  			fmt.Printf("Got 1 Token, tokens left: %d\n", limiter.Tokens())
   105  			mu.Unlock()
   106  		}()
   107  	}
   108  
   109  	time.Sleep(10 * time.Millisecond)
   110  	for i := 0; i < concurrency; i++ {
   111  		time.Sleep(10 * time.Millisecond)
   112  		mu.Lock()
   113  		fmt.Printf("PutToken #%d: before tokens left: %d\n", i, limiter.Tokens())
   114  		// fill one token
   115  		limiter.PutToken()
   116  		fmt.Printf("PutToken #%d: after tokens left: %d\n", i, limiter.Tokens())
   117  		mu.Unlock()
   118  	}
   119  	wg.Wait()
   120  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   121  
   122  	// expect allowed, as limiter is filled with one token(1)
   123  	if limiter.Allow() {
   124  		fmt.Printf("allow passed\n")
   125  	} else {
   126  		fmt.Printf("allow refused\n")
   127  	}
   128  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   129  
   130  	// expect not allowed, as limiter is initialized with empty tokens(0)
   131  	if limiter.Allow() {
   132  		fmt.Printf("allow passed\n")
   133  	} else {
   134  		fmt.Printf("allow refused\n")
   135  	}
   136  	// Output:
   137  	// tokens left: 0
   138  	// allow refused
   139  	// tokens left: 1
   140  	// allow passed
   141  	// tokens left: 0
   142  	// Wait 1 Token, tokens left: 0
   143  	// Wait 1 Token, tokens left: 0
   144  	// PutToken #0: before tokens left: 0
   145  	// PutToken #0: after tokens left: 0
   146  	// Got 1 Token, tokens left: 0
   147  	// PutToken #1: before tokens left: 0
   148  	// PutToken #1: after tokens left: 0
   149  	// Got 1 Token, tokens left: 0
   150  	// tokens left: 0
   151  	// allow refused
   152  	// tokens left: 0
   153  	// allow refused
   154  }
   155  
   156  func ExampleBurstLimiter_Reserve() {
   157  	const (
   158  		burst = 1
   159  		n     = 10
   160  	)
   161  	limiter := rate.NewFullBurstLimiter(burst)
   162  	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
   163  	defer cancel()
   164  
   165  	// expect dropped, as limiter is initialized with full tokens(3)
   166  	limiter.PutToken()
   167  
   168  	type Reservation struct {
   169  		index int
   170  		r     *rate.Reservation
   171  	}
   172  
   173  	var mu sync.Mutex
   174  	var wg sync.WaitGroup
   175  	var rs []*Reservation
   176  
   177  	for i := 0; i < n; i++ {
   178  		//fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339))
   179  		fmt.Printf("Reserve %03d\n", i)
   180  		r := &Reservation{
   181  			index: i,
   182  			r:     limiter.Reserve(ctx),
   183  		}
   184  		if i%2 == rand.Intn(2)%2 {
   185  			rs = append(rs, r)
   186  			continue
   187  		}
   188  		wg.Add(1)
   189  		go func() {
   190  			defer wg.Done()
   191  			//fmt.Printf("%03d %s\n", r.index, time.Now().Format(time.RFC3339))
   192  			//fmt.Printf("Wait %03d\n", r.index)
   193  			err := r.r.Wait(ctx)
   194  			if err != nil {
   195  				mu.Lock()
   196  				fmt.Printf("err: %s\n", err.Error())
   197  				mu.Unlock()
   198  			}
   199  
   200  			mu.Lock()
   201  			fmt.Printf("%03d Got 1 Token, tokens left: %d\n", r.index, limiter.Tokens())
   202  			mu.Unlock()
   203  			r.r.PutToken()
   204  		}()
   205  	}
   206  
   207  	for i := 0; i < len(rs); i++ {
   208  		r := rs[i]
   209  		wg.Add(1)
   210  		go func() {
   211  			defer wg.Done()
   212  			//fmt.Printf("%03d %s\n", r.index, time.Now().Format(time.RFC3339))
   213  			//fmt.Printf("Wait %03d\n", r.index)
   214  			err := r.r.Wait(ctx)
   215  			if err != nil {
   216  				mu.Lock()
   217  				fmt.Printf("err: %s\n", err.Error())
   218  				mu.Unlock()
   219  			}
   220  
   221  			mu.Lock()
   222  			fmt.Printf("%03d Got 1 Token, tokens left: %d\n", r.index, limiter.Tokens())
   223  			mu.Unlock()
   224  			r.r.PutToken()
   225  		}()
   226  	}
   227  	wg.Wait()
   228  	// Output:
   229  	// Reserve 000
   230  	// Reserve 001
   231  	// Reserve 002
   232  	// Reserve 003
   233  	// Reserve 004
   234  	// Reserve 005
   235  	// Reserve 006
   236  	// Reserve 007
   237  	// Reserve 008
   238  	// Reserve 009
   239  	// 000 Got 1 Token, tokens left: 0
   240  	// 001 Got 1 Token, tokens left: 0
   241  	// 002 Got 1 Token, tokens left: 0
   242  	// 003 Got 1 Token, tokens left: 0
   243  	// 004 Got 1 Token, tokens left: 0
   244  	// 005 Got 1 Token, tokens left: 0
   245  	// 006 Got 1 Token, tokens left: 0
   246  	// 007 Got 1 Token, tokens left: 0
   247  	// 008 Got 1 Token, tokens left: 0
   248  	// 009 Got 1 Token, tokens left: 0
   249  
   250  }