Fix issue with SqlMainDomLock that cannot use implicit lock timeouts … (#9973)
This commit is contained in:
@@ -409,26 +409,34 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
if (_sqlWriteLockTimeOut != default) return _sqlWriteLockTimeOut;
|
||||
|
||||
var timeOut = 5000; // 5 seconds
|
||||
var appSettingSqlWriteLockTimeOut = ConfigurationManager.AppSettings[Constants.AppSettings.SqlWriteLockTimeOut];
|
||||
if(int.TryParse(appSettingSqlWriteLockTimeOut, out var configuredTimeOut))
|
||||
{
|
||||
// Only apply this setting if it's not excessively high or low
|
||||
const int minimumTimeOut = 100;
|
||||
const int maximumTimeOut = 20000;
|
||||
if (configuredTimeOut >= minimumTimeOut && configuredTimeOut <= maximumTimeOut) // between 0.1 and 20 seconds
|
||||
{
|
||||
timeOut = configuredTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
Current.Logger.Warn<GlobalSettings>($"The `{Constants.AppSettings.SqlWriteLockTimeOut}` setting in web.config is not between the minimum of {minimumTimeOut} ms and maximum of {maximumTimeOut} ms, defaulting back to {timeOut}");
|
||||
}
|
||||
}
|
||||
var timeOut = GetSqlWriteLockTimeoutFromConfigFile(Current.Logger);
|
||||
|
||||
_sqlWriteLockTimeOut = timeOut;
|
||||
return _sqlWriteLockTimeOut;
|
||||
}
|
||||
}
|
||||
|
||||
internal static int GetSqlWriteLockTimeoutFromConfigFile(ILogger logger)
|
||||
{
|
||||
var timeOut = 5000; // 5 seconds
|
||||
var appSettingSqlWriteLockTimeOut = ConfigurationManager.AppSettings[Constants.AppSettings.SqlWriteLockTimeOut];
|
||||
if (int.TryParse(appSettingSqlWriteLockTimeOut, out var configuredTimeOut))
|
||||
{
|
||||
// Only apply this setting if it's not excessively high or low
|
||||
const int minimumTimeOut = 100;
|
||||
const int maximumTimeOut = 20000;
|
||||
if (configuredTimeOut >= minimumTimeOut && configuredTimeOut <= maximumTimeOut) // between 0.1 and 20 seconds
|
||||
{
|
||||
timeOut = configuredTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn<GlobalSettings>(
|
||||
$"The `{Constants.AppSettings.SqlWriteLockTimeOut}` setting in web.config is not between the minimum of {minimumTimeOut} ms and maximum of {maximumTimeOut} ms, defaulting back to {timeOut}");
|
||||
}
|
||||
}
|
||||
|
||||
return timeOut;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using NPoco;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Diagnostics;
|
||||
@@ -7,6 +8,7 @@ using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
@@ -18,6 +20,7 @@ namespace Umbraco.Core.Runtime
|
||||
{
|
||||
internal class SqlMainDomLock : IMainDomLock
|
||||
{
|
||||
private readonly TimeSpan _lockTimeout;
|
||||
private string _lockId;
|
||||
private const string MainDomKeyPrefix = "Umbraco.Core.Runtime.SqlMainDom";
|
||||
private const string UpdatedSuffix = "_updated";
|
||||
@@ -40,6 +43,8 @@ namespace Umbraco.Core.Runtime
|
||||
Constants.System.UmbracoConnectionName,
|
||||
_logger,
|
||||
new Lazy<IMapperCollection>(() => new MapperCollection(Enumerable.Empty<BaseMapper>())));
|
||||
|
||||
_lockTimeout = TimeSpan.FromMilliseconds(GlobalSettings.GetSqlWriteLockTimeoutFromConfigFile(logger));
|
||||
}
|
||||
|
||||
public async Task<bool> AcquireLockAsync(int millisecondsTimeout)
|
||||
@@ -198,7 +203,7 @@ namespace Umbraco.Core.Runtime
|
||||
|
||||
db.BeginTransaction(IsolationLevel.ReadCommitted);
|
||||
// get a read lock
|
||||
_sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom);
|
||||
_sqlServerSyntax.ReadLock(db, _lockTimeout, Constants.Locks.MainDom);
|
||||
|
||||
if (!IsMainDomValue(_lockId, db))
|
||||
{
|
||||
@@ -284,7 +289,7 @@ namespace Umbraco.Core.Runtime
|
||||
{
|
||||
transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
|
||||
// get a read lock
|
||||
_sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom);
|
||||
_sqlServerSyntax.ReadLock(db, _lockTimeout, Constants.Locks.MainDom);
|
||||
|
||||
// the row
|
||||
var mainDomRows = db.Fetch<KeyValueDto>("SELECT * FROM umbracoKeyValue WHERE [key] = @key", new { key = MainDomKey });
|
||||
@@ -296,7 +301,7 @@ namespace Umbraco.Core.Runtime
|
||||
// which indicates that we
|
||||
// can acquire it and it has shutdown.
|
||||
|
||||
_sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom);
|
||||
_sqlServerSyntax.WriteLock(db, _lockTimeout, Constants.Locks.MainDom);
|
||||
|
||||
// so now we update the row with our appdomain id
|
||||
InsertLockRecord(_lockId, db);
|
||||
@@ -355,7 +360,7 @@ namespace Umbraco.Core.Runtime
|
||||
{
|
||||
transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
|
||||
|
||||
_sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom);
|
||||
_sqlServerSyntax.WriteLock(db, _lockTimeout, Constants.Locks.MainDom);
|
||||
|
||||
// so now we update the row with our appdomain id
|
||||
InsertLockRecord(_lockId, db);
|
||||
@@ -438,7 +443,7 @@ namespace Umbraco.Core.Runtime
|
||||
db.BeginTransaction(IsolationLevel.ReadCommitted);
|
||||
|
||||
// get a write lock
|
||||
_sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom);
|
||||
_sqlServerSyntax.WriteLock(db, _lockTimeout, Constants.Locks.MainDom);
|
||||
|
||||
// When we are disposed, it means we have released the MainDom lock
|
||||
// and called all MainDom release callbacks, in this case
|
||||
|
||||
Reference in New Issue
Block a user