private async Task GetRetryGlobalConnectionStatusChangeCallback()

in DeviceBridge/Services/SubscriptionScheduler.cs [355:405]


        private async Task GetRetryGlobalConnectionStatusChangeCallback(string deviceId, ConnectionStatus status, ConnectionStatusChangeReason reason)
        {
            // Permanent failure state, taken from https://github.com/Azure-Samples/azure-iot-samples-csharp/tree/master/iot-hub/Samples/device/DeviceReconnectionSample
            bool isFailed = status == ConnectionStatus.Disconnected;

            // Don't retry if it's not a permanent failure.
            if (!isFailed)
            {
                _logger.Info("Ignoring global connection status change for device {deviceId} as status is not failed. Status: {status}. Reason: {reason}", deviceId, status, reason);
                return;
            }

            // Only retry if the device requires a permanent connection.
            if (!_hasDataSubscriptions.TryGetValue(deviceId, out _))
            {
                _logger.Info("Ignoring global connection status change for device {deviceId} as it does not have data subscriptions. Status: {status}. Reason: {reason}", deviceId, status, reason);
                return;
            }

            // Synchronize this block so we don't reschedule a connection retry while a connection attempt is ongoing.
            var mutex = _dbAndConnectionStateSyncSemaphores.GetOrAdd(deviceId, new SemaphoreSlim(1, 1));
            await mutex.WaitAsync();

            try
            {
                var deviceStatus = _connectionManager.GetDeviceStatus(deviceId);

                // The connection status might have changed while we were waiting for the mutex.
                if (deviceStatus?.status != ConnectionStatus.Disconnected)
                {
                    _logger.Info("Skipping retry attempt for device {deviceId} as status is no longer failed.", deviceId);
                    return;
                }

                // If a connection is already scheduled, don't schedule again.
                if (_scheduledConnectionsNotBefore.TryGetValue(deviceId, out _))
                {
                    _logger.Info("Skipping retry attempt for device {deviceId} as it already has a scheduled connection.", deviceId);
                    return;
                }

                // A permanent failure means that the SDK has retried for a while, so reschedule a connection attempt as soon as possible.
                _logger.Info("Scheduling connection retry for device {deviceId}.", deviceId);
                var notBefore = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                _scheduledConnectionsNotBefore.AddOrUpdate(deviceId, notBefore, (key, oldValue) => notBefore);
            }
            finally
            {
                mutex.Release();
            }
        }