mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Process all pending tasks at the end of the request
Instead of processing tasks asynchronously at the end of a request, we process them synchronously, so that the behavior is more deterministic. --HG-- branch : dev
This commit is contained in:
@@ -147,6 +147,8 @@ namespace Orchard.Environment {
|
||||
}
|
||||
|
||||
private void DisposeShellContext() {
|
||||
Logger.Information("Disposing active shell contexts");
|
||||
|
||||
if (_current != null) {
|
||||
foreach (var shellContext in _current) {
|
||||
shellContext.Shell.Terminate();
|
||||
@@ -160,25 +162,14 @@ namespace Orchard.Environment {
|
||||
BuildCurrent();
|
||||
}
|
||||
|
||||
|
||||
// the exit gate is temporary, until better control strategy is in place
|
||||
private readonly ManualResetEvent _exitGate = new ManualResetEvent(true);
|
||||
|
||||
protected virtual void EndRequest() {
|
||||
if (_processingEngine.AreTasksPending()) {
|
||||
_exitGate.Reset();
|
||||
ThreadPool.QueueUserWorkItem(state => {
|
||||
// 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.
|
||||
while (_processingEngine.AreTasksPending()) {
|
||||
_processingEngine.ExecuteNextTask();
|
||||
if (!_processingEngine.AreTasksPending()) {
|
||||
_exitGate.Set();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_exitGate.WaitOne(250);
|
||||
}
|
||||
|
||||
void IShellSettingsManagerEventHandler.Saved(ShellSettings settings) {
|
||||
DisposeShellContext();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
@@ -69,13 +70,25 @@ namespace Orchard.Environment.State {
|
||||
var shellContext = _shellContextFactory.CreateDescribedContext(entry.ShellSettings, entry.ShellDescriptor);
|
||||
using (shellContext.LifetimeScope) {
|
||||
using (var standaloneEnvironment = shellContext.LifetimeScope.CreateWorkContextScope()) {
|
||||
var eventBus = standaloneEnvironment.Resolve<IEventBus>();
|
||||
|
||||
ITransactionManager transactionManager;
|
||||
if (!standaloneEnvironment.TryResolve(out transactionManager))
|
||||
transactionManager = null;
|
||||
|
||||
try {
|
||||
var eventBus = standaloneEnvironment.Resolve<IEventBus>();
|
||||
Logger.Information("Executing event {0} in process {1} for shell {2}",
|
||||
entry.MessageName,
|
||||
entry.ProcessId,
|
||||
entry.ShellSettings.Name);
|
||||
eventBus.NotifyFailFast(entry.MessageName, entry.EventData);
|
||||
eventBus.Notify(entry.MessageName, entry.EventData);
|
||||
}
|
||||
catch {
|
||||
// any database changes in this using(env) scope are invalidated
|
||||
if (transactionManager != null)
|
||||
transactionManager.Cancel();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user