Skip to content

[FEATURE] 🔑 Access the cache key from the factory #470

@jodydonetti

Description

@jodydonetti

Problem

When we do a GetOrSet we can access a factory context, like this:

var cacheKey = "foo";
cache.GetOrSet<string>(
  cacheKey,
  (ctx, ct) => {
    // WE CAN WORK WITH ctx HERE
  }
);

All is good, but if we also need to access the cache key inside of the factory itself, the way to do it is by referencing that inside of the lambda, like this:

var cacheKey = "foo";
cache.GetOrSet<string>(
  cacheKey,
  (ctx, ct) => {
    var tmp = cacheKey; // HERE WE CAN REFERENCE cacheKey
  }
);

This works, but it also inadvertently creates a closure to capture the cacheKey variable from outside: this in turn allocates more memory, and prevent us from being able to use a static lambda, which can be an effective optimization technique.

Also, when using FusionCache we can specify a CacheKeyPrefix (typically used along with Named Caches) and in that case the cache key used internally would be processed: for example if we specify a CacheKeyPrefix as "MyPrefix:" and call GetOrSet("foo", ...), the cache key used internally would be processed and become "MyPrefix:foo".

Therefore we should be able to access both, the processed key and the original key.

Finally, this need has been recently reported in a couple of issues (see here and here).

Solution

I'm adding 2 new properties to the factory context (of type FusionCacheFactoryExecutionContext<TValue>):

  • string Key { get; }
  • string OriginalKey { get; }

both, as can be seen, read only.

If this way we'll be able to do this:

var cacheKey = "foo";
cache.GetOrSet<string>(
  cacheKey,
  (ctx, ct) => {
    var tmp1 = ctx.Key; // HERE WE CAN REFERENCE THE (PROCESSED) CACHE KEY
    var tmp2 = ctx.OriginalKey; // HERE WE CAN REFERENCE THE (ORIGINAL) CACHE KEY
  }
);

In this way a closure will not be created, and the lambda itself (the factory) may even be marked as static.

Note

Of course if CacheKeyPrefix is not being used, both properties will have the same value.

Naming

Regarding the names of the 2 new properties ("Key" and "OriginalKey"), someone may be thinking: why not call the 2 properties ProcessedKey and OriginalKey? In particular, why use "Key" and not "ProcessedKey"?

That was the first thing I thought too but then I remembered that the simple term "key", used to refer to the processed one, is already being used inside FusionCache in multiple places, like:

  • logging (see here)
  • traces (see here)
  • events (see here)
  • etc...

Therefore, we can say, the simple term "key" has always meant the processed one, therefore using in only this case the term "ProcessedKey" would be non uniform with the rest.

To be on the safe side I also added some xml comments to make this as evident as possible, like this:

Image

On top of this, when someone will type ctx. and then "key", they'll see this:

Image

showing both and sparking the question, even for people not knowing the 2 already.

This, ideally, should do the trick.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions