I am attempting to create a BaseService that uses Redis cache to build out the following pattern:
- Get from cache
- If in cache, return result
- If result is null, call Func to get result from source (database)
- Place in cache
- Return result from Func
I have everything working, but for some reason the service method that is calling to get the result is needing an "await await" before it will compile. I can't seem to figure out why my ResultFromCache method which is meant to imitate what Ok() does in WebAPI is doubly wrapped. Can you please help me find where I am not returning the correct result so my users of this pattern won't have to use two awaits to get their results :)
Here's a slimmed down version of my code that requires the await await in the GetMessage method.
using StackExchange.Redis;
using System.Text.Json;
namespace TestCache
{
public class Service: BaseService
{
//Injected DbContextx
private Context context { get; }
//service method
public async Task<Message> GetMessage(int accountId)
{
return await await ResultFromCache(accountId, FetchMessage, "Message");
}
//get from database method
private async Task<Message> FetchMessage(int parentId)
{
//Example of using EF to retrieve one record from Message table
return await context.Message;
}
}
public class BaseService
{
private const int Hour = 3600;
private ConnectionMultiplexer connection;
private IDatabaseAsync database;
public async Task<T1> ResultFromCache<T1, T2>(T2 param1, Func<T2, T1> fromSource, string cacheKey, int cacheDuration = Hour)
{
//get from cache
var result = await CacheGet<T1>(cacheKey);
if (result != null)
return result;
//get from db
result = fromSource(param1);
//TODO: add to cache
return result;
}
public async Task<T> CacheGet<T>(string key)
{
var value = await database.StringGetAsync(key);
if (value.IsNull)
{
return default;
}
return JsonSerializer.Deserialize<T>(value);
}
}
}