Merge remote-tracking branch 'origin/netcore/netcore' into netcore/netcore
This commit is contained in:
@@ -86,7 +86,7 @@ namespace Umbraco.Examine
|
||||
|| !validator.ValidateProtectedContent(path, v.Category))
|
||||
? 0
|
||||
: 1;
|
||||
});
|
||||
}).ToList();
|
||||
|
||||
var hasDeletes = false;
|
||||
var hasUpdates = false;
|
||||
@@ -105,7 +105,7 @@ namespace Umbraco.Examine
|
||||
{
|
||||
hasUpdates = true;
|
||||
//these are the valid ones, so just index them all at once
|
||||
base.PerformIndexItems(group, onComplete);
|
||||
base.PerformIndexItems(group.ToList(), onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -583,6 +583,26 @@ namespace Umbraco.Web.Search
|
||||
|
||||
public static void Execute(ExamineComponent examineComponent, IContent content, bool isPublished)
|
||||
{
|
||||
// TODO: This is ugly, it is going to build the value set 3x and for 2 of those times it will be the same value
|
||||
// set. We can do better.
|
||||
|
||||
// TODO: We are .ToList() ing each of the calls to GetValueSets here. This is currently required but isn't the way
|
||||
// that this was intended to work. Ideally, the IEnumerable package gets passed to Examine and it is only iterated/executed
|
||||
// when the indexing takes place which would occur on a background thread. This is problematic with how the ContentValueSetBuilder
|
||||
// in combination with UmbracoContentIndex.PerformIndexItems works because (at least what I've come to believe) we are using yield
|
||||
// return in the GetValueSets call in combination with trying to lazily resolve the enumerable but because we GroupBy in
|
||||
// UmbracoContentIndex.PerformIndexItems it's eagerly executed but then lazily executed again on the background thread and I believe
|
||||
// that in doing this when the call is made to _userService.GetProfilesById it's trying to resolve a scope from an AsyncLocal instance
|
||||
// that has already been disposed higher up it's chain. I 'think' to how the eager/lazy enumeration happens with yield return that it's
|
||||
// capturing a scope/AsyncLocal instance that it shouldn't really be using.
|
||||
|
||||
// TODO: We don't want these value sets to be eagerly built in this thread since this is most likely going to be a request thread.
|
||||
// This is why the lazy execution of the Enumerable had the intended affect of executing only when requested on the background thread.
|
||||
// This could still be acheived: Either we have a custom Enumerable/Enumerator to do this, or we simply call the below code
|
||||
// on a background thread... which would be much easier!
|
||||
|
||||
// TODO: I think this is an issue in v8 too!
|
||||
|
||||
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndex>()
|
||||
//filter the indexers
|
||||
.Where(x => isPublished || !x.PublishedValuesOnly)
|
||||
@@ -593,7 +613,7 @@ namespace Umbraco.Web.Search
|
||||
? examineComponent._publishedContentValueSetBuilder
|
||||
: (IValueSetBuilder<IContent>)examineComponent._contentValueSetBuilder;
|
||||
|
||||
index.IndexItems(builder.GetValueSets(content));
|
||||
index.IndexItems(builder.GetValueSets(content).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -16,7 +16,6 @@ using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Services.Implement
|
||||
{
|
||||
@@ -29,15 +28,17 @@ namespace Umbraco.Core.Services.Implement
|
||||
private readonly INotificationsRepository _notificationsRepository;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IContentSettings _contentSettings;
|
||||
private readonly IEmailSender _emailSender;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IIOHelper _ioHelper;
|
||||
|
||||
public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, ILocalizationService localizationService,
|
||||
ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, IContentSettings contentSettings)
|
||||
ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, IContentSettings contentSettings, IEmailSender emailSender)
|
||||
{
|
||||
_notificationsRepository = notificationsRepository;
|
||||
_globalSettings = globalSettings;
|
||||
_contentSettings = contentSettings;
|
||||
_emailSender = emailSender;
|
||||
_uowProvider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
|
||||
_contentService = contentService ?? throw new ArgumentNullException(nameof(contentService));
|
||||
@@ -405,8 +406,9 @@ namespace Umbraco.Core.Services.Implement
|
||||
string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath)),
|
||||
summary.ToString());
|
||||
|
||||
var fromMail = _contentSettings.NotificationEmailAddress ?? _globalSettings.SmtpSettings.From;
|
||||
// create the mail message
|
||||
var mail = new MailMessage(_contentSettings.NotificationEmailAddress, mailingUser.Email);
|
||||
var mail = new MailMessage(fromMail, mailingUser.Email);
|
||||
|
||||
// populate the message
|
||||
|
||||
@@ -508,51 +510,38 @@ namespace Umbraco.Core.Services.Implement
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
var s = new SmtpClient();
|
||||
try
|
||||
_logger.Debug<NotificationService>("Begin processing notifications.");
|
||||
while (true)
|
||||
{
|
||||
_logger.Debug<NotificationService>("Begin processing notifications.");
|
||||
while (true)
|
||||
NotificationRequest request;
|
||||
while (notificationRequests.TryTake(out request, 8 * 1000)) // stay on for 8s
|
||||
{
|
||||
NotificationRequest request;
|
||||
while (notificationRequests.TryTake(out request, 8 * 1000)) // stay on for 8s
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Sendmail != null) Sendmail(s, request.Mail, _logger); else s.Send(request.Mail);
|
||||
_logger.Debug<NotificationService>("Notification '{Action}' sent to {Username} ({Email})", request.Action, request.UserName, request.Email);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<NotificationService>(ex, "An error occurred sending notification");
|
||||
s.Dispose();
|
||||
s = new SmtpClient();
|
||||
}
|
||||
finally
|
||||
{
|
||||
request.Mail.Dispose();
|
||||
}
|
||||
_emailSender.SendAsync(request.Mail).GetAwaiter().GetResult();
|
||||
_logger.Debug<NotificationService>("Notification '{Action}' sent to {Username} ({Email})", request.Action, request.UserName, request.Email);
|
||||
}
|
||||
lock (Locker)
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (notificationRequests.Count > 0) continue; // last chance
|
||||
_running = false; // going down
|
||||
break;
|
||||
_logger.Error<NotificationService>(ex, "An error occurred sending notification");
|
||||
}
|
||||
finally
|
||||
{
|
||||
request.Mail.Dispose();
|
||||
}
|
||||
}
|
||||
lock (Locker)
|
||||
{
|
||||
if (notificationRequests.Count > 0) continue; // last chance
|
||||
_running = false; // going down
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
s.Dispose();
|
||||
}
|
||||
|
||||
_logger.Debug<NotificationService>("Done processing notifications.");
|
||||
});
|
||||
}
|
||||
|
||||
// for tests
|
||||
internal static Action<SmtpClient, MailMessage, ILogger> Sendmail;
|
||||
//= (_, msg, logger) => logger.Debug<NotificationService>("Email " + msg.To.ToString());
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,13 @@ namespace Umbraco.Core.Sync
|
||||
_lastPruned = _lastSync = DateTime.UtcNow;
|
||||
_syncIdle = new ManualResetEvent(true);
|
||||
_distCacheFilePath = new Lazy<string>(() => GetDistCacheFilePath(hostingEnvironment));
|
||||
|
||||
// See notes on LocalIdentity
|
||||
LocalIdentity = NetworkHelper.MachineName // eg DOMAIN\SERVER
|
||||
+ "/" + _hostingEnvironment.ApplicationId // eg /LM/S3SVC/11/ROOT
|
||||
+ " [P" + Process.GetCurrentProcess().Id // eg 1234
|
||||
+ "/D" + AppDomain.CurrentDomain.Id // eg 22
|
||||
+ "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique
|
||||
}
|
||||
|
||||
protected ILogger Logger { get; }
|
||||
@@ -526,11 +533,7 @@ namespace Umbraco.Core.Sync
|
||||
/// <para>Practically, all we really need is the guid, the other infos are here for information
|
||||
/// and debugging purposes.</para>
|
||||
/// </remarks>
|
||||
protected string LocalIdentity => NetworkHelper.MachineName // eg DOMAIN\SERVER
|
||||
+ "/" + _hostingEnvironment.ApplicationId // eg /LM/S3SVC/11/ROOT
|
||||
+ " [P" + Process.GetCurrentProcess().Id // eg 1234
|
||||
+ "/D" + AppDomain.CurrentDomain.Id // eg 22
|
||||
+ "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique
|
||||
protected string LocalIdentity { get; }
|
||||
|
||||
private string GetDistCacheFilePath(IHostingEnvironment hostingEnvironment)
|
||||
{
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
public static class TestHelper
|
||||
{
|
||||
private static readonly TestHelperInternal _testHelperInternal = new TestHelperInternal();
|
||||
private static IEmailSender _emailSender;
|
||||
|
||||
private class TestHelperInternal : TestHelperBase
|
||||
{
|
||||
public TestHelperInternal() : base(typeof(TestHelperInternal).Assembly)
|
||||
@@ -103,6 +105,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
|
||||
public static IWebRoutingSettings WebRoutingSettings => _testHelperInternal.WebRoutingSettings;
|
||||
|
||||
public static IEmailSender EmailSender { get; } = new EmailSender(SettingsForTests.GenerateMockGlobalSettings());
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Some test files are copied to the /bin (/bin/debug) on build, this is a utility to return their physical path based on a virtual path name
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
var dataTypeService = GetLazyService<IDataTypeService>(factory, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo<IDataTypeRepository>(c), GetRepo<IDataTypeContainerRepository>(c), GetRepo<IAuditRepository>(c), GetRepo<IEntityRepository>(c), GetRepo<IContentTypeRepository>(c), ioHelper, localizedTextService.Value, localizationService.Value, TestHelper.ShortStringHelper));
|
||||
var propertyValidationService = new Lazy<IPropertyValidationService>(() => new PropertyValidationService(propertyEditorCollection, dataTypeService.Value, localizedTextService.Value));
|
||||
var contentService = GetLazyService<IContentService>(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo<IDocumentRepository>(c), GetRepo<IEntityRepository>(c), GetRepo<IAuditRepository>(c), GetRepo<IContentTypeRepository>(c), GetRepo<IDocumentBlueprintRepository>(c), GetRepo<ILanguageRepository>(c), propertyValidationService, TestHelper.ShortStringHelper));
|
||||
var notificationService = GetLazyService<INotificationService>(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, ioHelper, GetRepo<INotificationsRepository>(c), globalSettings, contentSettings));
|
||||
var notificationService = GetLazyService<INotificationService>(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, ioHelper, GetRepo<INotificationsRepository>(c), globalSettings, contentSettings, TestHelper.EmailSender));
|
||||
var serverRegistrationService = GetLazyService<IServerRegistrationService>(factory, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo<IServerRegistrationRepository>(c), TestHelper.GetHostingEnvironment()));
|
||||
var memberGroupService = GetLazyService<IMemberGroupService>(factory, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo<IMemberGroupRepository>(c)));
|
||||
var memberService = GetLazyService<IMemberService>(factory, c => new MemberService(scopeProvider, logger, eventMessagesFactory, memberGroupService.Value, GetRepo<IMemberRepository>(c), GetRepo<IMemberTypeRepository>(c), GetRepo<IMemberGroupRepository>(c), GetRepo<IAuditRepository>(c)));
|
||||
|
||||
Reference in New Issue
Block a user