-
Notifications
You must be signed in to change notification settings - Fork 465
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
refactor storage implementation #243
Conversation
Signed-off-by: zufardhiyaulhaq <[email protected]>
@mattklein123 @nezdolik needs your help to review. I move all implementation details related to storage to StorageStrategy. |
Thanks @zufardhiyaulhaq, i will review shortly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zufardhiyaulhaq i've done first pass, will need to do one more. Please add unit/integration tests for this change.
package strategy | ||
|
||
type StorageStrategy interface { | ||
GetValue(key string) (uint64, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add docs to interface methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping on this
// Now fetch the pipeline. | ||
responseDescriptorStatuses := make([]*pb.RateLimitResponse_DescriptorStatus, | ||
len(request.Descriptors)) | ||
for i, cacheKey := range cacheKeys { | ||
|
||
limitAfterIncrease := results[i] | ||
limitBeforeIncrease := limitAfterIncrease - hitsAddend | ||
limitBeforeIncrease := uint32(results[i]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this change intended? eg limitBeforeIncrease
used to be results[i] - hitsAddend
and with this change it will be uint32(results[i])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes this is intended. since we are not increasing in this function, so it's should be the result that we get from redis. We will increase the value in increaseAsync function below.
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zufardhiyaulhaq PR mostly looks good to me (apart from missing tests). It's a large PR to review, but big part of it just moving code around, so functionality should remain the same.
src/redis/cache_impl.go
Outdated
s.RedisPerSecondType, s.RedisPerSecondUrl, s.RedisPerSecondPoolSize, s.RedisPerSecondPipelineWindow, s.RedisPerSecondPipelineLimit) | ||
} | ||
var otherPool Client | ||
otherPool = NewClientImpl(srv.Scope().Scope("redis_pool"), s.RedisTls, s.RedisAuth, s.RedisType, s.RedisUrl, s.RedisPoolSize, | ||
var otherPool storage_strategy.StorageStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use inline initialisation here
"github.com/mediocregopher/radix/v3" | ||
) | ||
|
||
type RedisClientInterface interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add docs to interface methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, comment repeats type name
"github.com/bradfitz/gomemcache/memcache" | ||
) | ||
|
||
type MemcachedClientInterface interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add docs to interface methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this comment looks rudimentary, as it repeats the name of type, either add more explanatory comment or remove it.
// simply by incrementing it but memcached cannot. In memcache new keys need to be explicitly | ||
// added. | ||
package memcached_test | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add tests for refactored code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi sorry for very slow resp, will start creating unit test for the code
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
Signed-off-by: zufardhiyaulhaq <[email protected]>
@nezdolik need your help to review, rebase from master and add the unit test. |
@zufardhiyaulhaq somehow i missed your comment, i will review by start of next week. |
if this.perSecondClient != nil && cacheKey.PerSecond { | ||
err := this.perSecondClient.IncrementValue(cacheKey.Key, uint64(hitsAddend)) | ||
if err != nil { | ||
logger.Error(err) | ||
} | ||
|
||
err = this.perSecondClient.SetExpire(cacheKey.Key, uint64(expirationSeconds)) | ||
if err != nil { | ||
logger.Error(err) | ||
} | ||
} else { | ||
err := this.client.IncrementValue(cacheKey.Key, uint64(hitsAddend)) | ||
if err != nil { | ||
logger.Error(err) | ||
} | ||
|
||
err = this.client.SetExpire(cacheKey.Key, uint64(expirationSeconds)) | ||
if err != nil { | ||
logger.Error(err) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this section looks like duplicated code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah but it's not, it's using different client to execute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps you could extract it to a function that accepts a client as argument?
client: client, | ||
perSecondClient: perSecondClient, | ||
jitterRand: jitterRand, | ||
expirationJitterMaxSeconds: expirationJitterMaxSeconds, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so here we pass jitter settings both in base rate limiter and in fixedRateLimitCacheImpl
, should stick to one class instead
if srv != "" { | ||
client = newMemcachedClientFromSrv(scope, srv, srvRefresh, maxIdleConnection) | ||
} else { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
either remove empty block or put client initialization with hosts here
defer t.Stop() | ||
for { | ||
select { | ||
case <-t.C: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not related to PR itself: i know this is Go convention, but is hard to read (if one is not familiar with Tickers in Go)
"github.com/bradfitz/gomemcache/memcache" | ||
) | ||
|
||
type MemcachedClientInterface interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this comment looks rudimentary, as it repeats the name of type, either add more explanatory comment or remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great refactoring, thank you. Added comments for bunch of nits, but overall makes sense to me. Would the next step be plugging different algorithms into storage strategy?
"github.com/mediocregopher/radix/v3" | ||
) | ||
|
||
type RedisClientInterface interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, comment repeats type name
"github.com/envoyproxy/ratelimit/src/storage/service" | ||
) | ||
|
||
type MemcachedStrategy struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use compile time check if given type implements interface, example here: https://github.com/envoyproxy/ratelimit/blob/main/src/memcached/cache_impl.go#L55
"github.com/mediocregopher/radix/v3" | ||
) | ||
|
||
type RedisStrategy struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use compile time check if given type implements interface, example here: https://github.com/envoyproxy/ratelimit/blob/main/src/memcached/cache_impl.go#L55
package strategy | ||
|
||
type StorageStrategy interface { | ||
GetValue(key string) (uint64, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping on this
package strategy | ||
|
||
// Interface to abstract underlying storage like memcached and redis | ||
// Implement bussiness level where we don't care how underlying storage doing it.\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra slash in the end?
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically closed because it has not had activity in the last 37 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
refactor storage implementation to use design pattern. this is also a step to implement rolling window support in #193
currently there is no unit test, let me know if this is make sense and I can write the unit test.
Signed-off-by: zufardhiyaulhaq [email protected]