Skip to content

2.7 Caching

Marjan Nikolovski edited this page Apr 9, 2021 · 1 revision

Purpose

Cache is a hardware or software component that stores data so that future requests for that data can be served faster. The data stored in a cache might be the result of an earlier computation or a copy of data stored elsewhere. A cache hit occurs when the requested data can be found in a cache, while a cache miss occurs when it cannot. Cache hits are served by reading data from the cache, which is faster than recomputing a result or reading from a slower data store; thus, the more requests that can be served from the cache, the faster the system performs.

Signals offers an implementation for the Scheduled tasks aspect out of the box:

  • Signals.Aspects.Caching.InMemory

Only one implementation can be active at a time.

How to use

When we implement any type of process a cache provider is automatically injected in the process context.

public class MyProcess : BusinessProcess<VoidResult>
{
    /// <summary>
    /// Authenticate process
    /// </summary>
    /// <returns></returns>
    public override VoidResult Auth()
    {
        return Ok();
    }

    /// <summary>
    /// Validate process
    /// </summary>
    /// <returns></returns>
    public override VoidResult Validate()
    {
        return Ok();
    }

    /// <summary>
    /// Handle process
    /// </summary>
    /// <returns></returns>
    public override VoidResult Handle()
    {
        // setting string valued cache entry
        Cache.Set<string>("my_key", "my_value");

        // setting User valued cache entry
        Cache.Set<User>("my_key", new User { Name = "my_name" });

        return Ok();
    }
}

Other more manual way of using the cache is through the ICache instance.

public void CacheData<T>(string key, T value)
{
    var cacheProvider = SystemBootstrapper.GetInstance<ICache>();
    cacheProvider.Set<T>(key, value);
}

Configuration

We configure the caching aspect by using an instance of Signals.Aspects.Caching.Configurations.ICacheConfiguration which we pass in the ApplicationBootstrapConfiguration instance (web or background) at startup.

Properties explanation

  • ExpirationTime: TimeSpan expiration value that the entries are being invalidated after
  • ExpirationPolicy: Enum Absolute or Sliding value
  • DataProvider: Should not be initialized except when we extend or implement custom cache provider

Examples

Using Signals.Aspects.Caching.InMemory

services
    .AddSignals(config =>
    {
        config.CacheConfiguration = new InMemoryCacheConfiguration
        {
            ExpirationPolicy = CacheExpirationPolicy.Sliding,
            ExpirationTime = TimeSpan.FromMinutes(5)
        }
    });

Extending caching

  1. Install package Signals.Aspects.Caching
  2. Create class with implementation of Signals.Aspects.Caching.Configurations.ICacheConfiguration
/// <summary>
/// Cache configuration contract
/// </summary>
public class MyCacheConfiguration : ICacheConfiguration
{
    /// <summary>
    /// Custom property
    /// </summary>
    public string MyProperty { get; set; }

    /// <summary>
    /// Provider that sets and gets values
    /// </summary>
    public IDataProvider DataProvider { get; set; }

    /// <summary>
    /// Expiration time
    /// </summary>
    public TimeSpan ExpirationTime { get; set; }

    /// <summary>
    /// Policy for expiration:
    /// sliding, absolute
    /// </summary>
    public CacheExpirationPolicy ExpirationPolicy { get; set; }
}
  1. Create class with implementation of Signals.Aspects.Caching.IDataProvider
/// <summary>
/// Data provider contract
/// </summary>
public class MyDataProvider : IDataProvider
{
    /// <summary>
    /// Gets cached entry
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    CacheEntry Get(string key);

    /// <summary>
    /// Removes cached entry
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    CacheEntry Remove(string key);

    /// <summary>
    /// Gets all cached entries
    /// </summary>
    /// <returns></returns>
    IEnumerable<CacheEntry> GetAll();

    /// <summary>
    /// Sets cache entry
    /// </summary>
    /// <param name="entry"></param>
    /// <returns></returns>
    CacheEntry Set(CacheEntry entry);

    /// <summary>
    /// Sets cache entry
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="cache"></param>
    /// <returns></returns>
    CacheEntry Set(string key, object value, Cache cache);
}
  1. Use our implementation of ICacheConfiguration when configuring our application
public static IServiceProvider AddSignals(this IServiceCollection services)
{
    services
        .AddSignals(config =>
        {
            config.CacheConfiguration = new InMemoryCacheConfiguration
            {
                MyProperty = "my_value",
                ExpirationPolicy = CacheExpirationPolicy.Sliding,
                ExpirationTime = TimeSpan.FromMinutes(5),
                DataProvider = new MyDataProvider(),
            }
        });
}
Clone this wiki locally