U4-6992 - fix server registration for new LB
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using System.Configuration;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
@@ -259,22 +260,13 @@ namespace Umbraco.Core
|
||||
{
|
||||
get
|
||||
{
|
||||
// if initialized, return
|
||||
if (_umbracoApplicationUrl != null) return _umbracoApplicationUrl;
|
||||
|
||||
// try settings
|
||||
ServerEnvironmentHelper.TrySetApplicationUrlFromSettings(this, ProfilingLogger.Logger, UmbracoConfig.For.UmbracoSettings());
|
||||
|
||||
// and return what we have, may be null
|
||||
ApplicationUrlHelper.EnsureApplicationUrl(this);
|
||||
return _umbracoApplicationUrl;
|
||||
}
|
||||
set
|
||||
{
|
||||
_umbracoApplicationUrl = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal string _umbracoApplicationUrl; // internal for tests
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal string _umbracoApplicationUrl;
|
||||
|
||||
private Lazy<bool> _configured;
|
||||
internal MainDom MainDom { get; private set; }
|
||||
@@ -379,6 +371,11 @@ namespace Umbraco.Core
|
||||
internal set { _services = value; }
|
||||
}
|
||||
|
||||
internal ServerRole GetCurrentServerRole()
|
||||
{
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
return registrar == null ? ServerRole.Unknown : registrar.GetCurrentServerRole();
|
||||
}
|
||||
|
||||
private volatile bool _disposed;
|
||||
private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
public const int DefaultMediaListViewDataTypeId = -96;
|
||||
public const int DefaultMembersListViewDataTypeId = -97;
|
||||
|
||||
// identifiers for lock objects
|
||||
public const int ServersLock = -331;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,13 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
bool IsActive { get; set; }
|
||||
|
||||
// note: cannot add this because of backward compatibility
|
||||
//
|
||||
///// <summary>
|
||||
///// Gets or sets a value indicating whether the server is master.
|
||||
///// </summary>
|
||||
//bool IsMaster { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date and time the registration was created.
|
||||
/// </summary>
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[Index(IndexTypes.NonClustered)]
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
|
||||
[Column("isMaster")]
|
||||
public bool IsMaster { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -14,10 +13,12 @@ namespace Umbraco.Core.Models
|
||||
private string _serverAddress;
|
||||
private string _serverIdentity;
|
||||
private bool _isActive;
|
||||
private bool _isMaster;
|
||||
|
||||
private static readonly PropertyInfo ServerAddressSelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, string>(x => x.ServerAddress);
|
||||
private static readonly PropertyInfo ServerIdentitySelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, string>(x => x.ServerIdentity);
|
||||
private static readonly PropertyInfo IsActiveSelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, bool>(x => x.IsActive);
|
||||
private static readonly PropertyInfo IsMasterSelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, bool>(x => x.IsMaster);
|
||||
|
||||
/// <summary>
|
||||
/// Initialiazes a new instance of the <see cref="ServerRegistration"/> class.
|
||||
@@ -34,7 +35,8 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="registered">The date and time the registration was created.</param>
|
||||
/// <param name="accessed">The date and time the registration was last accessed.</param>
|
||||
/// <param name="isActive">A value indicating whether the registration is active.</param>
|
||||
public ServerRegistration(int id, string serverAddress, string serverIdentity, DateTime registered, DateTime accessed, bool isActive)
|
||||
/// <param name="isMaster">A value indicating whether the registration is master.</param>
|
||||
public ServerRegistration(int id, string serverAddress, string serverIdentity, DateTime registered, DateTime accessed, bool isActive, bool isMaster)
|
||||
{
|
||||
UpdateDate = accessed;
|
||||
CreateDate = registered;
|
||||
@@ -43,6 +45,7 @@ namespace Umbraco.Core.Models
|
||||
ServerAddress = serverAddress;
|
||||
ServerIdentity = serverIdentity;
|
||||
IsActive = isActive;
|
||||
IsMaster = isMaster;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -108,6 +111,22 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the server is master.
|
||||
/// </summary>
|
||||
public bool IsMaster
|
||||
{
|
||||
get { return _isMaster; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_isMaster = value;
|
||||
return _isMaster;
|
||||
}, _isMaster, IsMasterSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date and time the registration was created.
|
||||
/// </summary>
|
||||
@@ -124,7 +143,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{{\"{0}\", \"{1}\", {2}active}}", ServerAddress, ServerIdentity, IsActive ? "" : "!");
|
||||
return string.Format("{{\"{0}\", \"{1}\", {2}active, {3}master}}", ServerAddress, ServerIdentity, IsActive ? "" : "!", IsMaster ? "" : "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
public ServerRegistration BuildEntity(ServerRegistrationDto dto)
|
||||
{
|
||||
var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive);
|
||||
var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive, dto.IsMaster);
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
model.ResetDirtyProperties(false);
|
||||
@@ -21,6 +21,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
ServerAddress = entity.ServerAddress,
|
||||
DateRegistered = entity.CreateDate,
|
||||
IsActive = entity.IsActive,
|
||||
IsMaster = ((ServerRegistration) entity).IsMaster,
|
||||
DateAccessed = entity.UpdateDate,
|
||||
ServerIdentity = entity.ServerIdentity
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.Id, dto => dto.Id);
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.IsActive, dto => dto.IsActive);
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.IsMaster, dto => dto.IsMaster);
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.ServerAddress, dto => dto.ServerAddress);
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.CreateDate, dto => dto.DateRegistered);
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.UpdateDate, dto => dto.DateAccessed);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
|
||||
{
|
||||
[Migration("7.3.0", 17, GlobalSettings.UmbracoMigrationName)]
|
||||
public class AddServerRegistrationColumnsAndLock : MigrationBase
|
||||
{
|
||||
public AddServerRegistrationColumnsAndLock(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
// don't execute if the column is already there
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
|
||||
if (columns.Any(x => x.TableName.InvariantEquals("umbracoServer") && x.ColumnName.InvariantEquals("isMaster")) == false)
|
||||
{
|
||||
Create.Column("isMaster").OnTable("umbracoServer").AsBoolean().NotNullable().WithDefaultValue(0);
|
||||
}
|
||||
|
||||
// wrap in a transaction so that everything runs on the same connection
|
||||
// and the IDENTITY_INSERT stuff is effective for all inserts.
|
||||
using (var tr = Context.Database.GetTransaction())
|
||||
{
|
||||
// turn on identity insert if db provider is not mysql
|
||||
if (SqlSyntax.SupportsIdentityInsert())
|
||||
Context.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
|
||||
InsertLockObject(Constants.System.ServersLock, "0AF5E610-A310-4B6F-925F-E928D5416AF7", "LOCK: Servers");
|
||||
|
||||
// turn off identity insert if db provider is not mysql
|
||||
if (SqlSyntax.SupportsIdentityInsert())
|
||||
Context.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
|
||||
tr.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
private void InsertLockObject(int id, string uniqueId, string text)
|
||||
{
|
||||
var exists = Context.Database.Exists<NodeDto>(id);
|
||||
if (exists) return;
|
||||
|
||||
Context.Database.Insert("umbracoNode", "id", false, new NodeDto
|
||||
{
|
||||
NodeId = id,
|
||||
Trashed = false,
|
||||
ParentId = -1,
|
||||
UserId = 0,
|
||||
Level = 1,
|
||||
Path = "-1," + id,
|
||||
SortOrder = 0,
|
||||
UniqueId = new Guid(uniqueId),
|
||||
Text = text,
|
||||
NodeObjectType = new Guid(Constants.ObjectTypes.LockObject),
|
||||
CreateDate = DateTime.Now
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,10 +117,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public void DeactiveStaleServers(TimeSpan staleTimeout)
|
||||
{
|
||||
var timeoutDate = DateTime.UtcNow.Subtract(staleTimeout);
|
||||
var timeoutDate = DateTime.Now.Subtract(staleTimeout);
|
||||
|
||||
Database.Update<ServerRegistrationDto>("SET isActive=0 WHERE lastNotifiedDate < @timeoutDate", new { timeoutDate = timeoutDate });
|
||||
Database.Update<ServerRegistrationDto>("SET isActive=0, isMaster=0 WHERE lastNotifiedDate < @timeoutDate", new { timeoutDate = timeoutDate });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -29,7 +30,22 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Return all active servers.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <returns>All active servers.</returns>
|
||||
IEnumerable<IServerRegistration> GetActiveServers();
|
||||
|
||||
// note: cannot add this because of backward compatibility
|
||||
//
|
||||
///// <summary>
|
||||
///// Gets the current server identity.
|
||||
///// </summary>
|
||||
//string CurrentServerIdentity { get; }
|
||||
|
||||
// note: cannot add this because of backward compatibility
|
||||
//
|
||||
///// <summary>
|
||||
///// Gets the role of the current server.
|
||||
///// </summary>
|
||||
///// <returns>The role of the current server.</returns>
|
||||
//ServerRole GetCurrentServerRole();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -15,6 +18,13 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public sealed class ServerRegistrationService : RepositoryService, IServerRegistrationService
|
||||
{
|
||||
private readonly static string CurrentServerIdentityValue = NetworkHelper.MachineName // eg DOMAIN\SERVER
|
||||
+ "/" + HttpRuntime.AppDomainAppId; // eg /LM/S3SVC/11/ROOT
|
||||
|
||||
private static readonly int[] LockingRepositoryIds = { Constants.System.ServersLock };
|
||||
private ServerRole _currentServerRole = ServerRole.Unknown;
|
||||
private readonly LockingRepository<IServerRegistrationRepository> _lrepo;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerRegistrationService"/> class.
|
||||
/// </summary>
|
||||
@@ -24,7 +34,12 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="eventMessagesFactory"></param>
|
||||
public ServerRegistrationService(IDatabaseUnitOfWorkProvider uowProvider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory)
|
||||
: base(uowProvider, repositoryFactory, logger, eventMessagesFactory)
|
||||
{ }
|
||||
{
|
||||
_lrepo = new LockingRepository<IServerRegistrationRepository>(UowProvider,
|
||||
x => RepositoryFactory.CreateServerRegistrationRepository(x),
|
||||
LockingRepositoryIds, LockingRepositoryIds);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Touches a server to mark it as active; deactivate stale servers.
|
||||
@@ -34,29 +49,42 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="staleTimeout">The time after which a server is considered stale.</param>
|
||||
public void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout)
|
||||
{
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow))
|
||||
_lrepo.WithWriteLocked(xr =>
|
||||
{
|
||||
var query = Query<IServerRegistration>.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper());
|
||||
var server = repo.GetByQuery(query).FirstOrDefault();
|
||||
var regs = xr.Repository.GetAll().ToArray(); // faster to query only once
|
||||
var hasMaster = regs.Any(x => ((ServerRegistration)x).IsMaster);
|
||||
var iserver = regs.FirstOrDefault(x => x.ServerIdentity.InvariantEquals(serverIdentity));
|
||||
var server = iserver as ServerRegistration; // because IServerRegistration is missing IsMaster
|
||||
var hasServer = server != null;
|
||||
|
||||
if (server == null)
|
||||
{
|
||||
server = new ServerRegistration(serverAddress, serverIdentity, DateTime.UtcNow)
|
||||
{
|
||||
IsActive = true
|
||||
};
|
||||
server = new ServerRegistration(serverAddress, serverIdentity, DateTime.Now);
|
||||
}
|
||||
else
|
||||
{
|
||||
server.ServerAddress = serverAddress; // should not really change but it might!
|
||||
server.UpdateDate = DateTime.UtcNow; // stick with Utc dates since these might be globally distributed
|
||||
server.IsActive = true;
|
||||
server.UpdateDate = DateTime.Now;
|
||||
}
|
||||
repo.AddOrUpdate(server);
|
||||
uow.Commit();
|
||||
|
||||
repo.DeactiveStaleServers(staleTimeout);
|
||||
}
|
||||
server.IsActive = true;
|
||||
if (hasMaster == false)
|
||||
server.IsMaster = true;
|
||||
|
||||
xr.Repository.AddOrUpdate(server);
|
||||
xr.UnitOfWork.Commit();
|
||||
xr.Repository.DeactiveStaleServers(staleTimeout);
|
||||
|
||||
// default role is single server
|
||||
_currentServerRole = ServerRole.Single;
|
||||
|
||||
// if registrations contain more than 0/1 server, role is master or slave
|
||||
// compare to 0 or 1 depending on whether regs already contains the server
|
||||
if (regs.Length > (hasServer ? 1 : 0))
|
||||
_currentServerRole = server.IsMaster
|
||||
? ServerRole.Master
|
||||
: ServerRole.Slave;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,18 +93,17 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="serverIdentity">The server unique identity.</param>
|
||||
public void DeactiveServer(string serverIdentity)
|
||||
{
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow))
|
||||
_lrepo.WithWriteLocked(xr =>
|
||||
{
|
||||
var query = Query<IServerRegistration>.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper());
|
||||
var server = repo.GetByQuery(query).FirstOrDefault();
|
||||
if (server != null)
|
||||
{
|
||||
server.IsActive = false;
|
||||
repo.AddOrUpdate(server);
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
var iserver = xr.Repository.GetByQuery(query).FirstOrDefault();
|
||||
var server = iserver as ServerRegistration; // because IServerRegistration is missing IsMaster
|
||||
if (server == null) return;
|
||||
|
||||
server.IsActive = false;
|
||||
server.IsMaster = false;
|
||||
xr.Repository.AddOrUpdate(server);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -85,11 +112,7 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="staleTimeout">The time after which a server is considered stale.</param>
|
||||
public void DeactiveStaleServers(TimeSpan staleTimeout)
|
||||
{
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow))
|
||||
{
|
||||
repo.DeactiveStaleServers(staleTimeout);
|
||||
}
|
||||
_lrepo.WithWriteLocked(xr => xr.Repository.DeactiveStaleServers(staleTimeout));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -98,12 +121,25 @@ namespace Umbraco.Core.Services
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IServerRegistration> GetActiveServers()
|
||||
{
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow))
|
||||
return _lrepo.WithReadLocked(xr =>
|
||||
{
|
||||
var query = Query<IServerRegistration>.Builder.Where(x => x.IsActive);
|
||||
return repo.GetByQuery(query).ToArray();
|
||||
}
|
||||
return xr.Repository.GetByQuery(query).ToArray();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local server identity.
|
||||
/// </summary>
|
||||
public string CurrentServerIdentity { get { return CurrentServerIdentityValue; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the role of the current server.
|
||||
/// </summary>
|
||||
/// <returns>The role of the current server.</returns>
|
||||
public ServerRole GetCurrentServerRole()
|
||||
{
|
||||
return _currentServerRole;
|
||||
}
|
||||
}
|
||||
}
|
||||
133
src/Umbraco.Core/Sync/ApplicationUrlHelper.cs
Normal file
133
src/Umbraco.Core/Sync/ApplicationUrlHelper.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Sync
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper used to determine the current server umbraco application url.
|
||||
/// </summary>
|
||||
public static class ApplicationUrlHelper
|
||||
{
|
||||
// because we cannot logger.Info<ApplicationUrlHelper> because type is static
|
||||
private static readonly Type TypeOfApplicationUrlHelper = typeof(ApplicationUrlHelper);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a custom provider for the umbraco application url.
|
||||
/// </summary>
|
||||
/// <remarks>Receives the current request as a parameter, and it may be null. Must return a properly
|
||||
/// formatted url with scheme and umbraco dir and no trailing slash eg "http://www.mysite.com/umbraco",
|
||||
/// or <c>null</c>. To be used in auto-load-balancing scenarios where the application url is not
|
||||
/// in config files but is determined programmatically.</remarks>
|
||||
public static Func<HttpRequestBase, string> ApplicationUrlProvider { get; set; }
|
||||
|
||||
// request: will be null if called from ApplicationContext
|
||||
// settings: for unit tests only
|
||||
internal static void EnsureApplicationUrl(ApplicationContext appContext, HttpRequestBase request = null, IUmbracoSettingsSection settings = null)
|
||||
{
|
||||
// if initialized, return
|
||||
if (appContext._umbracoApplicationUrl != null) return;
|
||||
|
||||
var logger = appContext.ProfilingLogger.Logger;
|
||||
|
||||
// try settings and IServerRegistrar
|
||||
if (TrySetApplicationUrl(appContext, settings ?? UmbracoConfig.For.UmbracoSettings()))
|
||||
return;
|
||||
|
||||
// try custom provider
|
||||
if (ApplicationUrlProvider != null)
|
||||
{
|
||||
var url = ApplicationUrlProvider(request);
|
||||
if (url.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
appContext._umbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (provider)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// last chance,
|
||||
// use the current request as application url
|
||||
if (request == null) return;
|
||||
SetApplicationUrlFromCurrentRequest(appContext, request);
|
||||
}
|
||||
|
||||
// internal for tests
|
||||
internal static bool TrySetApplicationUrl(ApplicationContext appContext, IUmbracoSettingsSection settings)
|
||||
{
|
||||
var logger = appContext.ProfilingLogger.Logger;
|
||||
|
||||
// try umbracoSettings:settings/web.routing/@umbracoApplicationUrl
|
||||
// which is assumed to:
|
||||
// - end with SystemDirectories.Umbraco
|
||||
// - contain a scheme
|
||||
// - end or not with a slash, it will be taken care of
|
||||
// eg "http://www.mysite.com/umbraco"
|
||||
var url = settings.WebRouting.UmbracoApplicationUrl;
|
||||
if (url.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
appContext._umbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using web.routing/@umbracoApplicationUrl)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// try umbracoSettings:settings/scheduledTasks/@baseUrl
|
||||
// which is assumed to:
|
||||
// - end with SystemDirectories.Umbraco
|
||||
// - NOT contain any scheme (because, legacy)
|
||||
// - end or not with a slash, it will be taken care of
|
||||
// eg "mysite.com/umbraco"
|
||||
url = settings.ScheduledTasks.BaseUrl;
|
||||
if (url.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
var ssl = GlobalSettings.UseSSL ? "s" : "";
|
||||
url = "http" + ssl + "://" + url;
|
||||
appContext._umbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using scheduledTasks/@baseUrl)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// try the server registrar
|
||||
// which is assumed to return a url that:
|
||||
// - end with SystemDirectories.Umbraco
|
||||
// - contain a scheme
|
||||
// - end or not with a slash, it will be taken care of
|
||||
// eg "http://www.mysite.com/umbraco"
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
url = registrar == null ? null : registrar.GetCurrentServerUmbracoApplicationUrl();
|
||||
if (url.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
appContext._umbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (IServerRegistrar)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// else give up...
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void SetApplicationUrlFromCurrentRequest(ApplicationContext appContext, HttpRequestBase request)
|
||||
{
|
||||
var logger = appContext.ProfilingLogger.Logger;
|
||||
|
||||
// if (HTTP and SSL not required) or (HTTPS and SSL required),
|
||||
// use ports from request
|
||||
// otherwise,
|
||||
// if non-standard ports used,
|
||||
// user may need to set umbracoApplicationUrl manually per
|
||||
// http://our.umbraco.org/documentation/Using-Umbraco/Config-files/umbracoSettings/#ScheduledTasks
|
||||
var port = (request.IsSecureConnection == false && GlobalSettings.UseSSL == false)
|
||||
|| (request.IsSecureConnection && GlobalSettings.UseSSL)
|
||||
? ":" + request.ServerVariables["SERVER_PORT"]
|
||||
: "";
|
||||
|
||||
var ssl = GlobalSettings.UseSSL ? "s" : ""; // force, whatever the first request
|
||||
var url = "http" + ssl + "://" + request.ServerVariables["SERVER_NAME"] + port + IOHelper.ResolveUrl(SystemDirectories.Umbraco);
|
||||
|
||||
appContext._umbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (UmbracoModule request)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Sync
|
||||
{
|
||||
@@ -9,27 +11,84 @@ namespace Umbraco.Core.Sync
|
||||
/// Provides server registrations to the distributed cache by reading the legacy Xml configuration
|
||||
/// in umbracoSettings to get the list of (manually) configured server nodes.
|
||||
/// </summary>
|
||||
internal class ConfigServerRegistrar : IServerRegistrar
|
||||
internal class ConfigServerRegistrar : IServerRegistrar2
|
||||
{
|
||||
private readonly List<IServerAddress> _addresses;
|
||||
private readonly ServerRole _serverRole;
|
||||
private readonly string _umbracoApplicationUrl;
|
||||
|
||||
public ConfigServerRegistrar()
|
||||
: this(UmbracoConfig.For.UmbracoSettings().DistributedCall.Servers)
|
||||
: this(UmbracoConfig.For.UmbracoSettings().DistributedCall)
|
||||
{ }
|
||||
|
||||
internal ConfigServerRegistrar(IEnumerable<IServer> servers)
|
||||
// for tests
|
||||
internal ConfigServerRegistrar(IDistributedCallSection settings)
|
||||
{
|
||||
_addresses = servers == null
|
||||
? new List<IServerAddress>()
|
||||
: servers
|
||||
.Select(x => new ConfigServerAddress(x))
|
||||
.Cast<IServerAddress>()
|
||||
.ToList();
|
||||
if (settings.Enabled == false)
|
||||
{
|
||||
_addresses = new List<IServerAddress>();
|
||||
_serverRole = ServerRole.Single;
|
||||
_umbracoApplicationUrl = null; // unspecified
|
||||
return;
|
||||
}
|
||||
|
||||
var serversA = settings.Servers.ToArray();
|
||||
|
||||
_addresses = serversA
|
||||
.Select(x => new ConfigServerAddress(x))
|
||||
.Cast<IServerAddress>()
|
||||
.ToList();
|
||||
|
||||
if (serversA.Length == 0)
|
||||
{
|
||||
_serverRole = ServerRole.Unknown; // config error, actually
|
||||
}
|
||||
else
|
||||
{
|
||||
var master = serversA[0]; // first one is master
|
||||
var appId = master.AppId;
|
||||
var serverName = master.ServerName;
|
||||
|
||||
if (appId.IsNullOrWhiteSpace() && serverName.IsNullOrWhiteSpace())
|
||||
_serverRole = ServerRole.Unknown; // config error, actually
|
||||
else
|
||||
_serverRole = IsCurrentServer(appId, serverName)
|
||||
? ServerRole.Master
|
||||
: ServerRole.Slave;
|
||||
}
|
||||
|
||||
var currentServer = serversA.FirstOrDefault(x => IsCurrentServer(x.AppId, x.ServerName));
|
||||
if (currentServer != null)
|
||||
{
|
||||
// match, use the configured url
|
||||
_umbracoApplicationUrl = string.Format("{0}://{1}:{2}/{3}",
|
||||
currentServer.ForceProtocol.IsNullOrWhiteSpace() ? "http" : currentServer.ForceProtocol,
|
||||
currentServer.ServerAddress,
|
||||
currentServer.ForcePortnumber.IsNullOrWhiteSpace() ? "80" : currentServer.ForcePortnumber,
|
||||
IOHelper.ResolveUrl(SystemDirectories.Umbraco).TrimStart('/'));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsCurrentServer(string appId, string serverName)
|
||||
{
|
||||
// match by appId or computer name
|
||||
return (appId.IsNullOrWhiteSpace() == false && appId.Trim().InvariantEquals(HttpRuntime.AppDomainAppId))
|
||||
|| (serverName.IsNullOrWhiteSpace() == false && serverName.Trim().InvariantEquals(NetworkHelper.MachineName));
|
||||
}
|
||||
|
||||
public IEnumerable<IServerAddress> Registrations
|
||||
{
|
||||
get { return _addresses; }
|
||||
}
|
||||
|
||||
public ServerRole GetCurrentServerRole()
|
||||
{
|
||||
return _serverRole;
|
||||
}
|
||||
|
||||
public string GetCurrentServerUmbracoApplicationUrl()
|
||||
{
|
||||
return _umbracoApplicationUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace Umbraco.Core.Sync
|
||||
{
|
||||
/// <summary>
|
||||
/// The current status of the server in the Umbraco environment
|
||||
/// </summary>
|
||||
internal enum CurrentServerEnvironmentStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// If the current server is detected as the 'master' server when configured in a load balanced scenario
|
||||
/// </summary>
|
||||
Master,
|
||||
|
||||
/// <summary>
|
||||
/// If the current server is detected as a 'slave' server when configured in a load balanced scenario
|
||||
/// </summary>
|
||||
Slave,
|
||||
|
||||
/// <summary>
|
||||
/// If the current server cannot be detected as a 'slave' or 'master' when configured in a load balanced scenario
|
||||
/// </summary>
|
||||
Unknown,
|
||||
|
||||
/// <summary>
|
||||
/// If load balancing is not enabled and this is the only server in the umbraco environment
|
||||
/// </summary>
|
||||
Single
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Sync
|
||||
/// <summary>
|
||||
/// A registrar that stores registered server nodes in the database.
|
||||
/// </summary>
|
||||
public sealed class DatabaseServerRegistrar : IServerRegistrar
|
||||
public sealed class DatabaseServerRegistrar : IServerRegistrar2
|
||||
{
|
||||
private readonly Lazy<IServerRegistrationService> _registrationService;
|
||||
|
||||
@@ -37,5 +37,24 @@ namespace Umbraco.Core.Sync
|
||||
{
|
||||
get { return _registrationService.Value.GetActiveServers(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the role of the current server in the application environment.
|
||||
/// </summary>
|
||||
public ServerRole GetCurrentServerRole()
|
||||
{
|
||||
var service = _registrationService.Value as ServerRegistrationService;
|
||||
return service.GetCurrentServerRole();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current umbraco application url.
|
||||
/// </summary>
|
||||
public string GetCurrentServerUmbracoApplicationUrl()
|
||||
{
|
||||
// this registrar does not provide the umbraco application url
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Sync
|
||||
/// </summary>
|
||||
public DatabaseServerRegistrarOptions()
|
||||
{
|
||||
StaleServerTimeout = new TimeSpan(1,0,0); // 1 day
|
||||
StaleServerTimeout = TimeSpan.FromMinutes(2); // 2 minutes
|
||||
ThrottleSeconds = 30; // 30 seconds
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@ namespace Umbraco.Core.Sync
|
||||
/// <summary>
|
||||
/// Provides server registrations to the distributed cache.
|
||||
/// </summary>
|
||||
/// <remarks>You should implement IServerRegistrar2 instead.</remarks>
|
||||
public interface IServerRegistrar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the server registrations.
|
||||
/// </summary>
|
||||
IEnumerable<IServerAddress> Registrations { get; }
|
||||
IEnumerable<IServerAddress> Registrations { get; }
|
||||
}
|
||||
}
|
||||
26
src/Umbraco.Core/Sync/IServerRegistrar2.cs
Normal file
26
src/Umbraco.Core/Sync/IServerRegistrar2.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace Umbraco.Core.Sync
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides server registrations to the distributed cache.
|
||||
/// </summary>
|
||||
/// <remarks>This interface exists because IServerRegistrar could not be modified
|
||||
/// for backward compatibility reasons - but IServerRegistrar is broken because it
|
||||
/// does not support server role management. So ppl should really implement
|
||||
/// IServerRegistrar2, and the two interfaces will get merged in v8.</remarks>
|
||||
public interface IServerRegistrar2 : IServerRegistrar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the role of the current server in the application environment.
|
||||
/// </summary>
|
||||
ServerRole GetCurrentServerRole();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current umbraco application url.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>If the registrar does not provide the umbraco application url, should return null.</para>
|
||||
/// <para>Must return null, or a url that ends with SystemDirectories.Umbraco, and contains a scheme, eg "http://www.mysite.com/umbraco".</para>
|
||||
/// </remarks>
|
||||
string GetCurrentServerUmbracoApplicationUrl();
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Sync
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper used to determine the current server environment status
|
||||
/// </summary>
|
||||
internal static class ServerEnvironmentHelper
|
||||
{
|
||||
public static void TrySetApplicationUrlFromSettings(ApplicationContext appContext, ILogger logger, IUmbracoSettingsSection settings)
|
||||
{
|
||||
// try umbracoSettings:settings/web.routing/@umbracoApplicationUrl
|
||||
// which is assumed to:
|
||||
// - end with SystemDirectories.Umbraco
|
||||
// - contain a scheme
|
||||
// - end or not with a slash, it will be taken care of
|
||||
// eg "http://www.mysite.com/umbraco"
|
||||
var url = settings.WebRouting.UmbracoApplicationUrl;
|
||||
if (url.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
appContext.UmbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info<ApplicationContext>("ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using web.routing/@umbracoApplicationUrl)");
|
||||
return;
|
||||
}
|
||||
|
||||
// try umbracoSettings:settings/scheduledTasks/@baseUrl
|
||||
// which is assumed to:
|
||||
// - end with SystemDirectories.Umbraco
|
||||
// - NOT contain any scheme (because, legacy)
|
||||
// - end or not with a slash, it will be taken care of
|
||||
// eg "mysite.com/umbraco"
|
||||
url = settings.ScheduledTasks.BaseUrl;
|
||||
if (url.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
var ssl = GlobalSettings.UseSSL ? "s" : "";
|
||||
url = "http" + ssl + "://" + url;
|
||||
appContext.UmbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info<ApplicationContext>("ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using scheduledTasks/@baseUrl)");
|
||||
return;
|
||||
}
|
||||
|
||||
// try servers
|
||||
var status = GetStatus(settings);
|
||||
if (status == CurrentServerEnvironmentStatus.Single)
|
||||
return;
|
||||
|
||||
// no server, nothing we can do
|
||||
var servers = settings.DistributedCall.Servers.ToArray();
|
||||
if (servers.Length == 0)
|
||||
return;
|
||||
|
||||
// we have servers, look for this server
|
||||
foreach (var server in servers)
|
||||
{
|
||||
var appId = server.AppId;
|
||||
var serverName = server.ServerName;
|
||||
|
||||
// skip if no data
|
||||
if (appId.IsNullOrWhiteSpace() && serverName.IsNullOrWhiteSpace())
|
||||
continue;
|
||||
|
||||
// if this server, build and return the url
|
||||
if ((appId.IsNullOrWhiteSpace() == false && appId.Trim().InvariantEquals(HttpRuntime.AppDomainAppId))
|
||||
|| (serverName.IsNullOrWhiteSpace() == false && serverName.Trim().InvariantEquals(NetworkHelper.MachineName)))
|
||||
{
|
||||
// match by appId or computer name, return the url configured
|
||||
url = string.Format("{0}://{1}:{2}/{3}",
|
||||
server.ForceProtocol.IsNullOrWhiteSpace() ? "http" : server.ForceProtocol,
|
||||
server.ServerAddress,
|
||||
server.ForcePortnumber.IsNullOrWhiteSpace() ? "80" : server.ForcePortnumber,
|
||||
IOHelper.ResolveUrl(SystemDirectories.Umbraco).TrimStart('/'));
|
||||
|
||||
appContext.UmbracoApplicationUrl = url.TrimEnd('/');
|
||||
logger.Info<ApplicationContext>("ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using distributedCall/servers)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current environment status for the current server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static CurrentServerEnvironmentStatus GetStatus(IUmbracoSettingsSection settings)
|
||||
{
|
||||
if (settings.DistributedCall.Enabled == false)
|
||||
{
|
||||
return CurrentServerEnvironmentStatus.Single;
|
||||
}
|
||||
|
||||
var servers = settings.DistributedCall.Servers.ToArray();
|
||||
|
||||
if (servers.Any() == false)
|
||||
{
|
||||
return CurrentServerEnvironmentStatus.Unknown;
|
||||
}
|
||||
|
||||
var master = servers.FirstOrDefault();
|
||||
|
||||
if (master == null)
|
||||
{
|
||||
return CurrentServerEnvironmentStatus.Unknown;
|
||||
}
|
||||
|
||||
//we determine master/slave based on the first server registered
|
||||
//TODO: In v7 we have publicized ServerRegisterResolver - we won't be able to determine this based on that
|
||||
// but we'd need to change the IServerAddress interfaces which is breaking.
|
||||
|
||||
var appId = master.AppId;
|
||||
var serverName = master.ServerName;
|
||||
|
||||
if (appId.IsNullOrWhiteSpace() && serverName.IsNullOrWhiteSpace())
|
||||
{
|
||||
return CurrentServerEnvironmentStatus.Unknown;
|
||||
}
|
||||
|
||||
if ((appId.IsNullOrWhiteSpace() == false && appId.Trim().InvariantEquals(HttpRuntime.AppDomainAppId))
|
||||
|| (serverName.IsNullOrWhiteSpace() == false && serverName.Trim().InvariantEquals(NetworkHelper.MachineName)))
|
||||
{
|
||||
//match by appdid or server name!
|
||||
return CurrentServerEnvironmentStatus.Master;
|
||||
}
|
||||
|
||||
return CurrentServerEnvironmentStatus.Slave;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/Umbraco.Core/Sync/ServerRole.cs
Normal file
28
src/Umbraco.Core/Sync/ServerRole.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace Umbraco.Core.Sync
|
||||
{
|
||||
/// <summary>
|
||||
/// The role of a server in an application environment.
|
||||
/// </summary>
|
||||
public enum ServerRole : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// The server role is unknown.
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The server is the single server of a single-server environment.
|
||||
/// </summary>
|
||||
Single = 1,
|
||||
|
||||
/// <summary>
|
||||
/// In a multi-servers environment, the server is a slave server.
|
||||
/// </summary>
|
||||
Slave = 2,
|
||||
|
||||
/// <summary>
|
||||
/// In a multi-servers environment, the server is the master server.
|
||||
/// </summary>
|
||||
Master = 3
|
||||
}
|
||||
}
|
||||
@@ -401,6 +401,7 @@
|
||||
<Compile Include="Persistence\Mappers\MigrationEntryMapper.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddExternalLoginsTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddForeignKeysForLanguageAndDictionaryTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddServerRegistrationColumnsAndLock.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddMigrationTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddPublicAccessTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddUniqueIdPropertyTypeColumn.cs" />
|
||||
@@ -1257,13 +1258,14 @@
|
||||
<Compile Include="Strings\ContentBaseExtensions.cs" />
|
||||
<Compile Include="Strings\Diff.cs" />
|
||||
<Compile Include="Sync\BatchedWebServiceServerMessenger.cs" />
|
||||
<Compile Include="Sync\CurrentServerEnvironmentStatus.cs" />
|
||||
<Compile Include="Sync\IServerRegistrar2.cs" />
|
||||
<Compile Include="Sync\ServerRole.cs" />
|
||||
<Compile Include="Sync\DatabaseServerMessenger.cs" />
|
||||
<Compile Include="Sync\DatabaseServerMessengerOptions.cs" />
|
||||
<Compile Include="Sync\DatabaseServerRegistrarOptions.cs" />
|
||||
<Compile Include="Sync\RefreshInstruction.cs" />
|
||||
<Compile Include="Sync\RefreshInstructionEnvelope.cs" />
|
||||
<Compile Include="Sync\ServerEnvironmentHelper.cs" />
|
||||
<Compile Include="Sync\ApplicationUrlHelper.cs" />
|
||||
<Compile Include="Sync\RefreshMethodType.cs" />
|
||||
<Compile Include="Sync\ServerMessengerBase.cs" />
|
||||
<Compile Include="TopologicalSorter.cs" />
|
||||
|
||||
303
src/Umbraco.Tests/ApplicationUrlHelperTests.cs
Normal file
303
src/Umbraco.Tests/ApplicationUrlHelperTests.cs
Normal file
@@ -0,0 +1,303 @@
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ApplicationUrlHelperTests
|
||||
{
|
||||
private ILogger _logger;
|
||||
|
||||
// note: in tests, read appContext._umbracoApplicationUrl and not the property,
|
||||
// because reading the property does run some code, as long as the field is null.
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitializeFixture()
|
||||
{
|
||||
_logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config")));
|
||||
}
|
||||
|
||||
private static void Initialize(IUmbracoSettingsSection settings)
|
||||
{
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new ConfigServerRegistrar(settings.DistributedCall));
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Reset()
|
||||
{
|
||||
ServerRegistrarResolver.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoApplicationUrlByDefault()
|
||||
{
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
Assert.IsNull(appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlViaProvider()
|
||||
{
|
||||
// no applicable settings, but a provider
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>());
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here
|
||||
|
||||
ApplicationUrlHelper.ApplicationUrlProvider = request => "http://server1.com/umbraco";
|
||||
ApplicationUrlHelper.EnsureApplicationUrl(appCtx, settings: settings);
|
||||
|
||||
Assert.AreEqual("http://server1.com/umbraco", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlWhenNoSettings()
|
||||
{
|
||||
// no applicable settings, cannot set url
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string) null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>());
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
// still NOT set
|
||||
Assert.IsNull(appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromDcSettingsSsl1()
|
||||
{
|
||||
// set from distributed call settings
|
||||
// first server is master server
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
|
||||
{
|
||||
Mock.Of<IServer>(server => server.ServerName == NetworkHelper.MachineName && server.ServerAddress == "server1.com"),
|
||||
Mock.Of<IServer>(server => server.ServerName == "ANOTHERNAME" && server.ServerAddress == "server2.com"),
|
||||
})
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == (string)null));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
Assert.AreEqual("http://server1.com:80/umbraco", appCtx._umbracoApplicationUrl);
|
||||
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
var role = registrar.GetCurrentServerRole();
|
||||
Assert.AreEqual(ServerRole.Master, role);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromDcSettingsSsl2()
|
||||
{
|
||||
// set from distributed call settings
|
||||
// other servers are slave servers
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
|
||||
{
|
||||
Mock.Of<IServer>(server => server.ServerName == "ANOTHERNAME" && server.ServerAddress == "server2.com"),
|
||||
Mock.Of<IServer>(server => server.ServerName == NetworkHelper.MachineName && server.ServerAddress == "server1.com"),
|
||||
})
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == (string)null));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
Assert.AreEqual("http://server1.com:80/umbraco", appCtx._umbracoApplicationUrl);
|
||||
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
var role = registrar.GetCurrentServerRole();
|
||||
Assert.AreEqual(ServerRole.Slave, role);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromDcSettingsSsl3()
|
||||
{
|
||||
// set from distributed call settings
|
||||
// cannot set if not enabled
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == false && callSection.Servers == new IServer[]
|
||||
{
|
||||
Mock.Of<IServer>(server => server.ServerName == "ANOTHERNAME" && server.ServerAddress == "server2.com"),
|
||||
Mock.Of<IServer>(server => server.ServerName == NetworkHelper.MachineName && server.ServerAddress == "server1.com"),
|
||||
})
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == (string)null));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
Assert.IsNull(appCtx._umbracoApplicationUrl);
|
||||
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
var role = registrar.GetCurrentServerRole();
|
||||
Assert.AreEqual(ServerRole.Single, role);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServerRoleSingle()
|
||||
{
|
||||
// distributed call settings disabled, single server
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == false && callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == (string)null));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
var role = registrar.GetCurrentServerRole();
|
||||
Assert.AreEqual(ServerRole.Single, role);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServerRoleUnknown1()
|
||||
{
|
||||
// distributed call enabled but missing servers, unknown server
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == (string)null));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
var role = registrar.GetCurrentServerRole();
|
||||
Assert.AreEqual(ServerRole.Unknown, role);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServerRoleUnknown2()
|
||||
{
|
||||
// distributed call enabled, cannot find server, assume it's an undeclared slave
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
|
||||
{
|
||||
Mock.Of<IServer>(server => server.ServerName == "ANOTHERNAME" && server.ServerAddress == "server2.com"),
|
||||
})
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string)null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == (string)null));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
var role = registrar.GetCurrentServerRole();
|
||||
Assert.AreEqual(ServerRole.Slave, role);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromStSettingsNoSsl()
|
||||
{
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string) null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/umbraco"));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false");
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
Assert.AreEqual("http://mycoolhost.com/umbraco", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromStSettingsSsl()
|
||||
{
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string) null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/umbraco/"));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
Assert.AreEqual("https://mycoolhost.com/umbraco", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromWrSettingsSsl()
|
||||
{
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == "httpx://whatever.com/umbraco/")
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/umbraco"));
|
||||
|
||||
Initialize(settings);
|
||||
|
||||
var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here
|
||||
|
||||
ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings);
|
||||
|
||||
Assert.AreEqual("httpx://whatever.com/umbraco", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ServerEnvironmentHelperTests
|
||||
{
|
||||
private ILogger _logger;
|
||||
|
||||
// note: in tests, read appContext._umbracoApplicationUrl and not the property,
|
||||
// because reading the property does run some code, as long as the field is null.
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitializeFixture()
|
||||
{
|
||||
_logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlWhenNoSettings()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()))
|
||||
{
|
||||
UmbracoApplicationUrl = null // NOT set
|
||||
};
|
||||
|
||||
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here
|
||||
|
||||
ServerEnvironmentHelper.TrySetApplicationUrlFromSettings(appCtx, _logger,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string) null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>()));
|
||||
|
||||
|
||||
// still NOT set
|
||||
Assert.IsNull(appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromDcSettingsNoSsl()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false");
|
||||
|
||||
ServerEnvironmentHelper.TrySetApplicationUrlFromSettings(appCtx, _logger,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string) null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world/")));
|
||||
|
||||
|
||||
Assert.AreEqual("http://mycoolhost.com/hello/world", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromDcSettingsSsl()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
ServerEnvironmentHelper.TrySetApplicationUrlFromSettings(appCtx, _logger,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == (string) null)
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world")));
|
||||
|
||||
|
||||
Assert.AreEqual("https://mycoolhost.com/hello/world", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetApplicationUrlFromWrSettingsSsl()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here
|
||||
|
||||
ServerEnvironmentHelper.TrySetApplicationUrlFromSettings(appCtx, _logger,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.WebRouting == Mock.Of<IWebRoutingSection>(wrSection => wrSection.UmbracoApplicationUrl == "httpx://whatever.com/hello/world/")
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world")));
|
||||
|
||||
|
||||
Assert.AreEqual("httpx://whatever.com/hello/world", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@
|
||||
<Compile Include="PublishedContent\StronglyTypedModels\TypedModelBase.cs" />
|
||||
<Compile Include="PublishedContent\StronglyTypedModels\UmbracoTemplatePage`T.cs" />
|
||||
<Compile Include="Scheduling\BackgroundTaskRunnerTests.cs" />
|
||||
<Compile Include="ServerEnvironmentHelperTests.cs" />
|
||||
<Compile Include="ApplicationUrlHelperTests.cs" />
|
||||
<Compile Include="Services\FileServiceTests.cs" />
|
||||
<Compile Include="Services\LocalizedTextServiceTests.cs" />
|
||||
<Compile Include="Services\TagServiceTests.cs" />
|
||||
|
||||
@@ -60,10 +60,14 @@ namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
if (_appContext == null) return true; // repeat...
|
||||
|
||||
if (ServerEnvironmentHelper.GetStatus(_settings) == CurrentServerEnvironmentStatus.Slave)
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
LogHelper.Debug<LogScrubber>("Does not run on slave servers.");
|
||||
return false; // do NOT repeat, server status comes from config and will NOT change
|
||||
case ServerRole.Slave:
|
||||
LogHelper.Debug<LogScrubber>("Does not run on slave servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
LogHelper.Debug<LogScrubber>("Does not run on servers with unknown role.");
|
||||
return true; // DO repeat, server role can change
|
||||
}
|
||||
|
||||
// ensure we do not run if not main domain, but do NOT lock it
|
||||
|
||||
@@ -32,10 +32,14 @@ namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
if (_appContext == null) return true; // repeat...
|
||||
|
||||
if (ServerEnvironmentHelper.GetStatus(_settings) == CurrentServerEnvironmentStatus.Slave)
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
LogHelper.Debug<ScheduledPublishing>("Does not run on slave servers.");
|
||||
return false; // do NOT repeat, server status comes from config and will NOT change
|
||||
case ServerRole.Slave:
|
||||
LogHelper.Debug<ScheduledPublishing>("Does not run on slave servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
LogHelper.Debug<ScheduledPublishing>("Does not run on servers with unknown role.");
|
||||
return true; // DO repeat, server role can change
|
||||
}
|
||||
|
||||
// ensure we do not run if not main domain, but do NOT lock it
|
||||
|
||||
@@ -90,10 +90,14 @@ namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
if (_appContext == null) return true; // repeat...
|
||||
|
||||
if (ServerEnvironmentHelper.GetStatus(_settings) == CurrentServerEnvironmentStatus.Slave)
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
LogHelper.Debug<ScheduledTasks>("Does not run on slave servers.");
|
||||
return false; // do NOT repeat, server status comes from config and will NOT change
|
||||
case ServerRole.Slave:
|
||||
LogHelper.Debug<ScheduledTasks>("Does not run on slave servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
LogHelper.Debug<ScheduledTasks>("Does not run on servers with unknown role.");
|
||||
return true; // DO repeat, server role can change
|
||||
}
|
||||
|
||||
// ensure we do not run if not main domain, but do NOT lock it
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
@@ -21,18 +22,23 @@ namespace Umbraco.Web.Strategies
|
||||
/// </remarks>
|
||||
public sealed class ServerRegistrationEventHandler : ApplicationEventHandler
|
||||
{
|
||||
private static DateTime _lastUpdated = DateTime.MinValue;
|
||||
private readonly object _locko = new object();
|
||||
private DatabaseServerRegistrar _registrar;
|
||||
private DateTime _lastUpdated = DateTime.MinValue;
|
||||
|
||||
// bind to events
|
||||
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
|
||||
{
|
||||
_registrar = ServerRegistrarResolver.Current.Registrar as DatabaseServerRegistrar;
|
||||
|
||||
// only for the DatabaseServerRegistrar
|
||||
if (ServerRegistrarResolver.Current.Registrar is DatabaseServerRegistrar)
|
||||
UmbracoModule.RouteAttempt += UmbracoModuleRouteAttempt;
|
||||
if (_registrar == null) return;
|
||||
|
||||
UmbracoModule.RouteAttempt += UmbracoModuleRouteAttempt;
|
||||
}
|
||||
|
||||
// handles route attempts.
|
||||
private static void UmbracoModuleRouteAttempt(object sender, RoutableAttemptEventArgs e)
|
||||
private void UmbracoModuleRouteAttempt(object sender, RoutableAttemptEventArgs e)
|
||||
{
|
||||
if (e.HttpContext.Request == null || e.HttpContext.Request.Url == null) return;
|
||||
|
||||
@@ -60,31 +66,26 @@ namespace Umbraco.Web.Strategies
|
||||
}
|
||||
|
||||
// register current server (throttled).
|
||||
private static void RegisterServer(UmbracoRequestEventArgs e)
|
||||
private void RegisterServer(UmbracoRequestEventArgs e)
|
||||
{
|
||||
var reg = (DatabaseServerRegistrar) ServerRegistrarResolver.Current.Registrar;
|
||||
var options = reg.Options;
|
||||
var secondsSinceLastUpdate = DateTime.Now.Subtract(_lastUpdated).TotalSeconds;
|
||||
if (secondsSinceLastUpdate < options.ThrottleSeconds) return;
|
||||
lock (_locko) // ensure we trigger only once
|
||||
{
|
||||
var secondsSinceLastUpdate = DateTime.Now.Subtract(_lastUpdated).TotalSeconds;
|
||||
if (secondsSinceLastUpdate < _registrar.Options.ThrottleSeconds) return;
|
||||
_lastUpdated = DateTime.Now;
|
||||
}
|
||||
|
||||
_lastUpdated = DateTime.Now;
|
||||
var svc = e.UmbracoContext.Application.Services.ServerRegistrationService as ServerRegistrationService;
|
||||
|
||||
var url = e.HttpContext.Request.Url;
|
||||
var svc = e.UmbracoContext.Application.Services.ServerRegistrationService;
|
||||
// because
|
||||
// - ApplicationContext.UmbracoApplicationUrl is initialized by UmbracoModule in BeginRequest
|
||||
// - RegisterServer is called on UmbracoModule.RouteAttempt which is triggered in ProcessRequest
|
||||
// we are safe, UmbracoApplicationUrl has been initialized
|
||||
var serverAddress = e.UmbracoContext.Application.UmbracoApplicationUrl;
|
||||
|
||||
try
|
||||
{
|
||||
if (url == null)
|
||||
throw new Exception("Request.Url is null.");
|
||||
|
||||
var serverAddress = url.GetLeftPart(UriPartial.Authority);
|
||||
var serverIdentity = JsonConvert.SerializeObject(new
|
||||
{
|
||||
machineName = NetworkHelper.MachineName,
|
||||
appDomainAppId = HttpRuntime.AppDomainAppId
|
||||
});
|
||||
|
||||
svc.TouchServer(serverAddress, serverIdentity, options.StaleServerTimeout);
|
||||
svc.TouchServer(serverAddress, svc.CurrentServerIdentity, _registrar.Options.StaleServerTimeout);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using umbraco;
|
||||
using Umbraco.Core.Sync;
|
||||
using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;
|
||||
using ObjectExtensions = Umbraco.Core.ObjectExtensions;
|
||||
using RenderingEngine = Umbraco.Core.RenderingEngine;
|
||||
@@ -36,36 +37,6 @@ namespace Umbraco.Web
|
||||
{
|
||||
#region HttpModule event handlers
|
||||
|
||||
private static void EnsureApplicationUrl(HttpRequestBase request)
|
||||
{
|
||||
var appctx = ApplicationContext.Current;
|
||||
|
||||
// already initialized = ok
|
||||
// note that getting ApplicationUrl will ALSO try the various settings
|
||||
if (appctx.UmbracoApplicationUrl.IsNullOrWhiteSpace() == false) return;
|
||||
|
||||
// so if we reach that point, nothing was configured
|
||||
// use the current request as application url
|
||||
|
||||
// if (HTTP and SSL not required) or (HTTPS and SSL required),
|
||||
// use ports from request
|
||||
// otherwise,
|
||||
// if non-standard ports used,
|
||||
// user may need to set umbracoApplicationUrl manually per
|
||||
// http://our.umbraco.org/documentation/Using-Umbraco/Config-files/umbracoSettings/#ScheduledTasks
|
||||
var port = (request.IsSecureConnection == false && GlobalSettings.UseSSL == false)
|
||||
|| (request.IsSecureConnection && GlobalSettings.UseSSL)
|
||||
? ":" + request.ServerVariables["SERVER_PORT"]
|
||||
: "";
|
||||
|
||||
var ssl = GlobalSettings.UseSSL ? "s" : ""; // force, whatever the first request
|
||||
var url = "http" + ssl + "://" + request.ServerVariables["SERVER_NAME"] + port + IOHelper.ResolveUrl(SystemDirectories.Umbraco);
|
||||
|
||||
appctx.UmbracoApplicationUrl = UriUtility.TrimPathEndSlash(url);
|
||||
LogHelper.Info<ApplicationContext>("ApplicationUrl: " + appctx.UmbracoApplicationUrl + " (UmbracoModule request)");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Begins to process a request.
|
||||
/// </summary>
|
||||
@@ -73,7 +44,7 @@ namespace Umbraco.Web
|
||||
static void BeginRequest(HttpContextBase httpContext)
|
||||
{
|
||||
// ensure application url is initialized
|
||||
EnsureApplicationUrl(httpContext.Request);
|
||||
ApplicationUrlHelper.EnsureApplicationUrl(ApplicationContext.Current, httpContext.Request);
|
||||
|
||||
// do not process if client-side request
|
||||
if (httpContext.Request.Url.IsClientSideRequest())
|
||||
|
||||
Reference in New Issue
Block a user