/// <summary> /// Registers the specified shellContext as dependent such that it is also released when the current shell context is released. /// </summary> public void AddDependentShell(ShellContext shellContext) { // If the dependent is released, nothing to do. if (shellContext.Released) { return; } // If the dependency is already released. if (_released) { // The dependent is released immediately. shellContext.Release(); return; } lock (_synLock) { if (_dependents == null) { _dependents = new List <WeakReference <ShellContext> >(); } // Remove any previous instance that represent the same tenant in case it has been released (restarted). _dependents.RemoveAll(x => !x.TryGetTarget(out var shell) || shell.Settings.Name == shellContext.Settings.Name); _dependents.Add(new WeakReference <ShellContext>(shellContext)); } }
/// <summary> /// Tries to acquire a lock for shell activation, a local lock if it is initializing, otherwise a distributed lock. /// </summary> public static Task <(ILocker locker, bool locked)> TryAcquireShellActivateLockAsync(this ShellContext shellContext) { // If the shell is initializing, force the usage of a local lock. var lockService = shellContext.Settings.State == TenantState.Initializing ? (ILock)shellContext.ServiceProvider.GetRequiredService <ILocalLock>() : shellContext.ServiceProvider.GetRequiredService <IDistributedLock>(); TimeSpan timeout, expiration; if (lockService is ILocalLock) { // If it is a local lock, don't use any timeout and expiration. timeout = expiration = TimeSpan.MaxValue; } else { // If it is a distributed lock, use the configured timeout and expiration. var options = shellContext.ServiceProvider.GetRequiredService <IOptions <ShellContextOptions> >(); timeout = TimeSpan.FromMilliseconds(options.Value.ShellActivateLockTimeout); expiration = TimeSpan.FromMilliseconds(options.Value.ShellActivateLockExpiration); } return(lockService.TryAcquireLockAsync("SHELL_ACTIVATE_LOCK", timeout, expiration)); }