using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DistributedLocking;
namespace Umbraco.Cms.Infrastructure.DistributedLocking;
public class DefaultDistributedLockingMechanismFactory : IDistributedLockingMechanismFactory
{
private object _lock = new();
private bool _initialized;
private IDistributedLockingMechanism? _distributedLockingMechanism;
private readonly IOptionsMonitor<GlobalSettings> _globalSettings;
private readonly IEnumerable<IDistributedLockingMechanism> _distributedLockingMechanisms;
public DefaultDistributedLockingMechanismFactory(
IOptionsMonitor<GlobalSettings> globalSettings,
IEnumerable<IDistributedLockingMechanism> distributedLockingMechanisms)
_globalSettings = globalSettings;
_distributedLockingMechanisms = distributedLockingMechanisms;
}
public IDistributedLockingMechanism? DistributedLockingMechanism
get
EnsureInitialized();
return _distributedLockingMechanism;
private void EnsureInitialized()
=> LazyInitializer.EnsureInitialized(ref _distributedLockingMechanism, ref _initialized, ref _lock, Initialize);
private IDistributedLockingMechanism Initialize()
var configured = _globalSettings.CurrentValue.DistributedLockingMechanism;
if (!string.IsNullOrEmpty(configured))
IDistributedLockingMechanism? value = _distributedLockingMechanisms
.FirstOrDefault(x => x.GetType().FullName?.EndsWith(configured) ?? false);
if (value == null)
throw new InvalidOperationException($"Couldn't find DistributedLockingMechanism specified by global config: {configured}");
IDistributedLockingMechanism? defaultMechanism = _distributedLockingMechanisms.FirstOrDefault(x => x.Enabled);
if (defaultMechanism != null)
return defaultMechanism;
throw new InvalidOperationException($"Couldn't find an appropriate default distributed locking mechanism.");