Adds IContentCrudService registration to UmbracoBuilder alongside IContentService. Both services are now resolvable from DI. Includes integration test verifying successful resolution. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
4.9 KiB
date, researcher, git_commit, branch, repository, topic, tags, status, last_updated, last_updated_by, type
| date | researcher | git_commit | branch | repository | topic | tags | status | last_updated | last_updated_by | type | ||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2025-12-20T00:38:15+00:00 | Claude | f4a01ed50d |
refactor/ContentService | Umbraco-CMS | ContentService Refactoring Performance Review |
|
completed | 2025-12-20 | Claude | implementation_strategy |
Handoff: ContentService Performance Review for Refactoring Design
Task(s)
Brainstorming session to review the ContentService refactoring design for performance improvements across four areas:
| Area | Status | Decision |
|---|---|---|
| 1. Database Query Efficiency | Completed | Batch lookups (4 steps) |
| 2. Memory Allocation Patterns | Completed | Aggressive, incremental (7 steps) |
| 3. Concurrency & Locking | Completed | Moderate (4 steps) |
| 4. Caching Strategies | Completed | Moderate (4 steps) |
Working from the design document at docs/plans/2025-12-19-contentservice-refactor-design.md.
Critical References
docs/plans/2025-12-19-contentservice-refactor-design.md- The refactoring design being reviewedsrc/Umbraco.Core/Services/ContentService.cs- Current ~3800 line implementation being refactoredsrc/Umbraco.Core/Services/IContentService.cs- Interface contract
Recent changes
No code changes made. This is a design review/brainstorming session.
Learnings
Database Query Efficiency Issues Identified
-
N+1 Query in
GetContentSchedulesByIds(ContentService.cs:1025-1049): Loop calling_idKeyMap.GetIdForKeyfor each key individually instead of batch lookup. -
Multiple repository calls in
CommitDocumentChangesInternal(ContentService.cs:1461+): Separate calls forGetContentSchedule,Save, andPersistContentSchedulewithin same scope. -
Repeated
GetByIdcalls:IsPathPublishable(line 1070),GetAncestors(line 792) make multiple single-item lookups.
Decision Made: User approved Option 1 (Batch lookups) approach:
- Add batch methods like
GetSchedulesByContentIds(int[] ids),ArePathsPublished(int[] contentIds),GetParents(int[] contentIds) - Fix N+1 in key-to-id resolution by adding/using
IIdKeyMap.GetIdsForKeys(Guid[] keys, UmbracoObjectTypes type)
Memory Allocation Issues Identified
- Excessive ToArray/ToList materializations: Lines 1170, 814, 2650 - materialize collections just to iterate
- String allocations in hot paths: Lines 1201, 2596-2598 - string concat in loops/move operations
- Lambda/closure allocations: Line 1125-1127 - creates list and closure on every save
- Dictionary recreations: Lines 555-556 - creates dictionary then iterates again
Pending Decision: User needs to choose approach:
- Conservative: Fix obvious issues (ToArray before iteration, string concat in loops)
- Moderate: Add StringBuilder pooling, avoid unnecessary materializations
- Aggressive: Full Span/ArrayPool usage, pooled collections
Artifacts
docs/plans/2025-12-19-contentservice-refactor-design.md- Design document updated to Revision 1.2 with Performance Optimizations section
Action Items & Next Steps
All performance review tasks completed. Design document updated with:
- ✅ Database Query Efficiency - 4 batch lookup improvements
- ✅ Memory Allocation Patterns - 7 incremental optimization steps
- ✅ Concurrency & Locking - 4 lock optimization steps
- ✅ Caching Strategies - 4 cache optimization steps
- ✅ Design document updated at
docs/plans/2025-12-19-contentservice-refactor-design.md(Revision 1.2)
Next step: Proceed to implementation planning with superpowers:writing-plans
Other Notes
Architecture Context
The refactoring splits ContentService into 5 public services + 2 internal managers:
IContentCrudService(~400 lines) - Create, Get, Save, DeleteIContentPublishOperationService(~1000 lines) - Publish, Unpublish, SchedulingIContentMoveService(~350 lines) - Move, RecycleBin, Copy, SortIContentQueryService(~250 lines) - Count, Paged queries, HierarchyIContentVersionService(~200 lines) - Versions, RollbackContentPermissionManager(internal) - PermissionsContentBlueprintManager(internal) - Blueprints
Key Design Decisions Already Made
- Naming:
IContentPublishOperationService(notIContentPublishingService) to avoid collision with existing API-layer service - Scope Pattern: Caller-Creates-Scope (Ambient Scope) - nested scopes participate in parent transaction
- Lock Coordination: Acquire locks at highest level that creates scope
- Dependency Direction: Unidirectional - Publish/Move may call CRUD, no reverse dependencies
Relevant Codebase Locations
- Core interfaces:
src/Umbraco.Core/Services/ - Repository interfaces:
src/Umbraco.Core/Persistence/Repositories/ - Scoping:
src/Umbraco.Core/Scoping/ - ID/Key mapping:
IIdKeyMapinterface for key-to-id resolution