#19799: Improving tenants creation stability

Work Item: 19799
This commit is contained in:
Sebastien Ros
2013-08-22 18:23:29 -07:00
parent 39f7cc0a78
commit a50e1b704d
3 changed files with 77 additions and 45 deletions

View File

@@ -43,7 +43,7 @@ namespace Orchard.Workflows.Models {
/// <summary>
/// List of <see cref="WorkflowRecord"/> associated with this workflow definition.
/// </summary>
[CascadeAllDeleteOrphan, Aggregate]
[CascadeAllDeleteOrphan]
public virtual IList<WorkflowRecord> WorkflowRecords { get; set; }
}
}

View File

@@ -11,7 +11,6 @@ using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Utility.Extensions;
namespace Orchard.Environment {
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler {
@@ -23,7 +22,7 @@ namespace Orchard.Environment {
private readonly IExtensionLoaderCoordinator _extensionLoaderCoordinator;
private readonly IExtensionMonitoringCoordinator _extensionMonitoringCoordinator;
private readonly ICacheManager _cacheManager;
private readonly object _syncLock = new object();
private readonly static object _syncLock = new object();
private IEnumerable<ShellContext> _shellContexts;
private IEnumerable<ShellSettings> _tenantsToRestart;
@@ -54,13 +53,8 @@ namespace Orchard.Environment {
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public IList<ShellContext> Current {
get { return BuildCurrent().ToReadOnlyCollection(); }
}
public ShellContext GetShellContext(ShellSettings shellSettings) {
return Current
.Single(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name));
return BuildCurrent().SingleOrDefault(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name));
}
void IOrchardHost.Initialize() {
@@ -112,7 +106,7 @@ namespace Orchard.Environment {
void StartUpdatedShells() {
lock (_syncLock) {
if (_tenantsToRestart.Any()) {
foreach (var settings in _tenantsToRestart.Distinct().ToList()) {
foreach (var settings in _tenantsToRestart.ToList()) {
ActivateShell(settings);
}
@@ -155,7 +149,11 @@ namespace Orchard.Environment {
Logger.Debug("Activating context for tenant {0}", context.Settings.Name);
context.Shell.Activate();
_shellContexts = (_shellContexts ?? Enumerable.Empty<ShellContext>()).Union(new [] {context});
_shellContexts = (_shellContexts ?? Enumerable.Empty<ShellContext>())
.Where(c => c.Settings.Name != context.Settings.Name)
.Concat(new[] { context })
.ToArray();
_runningShellTable.Add(context.Settings);
}
@@ -199,9 +197,13 @@ namespace Orchard.Environment {
Logger.Information("Disposing active shell contexts");
if (_shellContexts != null) {
foreach (var shellContext in _shellContexts) {
shellContext.Shell.Terminate();
shellContext.LifetimeScope.Dispose();
lock (_syncLock) {
if (_shellContexts != null) {
foreach (var shellContext in _shellContexts) {
shellContext.Shell.Terminate();
shellContext.LifetimeScope.Dispose();
}
}
}
_shellContexts = null;
}
@@ -232,7 +234,9 @@ namespace Orchard.Environment {
// if a tenant has been altered, and is not invalid, reload it
if (settings.State != TenantState.Invalid) {
_tenantsToRestart = _tenantsToRestart.Where(x => x.Name != settings.Name).Union(new[] { settings });
_tenantsToRestart = _tenantsToRestart
.Where(x => x.Name != settings.Name)
.Concat(new[] { settings });
}
}
}
@@ -284,12 +288,14 @@ namespace Orchard.Environment {
context = _shellContexts.First(x => x.Settings.Name == tenant);
}
// don't update the settings themselves here
// don't flag the tenant if already listed
if(_tenantsToRestart.Any(x => x.Name == tenant)) {
return;
}
_tenantsToRestart = _tenantsToRestart.Union(new[] { context.Settings });
_tenantsToRestart = _tenantsToRestart
.Concat(new[] { context.Settings })
.ToArray();
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using Orchard.Environment.Configuration;
@@ -17,34 +18,53 @@ namespace Orchard.Environment {
private IEnumerable<ShellSettings> _shells = Enumerable.Empty<ShellSettings>();
private IEnumerable<IGrouping<string, ShellSettings>> _shellsByHost = Enumerable.Empty<ShellSettings>().GroupBy(x => default(string));
private ShellSettings _fallback;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void Add(ShellSettings settings) {
_shells = _shells
.Where(s => s.Name != settings.Name)
.Concat(new[] { settings })
.ToArray();
_lock.EnterWriteLock();
try {
_shells = _shells
.Where(s => s.Name != settings.Name)
.Concat(new[] {settings})
.ToArray();
Organize();
Organize();
}
finally {
_lock.ExitWriteLock();
}
}
public void Remove(ShellSettings settings) {
_shells = _shells
.Where(s => s.Name != settings.Name)
.ToArray();
_lock.EnterWriteLock();
try {
_shells = _shells
.Where(s => s.Name != settings.Name)
.ToArray();
Organize();
Organize();
}
finally {
_lock.ExitWriteLock();
}
}
public void Update(ShellSettings settings) {
_shells = _shells
.Where(s => s.Name != settings.Name)
.ToArray();
_lock.EnterWriteLock();
try {
_shells = _shells
.Where(s => s.Name != settings.Name)
.ToArray();
_shells = _shells
.Concat(new[] { settings })
.ToArray();
_shells = _shells
.Concat(new[] {settings})
.ToArray();
Organize();
Organize();
}
finally {
_lock.ExitWriteLock();
}
}
private void Organize() {
@@ -86,19 +106,21 @@ namespace Orchard.Environment {
}
public ShellSettings Match(string host, string appRelativePath) {
// optimized path when only one tenant (Default)
if (!_shellsByHost.Any()) {
return _fallback;
}
_lock.EnterReadLock();
try {
// optimized path when only one tenant (Default), configured with no custom host
if (!_shellsByHost.Any() && _fallback != null) {
return _fallback;
}
var hostLength = host.IndexOf(':');
if (hostLength != -1)
host = host.Substring(0, hostLength);
var hostLength = host.IndexOf(':');
if (hostLength != -1)
host = host.Substring(0, hostLength);
var mostQualifiedMatch = _shellsByHost
.Where(group => host.EndsWith(group.Key, StringComparison.OrdinalIgnoreCase))
.SelectMany(group => group
.OrderByDescending(settings => (settings.RequestUrlPrefix ?? string.Empty).Length))
var mostQualifiedMatch = _shellsByHost
.Where(group => host.EndsWith(group.Key, StringComparison.OrdinalIgnoreCase))
.SelectMany(group => group
.OrderByDescending(settings => (settings.RequestUrlPrefix ?? string.Empty).Length))
.FirstOrDefault(settings => {
if (settings.State == TenantState.Disabled) {
return false;
@@ -112,7 +134,11 @@ namespace Orchard.Environment {
|| appRelativePath.Equals("~/" + settings.RequestUrlPrefix, StringComparison.OrdinalIgnoreCase);
});
return mostQualifiedMatch ?? _fallback;
return mostQualifiedMatch ?? _fallback;
}
finally {
_lock.ExitReadLock();
}
}
}
}