Proposition: package level PermutatedKey function
Is your feature request related to a problem? Please describe.
I rely mostly on the sturdyc.GetOrFetch method to pass a chosen pre-configured cache where needed,
this, however, means that it means a detour to using PermutatedKey alongside it:
// shortLived() returns some pre-configured instance, other ones are available, hence why we use this method.
key := shortLived().PermutatedKey(someInput)
sturdyc.GetOrFetch(ctx, shortLived(), key, func(ctx context.Context) (SomeData, error) {
// do the thing
})
Describe the solution you'd like
I would love to have a plain function version of PermutatedKey.
As far as I understand, PermutatedKey is only attached as a method to use c.log and c.handleTime internal methods. This makes me think it might be possible to provide a plain sturdyc.PermutatedKey function which would be much more useful for workflows like mine.
Happy to help if need be, and thank you for this incredible library, it's wonderful!
Hi, yes the main reason for having PermutatedKey as a function receiver on the cache is to support this option:
// WithRelativeTimeKeyFormat allows you to control the truncation of time.Time
// values that are being passed in to the cache key functions.
func WithRelativeTimeKeyFormat(truncation time.Duration) Option {
return func(c *Config) {
c.useRelativeTimeKeyFormat = true
c.keyTruncation = truncation
}
}
I think your example could be slightly improved like this:
cache := shortLived()
sturdyc.GetOrFetch(ctx, cache, cache.PermutatedKey(someInput), func(ctx context.Context) (SomeData, error) {
// do the thing
}
However, I agree that it's not as nice as being able to do this:
sturdyc.GetOrFetch(ctx, shortLived(), sturdyc.PermutatedKey(someInput), func(ctx context.Context) (SomeData, error) {
// do the thing
}
Doing this shouldn't be too difficult but I would most likely want to improve the entire keys.go file. It's something I did very early on in the project and I think it could be improved
Thank you for your answer, I didn't catch the WithRelativeTimeKeyFormat option and its relevance.
I do think it could potentially be a good idea to revisit the keys.
On that note, I had a couple of ideas, which you can feel free to use or discard,
- Perhaps
PermutatedKeycould follow existingjsontags if they exist? - Perhaps the type passed to
PermutatedKeycould implement an interface allowing the user to define exactly how the cache key should look ahead of time?
Example:
type Permutator interface { Key() string }
type MyType struct { /* ... */ }
func (m MyType) Key() string {
return fmt.Sprintf("...")
}
This could perhaps even open up the possibility for a GetOrFetch variant (GetOrFetchPermutated? ) which doesn't require a key in the parameters if the type passed in implements that interface.
There are a couple more things to take into consideration as well. The coalescing functionality relies on being able to extract the permutation of each cache key in order to create a request buffer. I believe this could be implemented similarly to how I've done it today (adding a suffix to every key).
The problem with giving control of the keys to the consumer, however, is that they would expect elements to be cached under those exact keys. A simple cache.Get would not find the item using what they perceive to be the correct key, since they wouldn't be aware of the internal suffix.
This could, of course, be addressed by having the Get method also check for the suffixed key. I'm just noting this here as something to keep in mind when working on the implementation