-
Notifications
You must be signed in to change notification settings - Fork 339
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
fix(cache) Don't cache failed calls to resourceStore #1894
fix(cache) Don't cache failed calls to resourceStore #1894
Conversation
We were caching errors to the resourceStore in the XDS cache This was causing problems when the resourceStore was returning an error we wouldn't attempt to get a value until the item was purge from the cache. We now never cache errors, thus ensuring we recover quickly from resourceStore errors Signed-off-by: Charly Molter <charly@koyeb.com>
064aa6c
to
18baef9
Compare
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.
that's a good one, thanks for introducing the 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.
What do you think about defer c.onceMap.Delete(mesh)
as a first line?
Could you also do the same change in pkg/xds/cache/cla/cache.go
?
Both sound like good suggestions. Updating this |
ec2794b
to
2358f8b
Compare
@jakubdyszkiewicz there was a lot of redundancy between these 2 implementations I've refactored a bit to simplify and added an "error" result in the metric. |
2358f8b
to
e45e156
Compare
…mplementation Signed-off-by: Charly Molter <charly@koyeb.com>
e45e156
to
7309523
Compare
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.
@lobkovilya could you check the refactor?
pkg/xds/cache/once/cache.go
Outdated
}, nil | ||
} | ||
|
||
func (c *Cache) Get(ctx context.Context, key string, fn func(context.Context, string) (interface{}, error)) (interface{}, 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.
Yeah, there was duplication indeed, but it's quite problematic to introduce a well-understandable and reusable abstraction here. I don't mind going with this once.Cache
abstraction, but we have to do something with the interface because it's really unclear what Get
does.
Maybe we can introduce new types:
type Key string
type Value interface{}
type Refresher func(context.Context, Key) (Value, error)
and rename Get
to GetOrRefresh
so it will look like:
func (c *Cache) GetOrRefresh(ctx context.Context, key Key, refresher Refresher) (Value, error)
and document this method with a comment something like:
// GetOrRefresh method returns cached Value if it was created within the last `expirationTime` time period.
// If the Value is older than `expirationTime` then Refresher will be launched and will update the Value.
// Regardless of the number of goroutines that have run into the expired Value, Refresher will be called only
// once, all goroutines will be blocked until the new Value returned by Refresher.
func (c *Cache) GetOrRefresh(ctx context.Context, k Key, r Refresher) (Value, error) {
WDYT?
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.
Sounds good!
How about GetOrCompute()
as Refresh sounds like it will only work when the item has been in the cache?
For the Key
what's the motivation for adding the subtype?
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.
The main reason for questioning the introduction of subtypes is that the underlying lib go-cache
uses string
as key and interface{}
as value.
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.
In the end went for GetOrRetrieve
and didn't add subtypes for key
and value
. Let me know what you think.
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.
I like GetOrRetrieve
👍
Subtypes help to make the signature more readable. If you define it like:
type FetcherFunc func(context.Context, string) (interface{}, error)
then it's not clear that FetcherFunc
takes key
as a parameter and returns value
.
Also, interface{}
is used twice - as a return value of GetOrRetrieve
and as a return value of FetcherFunc
. I think it makes sense to show that those interface{}
are the same type. For example, if in the future we would like to introduce a new type for Value
.
But I don't mind going with just string
and interface{}
Signed-off-by: Charly Molter <charly@koyeb.com>
@Mergifyio update |
Command
|
|
Signed-off-by: Charly Molter <charly@koyeb.com>
9ba4d02
to
9204da8
Compare
same thing fails on master, I don't want to block this PR from merging |
Signed-off-by: Charly Molter <charly@koyeb.com> (cherry picked from commit e73c990)
Signed-off-by: Charly Molter <charly@koyeb.com>
We were caching errors to the resourceStore in the XDS cache
This was causing problems when the resourceStore was returning an error
we wouldn't attempt to get a value until the item was purged from the cache.
We now never cache errors, thus ensuring we recover quickly from resourceStore errors
Signed-off-by: Charly Molter charly@koyeb.com