Removing the DIY cache
For the Proof of Concept(PoC) I had written a simple cache using a ConcurrentDictionary to store Azure IoT Hub connections to reduce the number of calls to the Device Provisioning Service(DPS).

For a PoC the DIY cache was ok but I wanted to replace it with something more robust like the .Net ObjectCache which is in the System.Runtime.Caching namespace.
I started by replacing the ConcurrentDictionary declaration
static readonly ConcurrentDictionary<string, DeviceClient> DeviceClients = new ConcurrentDictionary<string, DeviceClient>();
With an ObjectCache declaration.
static readonly ObjectCache DeviceClients = MemoryCache.Default;
Then, where there were compiler errors I updated the method call.
// See if the device has already been provisioned or is being provisioned on another thread.
if (DeviceClients.Add(registrationId, deviceContext, cacheItemPolicy))
{
log.LogInformation("RegID:{registrationId} Device provisioning start", registrationId);
...
One difference I found was that ObjectCache throws an exception if the value is null. I was using a null value to indicate that the Device Provisioning Service(DPS) process had been initiated on another thread and was underway.
I have been planning to add support for downlink messages so I added a new class to store the uplink (Azure IoT Hub DeviceClient) and downlink ( downlink_url in the uplink message) details.
public class DeviceContext
{
public DeviceClient Uplink { get; set; }
public Uri Downlink { get; set; }
}
For the first version the only functionality I’m using is sliding expiration which is set to one day
CacheItemPolicy cacheItemPolicy = new CacheItemPolicy()
{
SlidingExpiration = new TimeSpan(1, 0, 0, 0),
//RemovedCallback
};
DeviceContext deviceContext = new DeviceContext()
{
Uplink = null,
Downlink = new Uri(payload.DownlinkUrl)
};
I didn’t have to make many changes and I’ll double check my implementation in the next round of stress and soak testing.