Skip to content

Commit

Permalink
Initialize important services before unattended installs (#17366)
Browse files Browse the repository at this point in the history
* Added new notification to hook in after the premigrations and use this to init different services.

* Force MaxDegreeOfParallelism to 1, while investigating scopes

* Tried some more workarounds

* Updated scopes and changed parallel to non parallel to ensure migration works

* Missing scope

* Make it parallel again - The secret is, the SuppressFlow needs to be when you create the task, but not on the await!.

* Fixed issue when DEBUG_SCOPES is not added to tests.

* Remove test exception

* Try build on ubuntu again, even that we know it can be stuck. Just a test to see if all tests pass

* Updated comment

---------

Co-authored-by: kjac <[email protected]>
  • Loading branch information
bergmania and kjac authored Oct 28, 2024
1 parent 5cc0a35 commit 935c3b8
Show file tree
Hide file tree
Showing 35 changed files with 299 additions and 224 deletions.
2 changes: 1 addition & 1 deletion build/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ stages:
- job: A
displayName: Build Umbraco CMS
pool:
vmImage: 'windows-latest'
vmImage: 'ubuntu-latest'
steps:
- checkout: self
submodules: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,45 @@ namespace Umbraco.Cms.Persistence.EFCore.Scoping;

public class AmbientEFCoreScopeStack<TDbContext> : IAmbientEFCoreScopeStack<TDbContext> where TDbContext : DbContext
{

private static Lock _lock = new();
private static AsyncLocal<ConcurrentStack<IEfCoreScope<TDbContext>>> _stack = new();

public IEfCoreScope<TDbContext>? AmbientScope
{
get
{
if (_stack.Value?.TryPeek(out IEfCoreScope<TDbContext>? ambientScope) ?? false)
lock (_lock)
{
return ambientScope;
}
if (_stack.Value?.TryPeek(out IEfCoreScope<TDbContext>? ambientScope) ?? false)
{
return ambientScope;
}

return null;
return null;
}
}
}

public IEfCoreScope<TDbContext> Pop()
{
if (_stack.Value?.TryPop(out IEfCoreScope<TDbContext>? ambientScope) ?? false)
lock (_lock)
{
return ambientScope;
}
if (_stack.Value?.TryPop(out IEfCoreScope<TDbContext>? ambientScope) ?? false)
{
return ambientScope;
}

throw new InvalidOperationException("No AmbientScope was found.");
throw new InvalidOperationException("No AmbientScope was found.");
}
}

public void Push(IEfCoreScope<TDbContext> scope)
{
_stack.Value ??= new ConcurrentStack<IEfCoreScope<TDbContext>>();
lock (_lock)
{
_stack.Value ??= new ConcurrentStack<IEfCoreScope<TDbContext>>();

_stack.Value.Push(scope);
_stack.Value.Push(scope);
}
}
}
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Constants-Composing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class Composing
{
public static readonly string[] UmbracoCoreAssemblyNames =
{
"Umbraco.Core", "Umbraco.Infrastructure", "Umbraco.PublishedCache.NuCache", "Umbraco.Examine.Lucene",
"Umbraco.Core", "Umbraco.Infrastructure", "Umbraco.Examine.Lucene",
"Umbraco.Web.Common", "Umbraco.Cms.Api.Common","Umbraco.Cms.Api.Delivery","Umbraco.Cms.Api.Management", "Umbraco.Web.Website",
};
}
Expand Down
3 changes: 2 additions & 1 deletion src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,8 @@ private void AddCoreServices()

// Routing
Services.AddUnique<IDocumentUrlService, DocumentUrlService>();
Services.AddHostedService<DocumentUrlServiceInitializer>();
Services.AddNotificationAsyncHandler<UmbracoApplicationStartingNotification, DocumentUrlServiceInitializerNotificationHandler>();

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Core.Notifications;

public class PostRuntimePremigrationsUpgradeNotification : INotification
{

}
53 changes: 0 additions & 53 deletions src/Umbraco.Core/Services/DocumentUrlServiceInitializer.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;

namespace Umbraco.Cms.Core.Services;

