Caching is one of the operations that we always do when building software. We put an object that will be faster to be retrieved to improve the performance of our software. But likewise, because it is a Software Architecture. Choosing one side will always have risks. If the system cache the wrong data, of course, the output will be all wrong. Because of it, today we will learn how to avoid this problem by implementing WebJob to compare the cache vs the original value.
Create Azure Redis Cache
To create the Azure Redis Cache, you can follow up on this article or you can follow this step:
Go to your portal.azure.com > search Azure Redis Cache > hit create button > Fill in Subscription, Resource group, DNS name, Location, and Cache type. For example, these are the settings that I applied:

Once the resource is ready, go to your Redis Cache > Access Keys > copy the Primary/Secondary connection string for the next step.
PowerAutomate Flow (As WebApi)
For the demonstration purpose, I create a very simple API using PowerAutomate:

Create Console App
Today we will create Console App. The first one is just to set the cache. You just need to create an exe with this value (the *.csproj with .NET Core 3.1 and all the packages necessary):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StackExchange.Redis" Version="2.2.88" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
</ItemGroup>
</Project>
Below is the code for Program.cs:
using StackExchange.Redis;
using System.Threading.Tasks;
namespace RedisDemo
{
internal class Program
{
static async Task Main()
{
string cacheConnection = "redis-connection-string";
using (var connection = ConnectionMultiplexer.Connect(cacheConnection))
{
var db = connection.GetDatabase();
db.StringSet("demo-cache", "Temmy Wahyu Raharjo");
}
}
}
}
You can paste the Redis Connection string on line #10.
Create WebJob
In the next one, we will make a WebJob that will be triggered by the timer that we will set. Below is the *.csproj:
<Project Sdk="Microsoft.NET.Sdk;Microsoft.NET.Sdk.Publish">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.20.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
<PackageReference Include="RestSharp" Version="107.3.0" />
<PackageReference Include="StackExchange.Redis" Version="2.2.88" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="appSettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Settings.job">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
And here is the Program.cs of the WebJob:
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using RestSharp;
using StackExchange.Redis;
using System;
namespace DemoWebJob
{
internal class Program
{
static void Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureLogging(b =>
{
b.AddConsole();
b.AddApplicationInsights();
})
.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddTimers();
});
var host = builder.Build();
host.Run();
}
}
public class CacheManagerFunction
{
public IConfiguration Configuration { get; }
public CacheManagerFunction(IConfiguration configuration)
{
Configuration = configuration;
}
[FunctionName("CacheManagerFunction")]
public void Run([TimerTrigger("%scheduledTimer%")] TimerInfo _, ILogger logger)
{
logger.LogInformation("Begin executing CacheManagerFunction..");
var redisConnectionString = Configuration.GetConnectionString("redisCacheConnection");
using (var connection = ConnectionMultiplexer.Connect(redisConnectionString))
{
var db = connection.GetDatabase();
var cache = db.StringGet("demo-cache");
if (string.IsNullOrEmpty(cache)) return;
var client = new RestClient();
var request = new RestRequest("https://prod-06.southeastasia.logic.azure.com:443/workflows/255f73e3f2154ec9bf9d79d2bc8acfd3/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Md8xbCGz5qfdJh8UhZquufQWTfbQ288lU6Ske3tYvCU")
{
Method = Method.Get
};
var result = client.ExecuteAsync<Response>(request)
.GetAwaiter().GetResult();
var latestValue = result.Data ?? new Response();
if (cache == latestValue.Data)
{
logger.LogInformation("Cache still the same..");
return;
}
logger.LogInformation($"Cache is different. Cache: {cache}. Latest value: {latestValue.Data}.");
db.StringSet("demo-cache", latestValue.Data);
}
}
}
public class Response
{
public string Data { get; set; }
}
}
The Program class is the class that initiated the WebJob SDK. While the implementation is on CacheManagerFunction class. In CacheManagerFunction.Run method will be triggered automatically by the SDK. The first thing we need to do is just to connect with the Redis Database to get the value of the current cache. The next step is to get the value from the original source (PowerAutomate API). The last of-course to compare the value. If the value is not the same, then we need to change the Redis cache and we are done.
The next step is to deploy the WebJob. Right-click on the project, Publish > Create new profile > Select Azure WebJobs as the Specific Target.

In the next dialog, you need to select/create App Service. Here is the setting of my Profile:

Once the profile is ready (the resource needed is also created), you can publish it and wait until it is done.
If you have not yet created Storage Account (because our WebJob needs this Resource Group), you need to create one: Storage Account > create button > fill in Subscription, Resource Group, Storage account name, Region, Performance, and Redundancy. Once created, you can go to Access Key + save it for the next step.
Once done, you can go to App Service > Configuration blade and setup below red boxes (AzureWebJobStorage and scheduledTimer):

* The other configurations is automatic + if you setup the Application Insights
Don’t forget to add below Connection String (redisCacheConnection):

Once you have done these changes, don’t forget to hit the Save button on the top.
If you want to debug it locally, here are my appSettings.json:
{
"scheduledTimer": "0 */5 * * * *",
"connectionStrings": {
"azureWebJobsStorage": "Connection-String-Storage-Account",
"redisCacheConnection": "Connection-String-Redis-Cache"
}
}
Summary
We can summarize the step for the implementation like below diagram:

You can run the first Exe to set/changed the cache. For the setting of the timer, you can changed base on your requirement. Then if you check the WebJobs log you will see the result (sample from my side):

Happy learning!