Skip to content

[FEATURE] ⚙️ Add DefaultEntryOptionsProvider #484

@jodydonetti

Description

@jodydonetti

Problem

Not really a "problem", but more like a potential new feature: as emerged in #367 there may be the need to not have only one single DefaultEntryOptions, but allow users to centrally specify a custom logic that can provide different default entry options based on the cache key that it is being worked on.

Solution

Important

NOTE: nothing is confirmed yet. As of now I'm playing with the idea, but I still need to implement it and see what happens in all edge cases, etc.

The idea is to add a new option in the FusionCacheOptions class so that it's possible to specify such custom provider logic.

The initial name here #367 was "builder", but that may indicate a way to build entry options everytime, which is not necessarily true: therefore a better name feels like "provider", because it is a way to provide default entry options based on some custom logic.

The current shape is:

public class FusionCacheOptions {
  // ...
  public Func<EntryOptionsProviderContext, FusionCacheEntryOptions?> DefaultEntryOptionsProvider { get; set; }
}

The context object contains the needed informations to implement the custom logic, and the shape is:

public class EntryOptionsProviderContext
{
	public string Key { get; }
	public FusionCacheEntryOptions DuplicateDefaultEntryOptions();
}

Two things to consider:

  • of course if the custom logic is not specified, everything remains the same as before
  • the custom logic can return null, as a way to express "in this case I'm good with the normal DefaultEntryOptions"

This means that the custom logic can:

  • create a new FusionCacheEntryOptions from scratch, and return it
  • duplicate the DefaultEntryOptions, apply some logic, and return it
  • return null

This would allow customizations such as these:

// 1. BASIC:
// - ALWAYS CREATE A NEW ONE
DefaultEntryOptionsProvider = ctx => {
  return new FusionCacheEntryOptions().SetFailSafe(...);
};

// 2. MORE COMPLEX:
// - IF KEY STARTS WITH "foo/" -> CREATE A NEW ONE
// - OTHERWISE JUST RETURN THE DEFAULT ONE
DefaultEntryOptionsProvider = ctx => {
  if (ctx.Key.StartsWith("foo/")) {
    // CREATE A NEW ONE
    return new FusionCacheEntryOptions().SetFailSafe(...);
  }
  
  // RETURN NULL (USES THE DEFAULT ONE)
  return null;
};

// 3. MOST COMPLEX:
// - IF KEY STARTS WITH "foo/" -> CREATE A NEW ONE
// - IF KEY STARTS WITH "bar/" -> DUPLICATE THE DEFAULT ONE AND CHANGE SOMETHING
// - OTHERWISE JUST RETURN NULL (USES THE DEFAULT ONE)
DefaultEntryOptionsProvider = ctx => {
  if (ctx.Key.StartsWith("foo/")) {
    return new FusionCacheEntryOptions().SetFailSafe(...);
  }
  
  if (ctx.Key.StartsWith("bar/")) {
    return ctx.DuplicateDefaultEntryOptions().SetDuration(...);
  }
  
  return null;
};

Of course the user can also reference globally defined entry options to not allocate them every time, and save resources.
For example the example 3 can be:

// SOMEWHERE ELSE
public static class MyStuff {
  public static FusionCacheEntryOptions FooEntryOptions {get; set; }
  public static FusionCacheEntryOptions BarEntryOptions {get; set; }
}

// ...

// 3. MOST COMPLEX:
// - IF KEY STARTS WITH "foo/" -> CREATE A NEW ONE
// - IF KEY STARTS WITH "bar/" -> DUPLICATE THE DEFAULT ONE AND CHANGE SOMETHING
// - OTHERWISE JUST RETURN NULL (USES THE DEFAULT ONE)
DefaultEntryOptionsProvider = ctx => {
  if (ctx.Key.StartsWith("foo/")) {
    return MyStuff.FooEntryOptions ??= new FusionCacheEntryOptions().SetFailSafe(...);
  }
  
  if (ctx.Key.StartsWith("bar/")) {
    return MyStuff.BarEntryOptions ??= ctx.DuplicateDefaultEntryOptions().SetDuration(...);
  }
  
  return null;
};

This should basically cover any possible need (hopefully).

Thoughts?

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions