Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added Reset to TokenBucket #90

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Madraceee
Copy link

Motivation

Added new Reset feature to reset the state of the bucket
Fixes #19

Description

Reset allows the state of the bucket to be set to zero value.

Implementation done for

  • TokenBucket
  • LeakyBucket
  • Fixed Window
  • Sliding Window
  • Concurrent Buffer

@Madraceee
Copy link
Author

@mennanov Let me know whether the implementation and the test suite is fine. Else I will make the necessary changes

t.logger.Log(err)
}
}()
state, err := t.backend.State(ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you don't need you retrieve the state first and immediately override its fields.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohh yeah, my bad i will remove the code. Is the other stuff fine?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Race condition occurs while using a new TokenBucketState. Without retrieving the state and using it, error occurs.

For Reference Memcache CompareAndSwap. It expects the item's key to be the same while other values may differ.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can skip that check if the state is zero.

diff --git a/tokenbucket.go b/tokenbucket.go
index 16fc8ec..0b499b1 100644
--- a/tokenbucket.go
+++ b/tokenbucket.go
@@ -562,7 +562,7 @@ func (t *TokenBucketMemcached) SetState(ctx context.Context, state TokenBucketSt
                        Value: b.Bytes(),
                        CasID: t.casId,
                }
-               if t.raceCheck && t.casId > 0 {
+               if t.raceCheck && t.casId > 0 && !state.isZero() {
                        err = t.cli.CompareAndSwap(item)
                } else {
                        err = t.cli.Set(item)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively we may consider adding a separate Reset() method to the TokenBucketStateBackend interface.
That way we won't need a special logic in the SetState() to handle a reset.
However we will need to implement it for every backend.

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this? #91

tokenbucket_test.go Outdated Show resolved Hide resolved
tokenbucket_test.go Outdated Show resolved Hide resolved
@@ -122,6 +122,33 @@ func (t *TokenBucket) Limit(ctx context.Context) (time.Duration, error) {
return t.Take(ctx, 1)
}

// Reset the bucket to zero state
func (t *TokenBucket) Reset(ctx context.Context) (time.Duration, error) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the returned time.Duration value used for?
Is it needed? If so, please add a comment explaining what it means.

t.logger.Log(err)
}
}()
state, err := t.backend.State(ctx)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively we may consider adding a separate Reset() method to the TokenBucketStateBackend interface.
That way we won't need a special logic in the SetState() to handle a reset.
However we will need to implement it for every backend.

What do you think?

@Madraceee
Copy link
Author

@mennanov While trying to set a new state without invoking State(), I am getting race condition error. I still don't understand why this is happening. Just like you mentioned, making changes to SetState() makes the code ugly. I will work on a new function and update here.

@leeym leeym mentioned this pull request Oct 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reset or Clear a Limit
3 participants