mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-08 00:14:31 +08:00
Compare commits
9 Commits
1.9.2
...
feature/ba
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8c7f8feaf6 | ||
![]() |
02b5b502ff | ||
![]() |
35bc0bfd3d | ||
![]() |
fb1f8c5751 | ||
![]() |
cc13f2e4b7 | ||
![]() |
2d2f4530eb | ||
![]() |
4ac9007018 | ||
![]() |
8189724522 | ||
![]() |
c635a5aa9d |
@@ -18,10 +18,10 @@
|
||||
|
||||
<components>
|
||||
<!--
|
||||
Uncomment to use ReadUncommitted as the default isolation level. Please not that
|
||||
Sql Server Ce doesn't support ReadUncommitted.
|
||||
Uncomment to use ReadUncommitted as the default isolation level.
|
||||
Please note that Sql Server Ce doesn't support ReadUncommitted.
|
||||
|
||||
Isolation level for all database transaction.
|
||||
Isolation level for all database transactions.
|
||||
See http://msdn.microsoft.com/en-us/library/system.transactions.isolationlevel.aspx
|
||||
-->
|
||||
<!--
|
||||
@@ -33,6 +33,40 @@
|
||||
</properties>
|
||||
</component>
|
||||
-->
|
||||
|
||||
<!--
|
||||
Uncomment to use ReadUncommitted as the isolation level for data migrations.
|
||||
Please note that Sql Server Ce doesn't support ReadUncommitted.
|
||||
|
||||
Isolation level for data migration database transactions.
|
||||
See http://msdn.microsoft.com/en-us/library/system.transactions.isolationlevel.aspx
|
||||
-->
|
||||
|
||||
<component instance-scope="per-lifetime-scope"
|
||||
type="Orchard.Data.Migration.DataMigrationManager, Orchard.Framework"
|
||||
service="Orchard.Data.Migration.IDataMigrationManager">
|
||||
<properties>
|
||||
<property name="IsolationLevel" value="ReadUncommitted" />
|
||||
</properties>
|
||||
</component>
|
||||
|
||||
|
||||
<!--
|
||||
Uncomment to use ReadUncommitted as the isolation level for background tasks.
|
||||
Please note that Sql Server Ce doesn't support ReadUncommitted.
|
||||
|
||||
Isolation level for background task database transactions.
|
||||
See http://msdn.microsoft.com/en-us/library/system.transactions.isolationlevel.aspx
|
||||
-->
|
||||
<!--
|
||||
<component instance-scope="per-lifetime-scope"
|
||||
type="Orchard.Tasks.BackgroundService, Orchard.Framework"
|
||||
service="Orchard.Tasks.IBackgroundService">
|
||||
<properties>
|
||||
<property name="IsolationLevel" value="ReadUncommitted" />
|
||||
</properties>
|
||||
</component>
|
||||
-->
|
||||
|
||||
<!--
|
||||
Delay between background services executions
|
||||
|
@@ -11,5 +11,9 @@ namespace Orchard.Commands {
|
||||
public void Sweep() {
|
||||
// Don't run any background service in command line
|
||||
}
|
||||
|
||||
public void Terminate() {
|
||||
// No need to terminate anything here
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
@@ -21,7 +22,6 @@ namespace Orchard.Data.Migration {
|
||||
private readonly IDataMigrationInterpreter _interpreter;
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
|
||||
private readonly List<string> _processedFeatures;
|
||||
|
||||
public DataMigrationManager(
|
||||
@@ -31,6 +31,7 @@ namespace Orchard.Data.Migration {
|
||||
IDataMigrationInterpreter interpreter,
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
ITransactionManager transactionManager) {
|
||||
|
||||
_dataMigrations = dataMigrations;
|
||||
_dataMigrationRepository = dataMigrationRepository;
|
||||
_extensionManager = extensionManager;
|
||||
@@ -40,10 +41,11 @@ namespace Orchard.Data.Migration {
|
||||
|
||||
_processedFeatures = new List<string>();
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
IsolationLevel = IsolationLevel.ReadCommitted;
|
||||
}
|
||||
public Localizer T { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
public IsolationLevel IsolationLevel { get; set; }
|
||||
|
||||
public IEnumerable<string> GetFeaturesThatNeedUpdate() {
|
||||
var currentVersions = _dataMigrationRepository.Table.ToDictionary(r => r.DataMigrationClass);
|
||||
@@ -91,7 +93,7 @@ namespace Orchard.Data.Migration {
|
||||
|
||||
// apply update methods to each migration class for the module
|
||||
foreach (var migration in migrations) {
|
||||
_transactionManager.RequireNew();
|
||||
_transactionManager.RequireNew(IsolationLevel);
|
||||
|
||||
// copy the object for the Linq query
|
||||
var tempMigration = migration;
|
||||
@@ -119,11 +121,11 @@ namespace Orchard.Data.Migration {
|
||||
|
||||
while (lookupTable.ContainsKey(current)) {
|
||||
try {
|
||||
Logger.Information("Applying migration for {0} from version {1}.", feature, current);
|
||||
Logger.Information("Applying migration for {0} from version {1}", feature, current);
|
||||
current = (int)lookupTable[current].Invoke(migration, new object[0]);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current);
|
||||
Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}", feature, current);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -140,16 +142,15 @@ namespace Orchard.Data.Migration {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Logger.Error(e, "Error while running migration version {0} for {1}.", current, feature);
|
||||
Logger.Error(e, "Error while running migration version {0} for {1}", current, feature);
|
||||
_transactionManager.Cancel();
|
||||
throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Uninstall(string feature) {
|
||||
Logger.Information("Uninstalling feature: {0}.", feature);
|
||||
Logger.Information("Uninstalling feature: {0}", feature);
|
||||
|
||||
var migrations = GetDataMigrations(feature);
|
||||
|
||||
|
@@ -244,6 +244,10 @@ namespace Orchard.Environment {
|
||||
StartUpdatedShells();
|
||||
}
|
||||
|
||||
public void Stop(bool immediate) {
|
||||
DisposeShellContext();
|
||||
}
|
||||
|
||||
void IShellSettingsManagerEventHandler.Saved(ShellSettings settings) {
|
||||
Logger.Debug("Shell saved: " + settings.Name);
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
using System.Web.Hosting;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Environment {
|
||||
public interface IOrchardHost {
|
||||
public interface IOrchardHost : IRegisteredObject {
|
||||
/// <summary>
|
||||
/// Called once on startup to configure app domain, and load/apply existing shell configuration
|
||||
/// </summary>
|
||||
|
@@ -335,6 +335,7 @@
|
||||
<Compile Include="Services\IJsonConverter.cs" />
|
||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||
<Compile Include="Tasks\ITerminatable.cs" />
|
||||
<Compile Include="Themes\CurrentThemeWorkContext.cs" />
|
||||
<Compile Include="Themes\ThemeManager.cs" />
|
||||
<Compile Include="Time\CurrentTimeZoneWorkContext.cs" />
|
||||
|
@@ -1,15 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Data;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Hosting;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Logging;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Tasks {
|
||||
|
||||
public interface IBackgroundService : IDependency {
|
||||
void Sweep();
|
||||
void Terminate();
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
@@ -17,32 +22,64 @@ namespace Orchard.Tasks {
|
||||
private readonly IEnumerable<IBackgroundTask> _tasks;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private readonly string _shellName;
|
||||
private readonly IContentManager _contentManager;
|
||||
private bool _shuttingDown;
|
||||
|
||||
private AutoResetEvent _finishedEvent = new AutoResetEvent(true);
|
||||
|
||||
public BackgroundService(
|
||||
IEnumerable<IBackgroundTask> tasks,
|
||||
ITransactionManager transactionManager,
|
||||
ShellSettings shellSettings,
|
||||
IContentManager contentManager) {
|
||||
ShellSettings shellSettings) {
|
||||
|
||||
_tasks = tasks;
|
||||
_transactionManager = transactionManager;
|
||||
_shellName = shellSettings.Name;
|
||||
_contentManager = contentManager;
|
||||
Logger = NullLogger.Instance;
|
||||
IsolationLevel = IsolationLevel.ReadCommitted;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
public IsolationLevel IsolationLevel { get; set; }
|
||||
|
||||
public void Sweep() {
|
||||
foreach(var task in _tasks) {
|
||||
if (_shuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_transactionManager.RequireNew();
|
||||
_finishedEvent.Reset();
|
||||
_transactionManager.RequireNew(IsolationLevel);
|
||||
task.Sweep();
|
||||
}
|
||||
catch (Exception e) {
|
||||
_transactionManager.Cancel();
|
||||
Logger.Error(e, "Error while processing background task on tenant '{0}'.", _shellName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_finishedEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Terminate() {
|
||||
Logger.Debug("Background service terminating...");
|
||||
_shuttingDown = true;
|
||||
|
||||
foreach (var task in _tasks.Where(t => t is ITerminatable)) {
|
||||
try {
|
||||
((ITerminatable)task).Terminate();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "Error while terminating background task {0}", task.GetType().Name);
|
||||
}
|
||||
}
|
||||
|
||||
if (_finishedEvent != null) {
|
||||
_finishedEvent.WaitOne(TimeSpan.FromSeconds(90));
|
||||
_finishedEvent.Dispose();
|
||||
_finishedEvent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
src/Orchard/Tasks/ITerminatable.cs
Normal file
5
src/Orchard/Tasks/ITerminatable.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace Orchard.Tasks {
|
||||
public interface ITerminatable {
|
||||
void Terminate();
|
||||
}
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Timers;
|
||||
using System.Web.Hosting;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Tasks {
|
||||
|
||||
public interface ISweepGenerator : ISingletonDependency {
|
||||
public interface ISweepGenerator : IRegisteredObject, ISingletonDependency {
|
||||
void Activate();
|
||||
void Terminate();
|
||||
}
|
||||
@@ -12,6 +14,9 @@ namespace Orchard.Tasks {
|
||||
public class SweepGenerator : ISweepGenerator, IDisposable {
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly Timer _timer;
|
||||
private bool _shuttingDown;
|
||||
|
||||
private IBackgroundService _manager;
|
||||
|
||||
public SweepGenerator(IWorkContextAccessor workContextAccessor) {
|
||||
_workContextAccessor = workContextAccessor;
|
||||
@@ -19,6 +24,8 @@ namespace Orchard.Tasks {
|
||||
_timer.Elapsed += Elapsed;
|
||||
Logger = NullLogger.Instance;
|
||||
Interval = TimeSpan.FromMinutes(1);
|
||||
|
||||
HostingEnvironment.RegisterObject(this);
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
@@ -46,7 +53,7 @@ namespace Orchard.Tasks {
|
||||
return;
|
||||
|
||||
try {
|
||||
if (_timer.Enabled) {
|
||||
if (_timer.Enabled && !_shuttingDown) {
|
||||
DoWork();
|
||||
}
|
||||
}
|
||||
@@ -61,13 +68,20 @@ namespace Orchard.Tasks {
|
||||
public void DoWork() {
|
||||
using (var scope = _workContextAccessor.CreateWorkContextScope()) {
|
||||
// resolve the manager and invoke it
|
||||
var manager = scope.Resolve<IBackgroundService>();
|
||||
manager.Sweep();
|
||||
_manager = scope.Resolve<IBackgroundService>();
|
||||
_manager.Sweep();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
_timer.Dispose();
|
||||
}
|
||||
|
||||
public void Stop(bool immediate) {
|
||||
_shuttingDown = true;
|
||||
_manager.Terminate();
|
||||
|
||||
HostingEnvironment.UnregisterObject(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user