@@ -2,36 +2,43 @@ package budget
22
33import (
44 "context"
5+ "fmt"
56 "time"
67
78 "github.com/jonboulle/clockwork"
89
910 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
11+ "github.com/ydb-platform/ydb-go-sdk/v3/internal/xrand"
1012)
1113
1214type (
1315 // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
1416 Budget interface {
17+ // Acquire called from retryer on second and subsequence attempts
1518 Acquire (ctx context.Context ) error
1619 }
17- budget struct {
20+ fixedBudget struct {
1821 clock clockwork.Clock
1922 ticker clockwork.Ticker
2023 quota chan struct {}
2124 done chan struct {}
2225 }
23- option func (q * budget )
26+ fixedBudgetOption func (q * fixedBudget )
27+ percentBudget struct {
28+ percent int
29+ rand xrand.Rand
30+ }
2431)
2532
26- func withBudgetClock (clock clockwork.Clock ) option {
27- return func (q * budget ) {
33+ func withFixedBudgetClock (clock clockwork.Clock ) fixedBudgetOption {
34+ return func (q * fixedBudget ) {
2835 q .clock = clock
2936 }
3037}
3138
3239// Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
33- func New (attemptsPerSecond int , opts ... option ) * budget {
34- q := & budget {
40+ func Limited (attemptsPerSecond int , opts ... fixedBudgetOption ) * fixedBudget {
41+ q := & fixedBudget {
3542 clock : clockwork .NewRealClock (),
3643 done : make (chan struct {}),
3744 }
@@ -68,15 +75,15 @@ func New(attemptsPerSecond int, opts ...option) *budget {
6875}
6976
7077// Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
71- func (q * budget ) Stop () {
78+ func (q * fixedBudget ) Stop () {
7279 if q .ticker != nil {
7380 q .ticker .Stop ()
7481 }
7582 close (q .done )
7683}
7784
7885// Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
79- func (q * budget ) Acquire (ctx context.Context ) error {
86+ func (q * fixedBudget ) Acquire (ctx context.Context ) error {
8087 if err := ctx .Err (); err != nil {
8188 return xerrors .WithStackTrace (err )
8289 }
@@ -89,3 +96,22 @@ func (q *budget) Acquire(ctx context.Context) error {
8996 return xerrors .WithStackTrace (ctx .Err ())
9097 }
9198}
99+
100+ // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
101+ func Percent (percent int ) * percentBudget {
102+ if percent > 100 || percent < 0 {
103+ panic (fmt .Sprintf ("wrong percent value: %d" , percent ))
104+ }
105+ return & percentBudget {
106+ percent : percent ,
107+ rand : xrand .New (xrand .WithLock ()),
108+ }
109+ }
110+
111+ func (b * percentBudget ) Acquire (ctx context.Context ) error {
112+ if b .rand .Int (100 ) < b .percent {
113+ return nil
114+ }
115+
116+ return ErrNoQuota
117+ }
0 commit comments