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.