public class DocumentUrlServiceInitializerNotificationHandler : INotificationAsyncHandler<UmbracoApplicationStartingNotification>
{
private readonly IDocumentUrlService _documentUrlService;
private readonly IRuntimeState _runtimeState;

public DocumentUrlServiceInitializerNotificationHandler(IDocumentUrlService documentUrlService, IRuntimeState runtimeState)
{
_documentUrlService = documentUrlService;
_runtimeState = runtimeState;
}

public async Task HandleAsync(UmbracoApplicationStartingNotification notification, CancellationToken cancellationToken)
{
if (_runtimeState.Level == RuntimeLevel.Upgrade)
{
//Special case on the first upgrade, as the database is not ready yet.
return;
}

await _documentUrlService.InitAsync(
_runtimeState.Level <= RuntimeLevel.Install,
cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
using Microsoft.Extensions.Hosting;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;

namespace Umbraco.Cms.Core.Services.Navigation;

/// <summary>
/// Responsible for seeding the in-memory navigation structures at application's startup
/// by rebuild the navigation structures.
/// </summary>
public sealed class NavigationInitializationHostedService : IHostedLifecycleService
public sealed class NavigationInitializationNotificationHandler : INotificationAsyncHandler<PostRuntimePremigrationsUpgradeNotification>
{
private readonly IRuntimeState _runtimeState;
private readonly IDocumentNavigationManagementService _documentNavigationManagementService;
private readonly IMediaNavigationManagementService _mediaNavigationManagementService;

public NavigationInitializationHostedService(
public NavigationInitializationNotificationHandler(
IRuntimeState runtimeState,
IDocumentNavigationManagementService documentNavigationManagementService,
IMediaNavigationManagementService mediaNavigationManagementService)
Expand All @@ -22,7 +24,7 @@ public NavigationInitializationHostedService(
_mediaNavigationManagementService = mediaNavigationManagementService;
}

public async Task StartingAsync(CancellationToken cancellationToken)
public async Task HandleAsync(PostRuntimePremigrationsUpgradeNotification notification, CancellationToken cancellationToken)
{
if(_runtimeState.Level < RuntimeLevel.Upgrade)
{
Expand All @@ -34,14 +36,4 @@ public async Task StartingAsync(CancellationToken cancellationToken)
await _mediaNavigationManagementService.RebuildAsync();
await _mediaNavigationManagementService.RebuildBinAsync();
}

public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StartedAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StoppingAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
using Microsoft.Extensions.Hosting;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;

namespace Umbraco.Cms.Core.Services.Navigation;

/// <summary>
/// Responsible for seeding the in-memory publish status cache at application's startup
/// by loading all data from the database.
/// </summary>
public sealed class PublishStatusInitializationHostedService : IHostedLifecycleService
public sealed class PublishStatusInitializationNotificationHandler : INotificationAsyncHandler<PostRuntimePremigrationsUpgradeNotification>
{
private readonly IRuntimeState _runtimeState;
private readonly IPublishStatusManagementService _publishStatusManagementService;

public PublishStatusInitializationHostedService(
public PublishStatusInitializationNotificationHandler(
IRuntimeState runtimeState,
IPublishStatusManagementService publishStatusManagementService
)
Expand All @@ -20,7 +22,7 @@ IPublishStatusManagementService publishStatusManagementService
_publishStatusManagementService = publishStatusManagementService;
}

public async Task StartingAsync(CancellationToken cancellationToken)
public async Task HandleAsync(PostRuntimePremigrationsUpgradeNotification notification, CancellationToken cancellationToken)
{
if(_runtimeState.Level < RuntimeLevel.Upgrade)
{
Expand All @@ -29,14 +31,4 @@ public async Task StartingAsync(CancellationToken cancellationToken)

await _publishStatusManagementService.InitializeAsync(cancellationToken);
}

public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StartedAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StoppingAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;

public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
2 changes: 1 addition & 1 deletion src/Umbraco.Infrastructure/Install/PremigrationUpgrader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace Umbraco.Cms.Infrastructure.Install;

/// <summary>
/// Handles <see cref="RuntimeUnattendedUpgradeNotification" /> to execute the unattended Umbraco upgrader
/// Handles <see cref="RuntimePremigrationsUpgradeNotification" /> to execute the unattended Umbraco upgrader
/// or the unattended Package migrations runner.
/// </summary>
public class PremigrationUpgrader : INotificationAsyncHandler<RuntimePremigrationsUpgradeNotification>
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ protected virtual void DefinePlan()
To<V_13_5_0.ChangeRedirectUrlToNvarcharMax>("{CC47C751-A81B-489A-A2BC-0240245DB687}");

// To 14.0.0
To<V_14_0_0.AddPropertyEditorUiAliasColumn>("{419827A0-4FCE-464B-A8F3-247C6092AF55}");
To<NoopMigration>("{419827A0-4FCE-464B-A8F3-247C6092AF55}");
To<NoopMigration>("{69E12556-D9B3-493A-8E8A-65EC89FB658D}");
To<NoopMigration>("{F2B16CD4-F181-4BEE-81C9-11CF384E6025}");
To<NoopMigration>("{A8E01644-9F2E-4988-8341-587EF5B7EA69}");
To<V_14_0_0.UpdateDefaultGuidsOfCreatedPackages>("{E073DBC0-9E8E-4C92-8210-9CB18364F46E}");
To<V_14_0_0.RenameTechnologyLeakingPropertyEditorAliases>("{80D282A4-5497-47FF-991F-BC0BCE603121}");
To<V_14_0_0.MigrateSchduledPublishesToUtc>("{96525697-E9DC-4198-B136-25AD033442B8}");
To<V_14_0_0.AddListViewKeysToDocumentTypes>("{7FC5AC9B-6F56-415B-913E-4A900629B853}");
To<NoopMigration>("{7FC5AC9B-6F56-415B-913E-4A900629B853}");
To<V_14_0_0.MigrateDataTypeConfigurations>("{1539A010-2EB5-4163-8518-4AE2AA98AFC6}");
To<NoopMigration>("{C567DE81-DF92-4B99-BEA8-CD34EF99DA5D}");
To<V_14_0_0.DeleteMacroTables>("{0D82C836-96DD-480D-A924-7964E458BD34}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,7 @@ protected virtual void DefinePlan()
To<V_14_0_0.MigrateTours>("{A08254B6-D9E7-4207-A496-2ED0A87FB4FD}");
To<V_15_0_0.AddKindToUser>("{69AA6889-8B67-42B4-AA4F-114704487A45}");
To<V_15_0_0.AddDocumentUrl>("{B9133686-B758-404D-AF12-708AA80C7E44}");
To<V_14_0_0.AddPropertyEditorUiAliasColumn>("{EEB1F012-B44D-4AB4-8756-F7FB547345B4}");
To<V_14_0_0.AddListViewKeysToDocumentTypes>("{0F49E1A4-AFD8-4673-A91B-F64E78C48174}");
}
}
Loading

0 comments on commit 935c3b8

Please sign in to comment.