mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Fixing shell context activation as per module enabling/disabling
--HG-- branch : 1.x
This commit is contained in:
@@ -139,7 +139,7 @@ namespace Orchard.Tests.Environment {
|
||||
public void NormalDependenciesShouldBeUniquePerRequestContainer() {
|
||||
var host = _lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer_Obsolete();
|
||||
((IShellDescriptorManagerEventHandler)host).Changed(null);
|
||||
((IShellDescriptorManagerEventHandler)host).Changed(null, String.Empty);
|
||||
var container2 = host.CreateShellContainer_Obsolete();
|
||||
var requestContainer1a = container1.BeginLifetimeScope();
|
||||
var requestContainer1b = container1.BeginLifetimeScope();
|
||||
|
@@ -2,20 +2,25 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Core.Settings.Descriptor.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Core.Settings.Descriptor {
|
||||
public class ShellDescriptorManager : IShellDescriptorManager {
|
||||
private readonly IRepository<ShellDescriptorRecord> _shellDescriptorRepository;
|
||||
private readonly IShellDescriptorManagerEventHandler _events;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
|
||||
public ShellDescriptorManager(
|
||||
IRepository<ShellDescriptorRecord> shellDescriptorRepository,
|
||||
IShellDescriptorManagerEventHandler events) {
|
||||
IShellDescriptorManagerEventHandler events,
|
||||
ShellSettings shellSettings) {
|
||||
_shellDescriptorRepository = shellDescriptorRepository;
|
||||
_events = events;
|
||||
_shellSettings = shellSettings;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@@ -82,9 +87,7 @@ namespace Orchard.Core.Settings.Descriptor {
|
||||
});
|
||||
}
|
||||
|
||||
_events.Changed(GetShellDescriptorFromRecord(shellDescriptorRecord));
|
||||
_events.Changed(GetShellDescriptorFromRecord(shellDescriptorRecord), _shellSettings.Name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -150,6 +150,9 @@ namespace Orchard.Setup.Services {
|
||||
}
|
||||
}
|
||||
|
||||
_shellSettingsManager.SaveSettings(shellSettings);
|
||||
|
||||
|
||||
// in effect "pump messages" see PostMessage circa 1980
|
||||
while ( _processingEngine.AreTasksPending() )
|
||||
_processingEngine.ExecuteNextTask();
|
||||
@@ -170,11 +173,11 @@ namespace Orchard.Setup.Services {
|
||||
}
|
||||
}
|
||||
|
||||
while (_processingEngine.AreTasksPending())
|
||||
_processingEngine.ExecuteNextTask();
|
||||
|
||||
_shellSettingsManager.SaveSettings(shellSettings);
|
||||
//// execute pending recipe steps
|
||||
//while (_processingEngine.AreTasksPending())
|
||||
// _processingEngine.ExecuteNextTask();
|
||||
|
||||
|
||||
return executionId;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Transactions;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
@@ -23,7 +24,8 @@ namespace Orchard.Environment {
|
||||
private readonly ICacheManager _cacheManager;
|
||||
private readonly object _syncLock = new object();
|
||||
|
||||
private IEnumerable<ShellContext> _current;
|
||||
private IEnumerable<ShellContext> _shellContexts;
|
||||
private IEnumerable<ShellSettings> _tenantsToRestart;
|
||||
|
||||
public DefaultOrchardHost(
|
||||
IShellSettingsManager shellSettingsManager,
|
||||
@@ -42,6 +44,7 @@ namespace Orchard.Environment {
|
||||
_extensionMonitoringCoordinator = extensionMonitoringCoordinator;
|
||||
_cacheManager = cacheManager;
|
||||
_hostLocalRestart = hostLocalRestart;
|
||||
_tenantsToRestart = Enumerable.Empty<ShellSettings>();
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
Logger = NullLogger.Instance;
|
||||
@@ -88,44 +91,65 @@ namespace Orchard.Environment {
|
||||
return shellContext.LifetimeScope.CreateWorkContextScope();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures shells are activated, or re-activated if extensions have changed
|
||||
/// </summary>
|
||||
IEnumerable<ShellContext> BuildCurrent() {
|
||||
if (_current == null) {
|
||||
if (_shellContexts == null) {
|
||||
lock (_syncLock) {
|
||||
if (_current == null) {
|
||||
if (_shellContexts == null) {
|
||||
SetupExtensions();
|
||||
MonitorExtensions();
|
||||
_current = CreateAndActivate().ToArray();
|
||||
CreateAndActivateShells();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _current;
|
||||
|
||||
return _shellContexts;
|
||||
}
|
||||
|
||||
IEnumerable<ShellContext> CreateAndActivate() {
|
||||
void StartUpdatedShells() {
|
||||
lock (_syncLock) {
|
||||
if (_tenantsToRestart.Any()) {
|
||||
foreach (var settings in _tenantsToRestart.Distinct().ToList()) {
|
||||
ActivateShell(settings);
|
||||
}
|
||||
|
||||
_tenantsToRestart = Enumerable.Empty<ShellSettings>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateAndActivateShells() {
|
||||
Logger.Information("Start creation of shells");
|
||||
|
||||
IEnumerable<ShellContext> result;
|
||||
// is there any tenant right now ?
|
||||
var allSettings = _shellSettingsManager.LoadSettings();
|
||||
|
||||
// load all tenants, and activate their shell
|
||||
if (allSettings.Any()) {
|
||||
result = allSettings.Select(
|
||||
settings => {
|
||||
var context = CreateShellContext(settings);
|
||||
ActivateShell(context);
|
||||
return context;
|
||||
});
|
||||
foreach (var settings in allSettings) {
|
||||
var context = CreateShellContext(settings);
|
||||
ActivateShell(context);
|
||||
}
|
||||
}
|
||||
// no settings, run the Setup
|
||||
else {
|
||||
var setupContext = CreateSetupContext();
|
||||
ActivateShell(setupContext);
|
||||
result = new[] {setupContext};
|
||||
}
|
||||
|
||||
Logger.Information("Done creating shells");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a Shell and register its settings in RunningShellTable
|
||||
/// </summary>
|
||||
private void ActivateShell(ShellContext context) {
|
||||
Logger.Debug("Activating context for tenant {0}", context.Settings.Name);
|
||||
context.Shell.Activate();
|
||||
|
||||
_shellContexts = (_shellContexts ?? Enumerable.Empty<ShellContext>()).Union(new [] {context});
|
||||
_runningShellTable.Add(context.Settings);
|
||||
}
|
||||
|
||||
@@ -161,27 +185,34 @@ namespace Orchard.Environment {
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminates all active shell contexts, and dispose their scope, forcing
|
||||
/// them to be reloaded if necessary.
|
||||
/// </summary>
|
||||
private void DisposeShellContext() {
|
||||
Logger.Information("Disposing active shell contexts");
|
||||
|
||||
if (_current != null) {
|
||||
foreach (var shellContext in _current) {
|
||||
if (_shellContexts != null) {
|
||||
foreach (var shellContext in _shellContexts) {
|
||||
shellContext.Shell.Terminate();
|
||||
shellContext.LifetimeScope.Dispose();
|
||||
}
|
||||
_current = null;
|
||||
_shellContexts = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void BeginRequest() {
|
||||
// Ensure all shell contexts are loaded, or need to be reloaded if
|
||||
// extensions have changed
|
||||
MonitorExtensions();
|
||||
BuildCurrent();
|
||||
StartUpdatedShells();
|
||||
}
|
||||
|
||||
protected virtual void EndRequest() {
|
||||
// Synchronously process all pending tasks. It's safe to do this at this point
|
||||
// of the pipeline, as the request transaction has been closed, so creating a new
|
||||
// environment and transaction for these tasks will behave as expected.
|
||||
// environment and transaction for these tasks will behave as expected.)
|
||||
while (_processingEngine.AreTasksPending()) {
|
||||
_processingEngine.ExecuteNextTask();
|
||||
}
|
||||
@@ -190,33 +221,37 @@ namespace Orchard.Environment {
|
||||
/// <summary>
|
||||
/// Register and activate a new Shell when a tenant is created
|
||||
/// </summary>
|
||||
void IShellSettingsManagerEventHandler.Saved(ShellSettings settings)
|
||||
{
|
||||
// is it a new tenant ?
|
||||
var shellContext = _current.FirstOrDefault(c => c.Settings.Name == settings.Name);
|
||||
|
||||
ShellContext context;
|
||||
|
||||
// if null, this is a new tenant, register and activate a new context
|
||||
if(shellContext == null)
|
||||
{
|
||||
context = CreateShellContext(settings);
|
||||
ActivateShell(context);
|
||||
_current = _current.Union(new[] { context });
|
||||
_runningShellTable.Add(settings);
|
||||
void IShellSettingsManagerEventHandler.Saved(ShellSettings settings) {
|
||||
lock (_syncLock) {
|
||||
_tenantsToRestart = _tenantsToRestart.Where(x => x.Name != settings.Name).Union(new[] { settings });
|
||||
}
|
||||
else
|
||||
{
|
||||
context = _shellContextFactory.CreateShellContext(settings);
|
||||
}
|
||||
|
||||
void ActivateShell(ShellSettings settings) {
|
||||
// look for the associated shell context
|
||||
var shellContext = _shellContexts.FirstOrDefault(c => c.Settings.Name == settings.Name);
|
||||
|
||||
// is this is a new tenant ?
|
||||
if (shellContext == null) {
|
||||
// create the Shell
|
||||
var context = CreateShellContext(settings);
|
||||
|
||||
// activate the Shell
|
||||
ActivateShell(context);
|
||||
}
|
||||
// reload the shell as its settings have changed
|
||||
else {
|
||||
// dispose previous context
|
||||
shellContext.Shell.Terminate();
|
||||
shellContext.LifetimeScope.Dispose();
|
||||
|
||||
var context = _shellContextFactory.CreateShellContext(settings);
|
||||
|
||||
// activate and register modified context
|
||||
_current = _current.Where(shell => shell.Settings.Name != settings.Name).Union(new[] { shellContext });
|
||||
|
||||
_shellContexts = _shellContexts.Where(shell => shell.Settings.Name != settings.Name).Union(new[] { context });
|
||||
|
||||
context.Shell.Activate();
|
||||
|
||||
_runningShellTable.Update(settings);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +259,23 @@ namespace Orchard.Environment {
|
||||
/// <summary>
|
||||
/// A feature is enabled/disabled
|
||||
/// </summary>
|
||||
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) {
|
||||
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor, string tenant) {
|
||||
lock (_syncLock) {
|
||||
var context = _shellContexts.Where(x => x.Settings.Name == tenant).FirstOrDefault();
|
||||
|
||||
// some shells might need to be started, e.g. created by command line
|
||||
if(context == null) {
|
||||
StartUpdatedShells();
|
||||
context = _shellContexts.Where(x => x.Settings.Name == tenant).First();
|
||||
}
|
||||
|
||||
// don't update the settings themselves here
|
||||
if(_tenantsToRestart.Any(x => x.Name == tenant)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_tenantsToRestart = _tenantsToRestart.Union(new[] { context.Settings });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,6 @@ namespace Orchard.Environment.Descriptor {
|
||||
}
|
||||
|
||||
public interface IShellDescriptorManagerEventHandler : IEventHandler {
|
||||
void Changed(ShellDescriptor descriptor);
|
||||
void Changed(ShellDescriptor descriptor, string tenant);
|
||||
}
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ namespace Orchard.Environment {
|
||||
TouchFile();
|
||||
}
|
||||
|
||||
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) {
|
||||
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor, string tenant) {
|
||||
TouchFile();
|
||||
}
|
||||
|
||||
|
@@ -89,7 +89,7 @@ namespace Orchard.Environment {
|
||||
.Where(group => host.EndsWith(group.Key, StringComparison.OrdinalIgnoreCase))
|
||||
.SelectMany(group => group
|
||||
.OrderByDescending(settings => (settings.RequestUrlPrefix ?? "").Length))
|
||||
.Where(settings => settings.State.CurrentState == TenantState.State.Running && appRelativePath.StartsWith(settings.RequestUrlPrefix ?? "", StringComparison.OrdinalIgnoreCase))
|
||||
.Where(settings => settings.State.CurrentState != TenantState.State.Disabled && appRelativePath.StartsWith(settings.RequestUrlPrefix ?? "", StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
|
||||
return mostQualifiedMatch ?? _fallback;
|
||||
|
@@ -33,7 +33,7 @@ namespace Orchard.Environment.State {
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) {
|
||||
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor, string tenant) {
|
||||
// deduce and apply state changes involved
|
||||
var shellState = _stateManager.GetShellState();
|
||||
foreach (var feature in descriptor.Features) {
|
||||
|
Reference in New Issue
Block a user