feat(core): add ContentServiceBase abstract class for Phase 1
Establishes shared infrastructure for content services: - Common dependencies (DocumentRepository, AuditService, UserIdKeyResolver) - Audit helper methods (sync and async) - Inherits from RepositoryService for scope/query support - Adds ContentServiceConstants for shared constants (batch page size) Updated tracking test to look for correct assembly location. Tracking test now fails (expected) - signals class exists for future work. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
69
src/Umbraco.Core/Services/ContentServiceBase.cs
Normal file
69
src/Umbraco.Core/Services/ContentServiceBase.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for content-related services providing shared infrastructure.
|
||||
/// </summary>
|
||||
public abstract class ContentServiceBase : RepositoryService
|
||||
{
|
||||
protected readonly IDocumentRepository DocumentRepository;
|
||||
protected readonly IAuditService AuditService;
|
||||
protected readonly IUserIdKeyResolver UserIdKeyResolver;
|
||||
|
||||
protected ContentServiceBase(
|
||||
ICoreScopeProvider provider,
|
||||
ILoggerFactory loggerFactory,
|
||||
IEventMessagesFactory eventMessagesFactory,
|
||||
IDocumentRepository documentRepository,
|
||||
IAuditService auditService,
|
||||
IUserIdKeyResolver userIdKeyResolver)
|
||||
: base(provider, loggerFactory, eventMessagesFactory)
|
||||
{
|
||||
DocumentRepository = documentRepository ?? throw new ArgumentNullException(nameof(documentRepository));
|
||||
AuditService = auditService ?? throw new ArgumentNullException(nameof(auditService));
|
||||
UserIdKeyResolver = userIdKeyResolver ?? throw new ArgumentNullException(nameof(userIdKeyResolver));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Records an audit entry for a content operation (synchronous).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Uses ConfigureAwait(false) to avoid capturing synchronization context and prevent deadlocks.
|
||||
/// TODO: Replace with sync overloads when IAuditService.Add and IUserIdKeyResolver.Get are available.
|
||||
/// </remarks>
|
||||
protected void Audit(AuditType type, int userId, int objectId, string? message = null, string? parameters = null)
|
||||
{
|
||||
// Use ConfigureAwait(false) to avoid context capture and potential deadlocks
|
||||
Guid userKey = UserIdKeyResolver.GetAsync(userId).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
AuditService.AddAsync(
|
||||
type,
|
||||
userKey,
|
||||
objectId,
|
||||
UmbracoObjectTypes.Document.GetName(),
|
||||
message,
|
||||
parameters).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Records an audit entry for a content operation asynchronously.
|
||||
/// </summary>
|
||||
protected async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null)
|
||||
{
|
||||
Guid userKey = await UserIdKeyResolver.GetAsync(userId).ConfigureAwait(false);
|
||||
|
||||
await AuditService.AddAsync(
|
||||
type,
|
||||
userKey,
|
||||
objectId,
|
||||
UmbracoObjectTypes.Document.GetName(),
|
||||
message,
|
||||
parameters).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
12
src/Umbraco.Core/Services/ContentServiceConstants.cs
Normal file
12
src/Umbraco.Core/Services/ContentServiceConstants.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Constants used by content-related services.
|
||||
/// </summary>
|
||||
public static class ContentServiceConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// Default page size for batch operations (e.g., cascade delete).
|
||||
/// </summary>
|
||||
public const int DefaultBatchPageSize = 500;
|
||||
}
|
||||
Reference in New Issue
Block a user