Skip to content

Commit

Permalink
V15: Cache Seeding (#17102)
Browse files Browse the repository at this point in the history
* Update to dotnet 9 and update nuget packages

* Update umbraco code version

* Update Directory.Build.props

Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>

* Include preview version in pipeline

* update template projects

* update global json with specific version

* Update version.json to v15

* Rename TrimStart and TrimEnd to string specific

* Rename to Exact

* Update global.json

Co-authored-by: Ronald Barendse <ronald@barend.se>

* Remove includePreviewVersion

* Rename to trim exact

* Add new Hybridcache project

* Add tests

* Start implementing PublishedContent.cs

* Implement repository for content

* Refactor to use async everywhere

* Add cache refresher

* make public as needed for serialization

* Use content type cache to get content type out

* Refactor to use ContentCacheNode model, that goes in the memory cache

* Remove content node kit as its not needed

* Implement tests for ensuring caching

* Implement better asserts

* Implement published property

* Refactor to use mapping

* Rename to document tests

* Update to test properties

* Create more tests

* Refactor mock tests into own file

* Update property test

* Fix published version of content

* Change default cache level to elements

* Refactor to always have draft

* Refactor to not use PublishedModelFactory

* Added tests

* Added and updated tests

* Fixed tests

* Don't return empty object with id

* More tests

* Added key

* Another key

* Refactor CacheService to be responsible for using the hybrid cache

* Use notification handler to remove deleted content from cache

* Add more tests for missing functions

* Implement missing methods

* Remove HasContent as it pertains to routing

* Fik up test

* formatting

* refactor variable names

* Implement variant tests

* Map all the published content properties

* Get item out of cache first, to assert updated

* Implement member cache

* Add member test

* Implement media cache

* Implement property tests for media tests

* Refactor tests to use extension method

* Add more media tests

* Refactor properties to no longer have element caching

* Don't use property cache level

* Start implementing seeding

* Only seed when main

* Add Immutable for performance

* Implement permanent seeding of content

* Implement cache settings

* Implement tests for seeding

* Update package version

* start refactoring nurepo

* Refactor so draft & published nodes are cached individually

* Refactor RefreshContent to take node instead of IContent

* Refactor media to also use cache nodes

* Remove member from repo as it isn't cached

* Refactor media to not include preview, as media has no draft

* create new benchmark project

* POC Integration benchmarks with custom api controllers

* Start implementing content picker tests

* Implement domain cache

* Rework content cache to implement interface

* Start implementing elements cache

* Implement published snapshot service

* Publish snapshot tests

* Use snapshot for elements cache

* Create test proving we don't clear cache when updating content picker

* Clear entire elements cache

* Remove properties from element cache, when content gets updated.

* Rename methods to async

* Refactor to use old cache interfaces instead of new ones

* Remove snapshot, as it is no longer needed

* Fix tests building

* Refactor domaincache to not have snapshots

* Delete benchmarks

* Delete benchmarks

* Add HybridCacheProject to Umbraco

* Add comment to route value transformer

* Implement is draft

* remove snapshot from property

* V15 updated the hybrid caching integration tests to use ContentEditingService (#16947)

* Added builder extension withParentKey

* Created builder with ContentEditingService

* Added usage of the ContentEditingService to SETUP

* Started using ContentEditingService builder in tests

* Updated builder extensions

* Fixed builder

* Clean up

* Clean up, not done

* Added Ids

* Remove entries from cache on delete

* Fix up seeding logic

* Don't register hybrid cache twice

* Change seeded entry options

* Update hybrid cache package

* Fix up published property to work with delivery api again

* Fix dependency injection to work with tests

* Fix naming

* Dont make caches nullable

* Make content node sealed

* Remove path and other unused from content node

* Remove hacky 2 phase ctor

* Refactor to actually set content templates

* Remove umbraco context

* Remove "HasBy" methods

* rename property data

* Delete obsolete legacy stuff

* Add todo for making expiration configurable

* Add todo in UmbracoContext

* Add clarifying comment in content factory

* Remove xml stuff from published property

* Fix according to review

* Make content type cache injectible

* Make content type cache injectible

* Rename to database cache repository

* Rename to document cache

* Add TODO

* Refactor to async

* Rename to async

* Make everything async

* Remove duplicate line from json schema

* Move Hybrid cache project

* Remove leftover file

* Refactor to use keys

* Refactor published content to no longer have content data, as it is on the node itself

* Refactor to member to use proper content node ctor

* Move tests to own folder

* Add immutable objects to property and content data for performance

* Make property data public

* Fix member caching to be singleton

* Obsolete GetContentType

* Remove todo

* Fix naming

* Fix lots of exposed errors due to scope test

* Add final scope tests

* Rename to document cache service

* Rename test files

* Create new doc type tests

* Add ignore to tests

* Start implementing refresh for content type save

* Clear contenttype cache when contenttype is updated

* Fix test

Teh contenttype is not upated unless the property is dirty

* Updated tests

* Added tests

* Use init for ContentSourceDto

* Startup of setup

* Fix get by key in PublishedContentTypeCache

* Remove ContentType from PublishedContentTypeCache when contenttype is deleted

* Created interfaces for the builder with the necessary properties

* Created builder for PropertyTypeContainer

* Created builder for PropertyTypeEditing

* Created builder for PropertyTypeValidationEditing

* Made adjustments to the builder

* Updated name of usage

* Commented out to test

* Cleaned up builders

* Updated integration test setup

* Moved tests

* Added interface

* Add IDocumentSeedKeyProvider and migrate existing logic to seed key provider

* Added functionality to the INavigationQueryService to get root keys

* Fixed issue with navigation

* Created helper to Convert a IContentType to ContentTypeUpdateModel

* Added interfaces

* Added builder

* Cleaned up builders and added fixes

* Added tests for PublishedContentTypeCache

* Applied changes in builder

* Add BreadthFirstKeyProvider

* Use ISet for seedkey providers

* Implement GetContentSource by key

* Seed the cache with keys provided by seed key providers

* Builder updates

* Test setup updates

* Updated tests

* Dont require contenttype keys for seeding

* Fix cache settings

* Don't inject cache settings into SeedingNotificationHandler

* Fix tests

* Use enlistment for setting updated cache item

* Pin seeded nodes for longer

* Fix BreadthFirstKeyProvider

* Fix ContentTypeSeedKeyProvider

* Fix tests

* Only seed published documents

* Only cache published if contentCacheNode is not draft

* Fix incorrect templateId

* Removed unnecessary setup

* initialized value

* Fixed template test

* Removed test

* Updated tests

* Removed code that was not used

* Removed unused cacheSettings

* Re-organize to support media cache seeding

* Add MediaBreadthFirstKeyProvider

* Seed media

* Don't use IdKeyMap when removing content from cache

* Don't clear IdKeyMap in DocumentCacheService

* Add unit tests

* Don't use IdKeyMap when deleting media

* Add default value to timespan

* Use cancellation tokens when doing loop

* Fixed Models Builder error

---------

Co-authored-by: Zeegaan <skrivdetud@gmail.com>
Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>
Co-authored-by: Ronald Barendse <ronald@barend.se>
Co-authored-by: Andreas Zerbst <andr317c@live.dk>
Co-authored-by: Sven Geusens <sge@umbraco.dk>
Co-authored-by: Andreas Zerbst <73799582+andr317c@users.noreply.github.com>
Co-authored-by: Bjarke Berg <mail@bergmania.dk>
  • Loading branch information
9 people authored Sep 24, 2024
1 parent d2504e3 commit e342e79
Show file tree
Hide file tree
Showing 51 changed files with 1,766 additions and 410 deletions.
1 change: 1 addition & 0 deletions src/Umbraco.Core/Constants-SqlTemplates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static class DataTypeRepository
public static class NuCacheDatabaseDataSource
{
public const string WhereNodeId = "Umbraco.Web.PublishedCache.NuCache.DataSource.WhereNodeId";
public const string WhereNodeKey = "Umbraco.Web.PublishedCache.NuCache.DataSource.WhereNodeKey";
public const string WhereNodeIdX = "Umbraco.Web.PublishedCache.NuCache.DataSource.WhereNodeIdX";

public const string SourcesSelectUmbracoNodeJoin =
Expand Down
7 changes: 2 additions & 5 deletions src/Umbraco.Core/Factories/NavigationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ internal static class NavigationFactory
/// <summary>
/// Builds a dictionary of NavigationNode objects from a given dataset.
/// </summary>
/// <param name="nodesStructure">A dictionary of <see cref="NavigationNode" /> objects with key corresponding to their unique Guid.</param>
/// <param name="entities">The <see cref="INavigationModel" /> objects used to build the navigation nodes dictionary.</param>
/// <returns>A dictionary of <see cref="NavigationNode" /> objects with key corresponding to their unique Guid.</returns>
public static ConcurrentDictionary<Guid, NavigationNode> BuildNavigationDictionary(IEnumerable<INavigationModel> entities)
public static void BuildNavigationDictionary(ConcurrentDictionary<Guid, NavigationNode> nodesStructure,IEnumerable<INavigationModel> entities)
{
var nodesStructure = new ConcurrentDictionary<Guid, NavigationNode>();
var entityList = entities.ToList();
var idToKeyMap = entityList.ToDictionary(x => x.Id, x => x.Key);

Expand All @@ -39,7 +38,5 @@ public static ConcurrentDictionary<Guid, NavigationNode> BuildNavigationDictiona
parentNode.AddChild(node);
}
}

return nodesStructure;
}
}
18 changes: 17 additions & 1 deletion src/Umbraco.Core/Models/CacheSettings.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
using Umbraco.Cms.Core.Configuration.Models;
using System.ComponentModel;
using Umbraco.Cms.Core.Configuration.Models;

namespace Umbraco.Cms.Core.Models;

[UmbracoOptions(Constants.Configuration.ConfigCache)]
public class CacheSettings
{
internal const int StaticDocumentBreadthFirstSeedCount = 100;

internal const int StaticMediaBreadthFirstSeedCount = 100;
internal const string StaticSeedCacheDuration = "365.00:00:00";

/// <summary>
/// Gets or sets a value for the collection of content type ids to always have in the cache.
/// </summary>
public List<Guid> ContentTypeKeys { get; set; } =
new();

[DefaultValue(StaticDocumentBreadthFirstSeedCount)]
public int DocumentBreadthFirstSeedCount { get; set; } = StaticDocumentBreadthFirstSeedCount;


[DefaultValue(StaticMediaBreadthFirstSeedCount)]
public int MediaBreadthFirstSeedCount { get; set; } = StaticDocumentBreadthFirstSeedCount;

[DefaultValue(StaticSeedCacheDuration)]
public TimeSpan SeedCacheDuration { get; set; } = TimeSpan.Parse(StaticSeedCacheDuration);
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public bool TryGetParentKey(Guid childKey, out Guid? parentKey)
public bool TryGetChildrenKeys(Guid parentKey, out IEnumerable<Guid> childrenKeys)
=> TryGetChildrenKeysFromStructure(_navigationStructure, parentKey, out childrenKeys);

public bool TryGetRootKeys(out IEnumerable<Guid> childrenKeys)
=> TryGetRootKeysFromStructure(_navigationStructure, out childrenKeys);

public bool TryGetDescendantsKeys(Guid parentKey, out IEnumerable<Guid> descendantsKeys)
=> TryGetDescendantsKeysFromStructure(_navigationStructure, parentKey, out descendantsKeys);

Expand Down Expand Up @@ -162,6 +165,7 @@ public bool RestoreFromBin(Guid key, Guid? targetParentKey = null)
_recycleBinNavigationStructure.TryRemove(key, out _);
}


/// <summary>
/// Rebuilds the navigation structure based on the specified object type key and whether the items are trashed.
/// Only relevant for items in the content and media trees (which have readLock values of -333 or -334).
Expand All @@ -184,7 +188,7 @@ protected async Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool t
_navigationRepository.GetTrashedContentNodesByObjectType(objectTypeKey) :
_navigationRepository.GetContentNodesByObjectType(objectTypeKey);

_navigationStructure = NavigationFactory.BuildNavigationDictionary(navigationModels);
NavigationFactory.BuildNavigationDictionary(_navigationStructure, navigationModels);
}

private bool TryGetParentKeyFromStructure(ConcurrentDictionary<Guid, NavigationNode> structure, Guid childKey, out Guid? parentKey)
Expand Down Expand Up @@ -213,6 +217,13 @@ private bool TryGetChildrenKeysFromStructure(ConcurrentDictionary<Guid, Navigati
return true;
}

private bool TryGetRootKeysFromStructure(ConcurrentDictionary<Guid, NavigationNode> structure, out IEnumerable<Guid> childrenKeys)
{
// TODO can we make this more efficient?
childrenKeys = structure.Values.Where(x=>x.Parent is null).Select(x=>x.Key);
return true;
}

private bool TryGetDescendantsKeysFromStructure(ConcurrentDictionary<Guid, NavigationNode> structure, Guid parentKey, out IEnumerable<Guid> descendantsKeys)
{
var descendants = new List<Guid>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public interface INavigationQueryService
bool TryGetParentKey(Guid childKey, out Guid? parentKey);

bool TryGetChildrenKeys(Guid parentKey, out IEnumerable<Guid> childrenKeys);
bool TryGetRootKeys(out IEnumerable<Guid> childrenKeys);

bool TryGetDescendantsKeys(Guid parentKey, out IEnumerable<Guid> descendantsKeys);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using Umbraco.Cms.Infrastructure.HybridCache.Factories;
using Umbraco.Cms.Infrastructure.HybridCache.NotificationHandlers;
using Umbraco.Cms.Infrastructure.HybridCache.Persistence;
using Umbraco.Cms.Infrastructure.HybridCache.SeedKeyProviders.Document;
using Umbraco.Cms.Infrastructure.HybridCache.SeedKeyProviders.Media;
using Umbraco.Cms.Infrastructure.HybridCache.Serialization;
using Umbraco.Cms.Infrastructure.HybridCache.Services;

Expand Down Expand Up @@ -62,6 +64,17 @@ public static IUmbracoBuilder AddUmbracoHybridCache(this IUmbracoBuilder builder
builder.AddNotificationAsyncHandler<MediaDeletedNotification, CacheRefreshingNotificationHandler>();
builder.AddNotificationAsyncHandler<UmbracoApplicationStartedNotification, SeedingNotificationHandler>();
builder.AddNotificationAsyncHandler<ContentTypeRefreshedNotification, CacheRefreshingNotificationHandler>();
builder.AddCacheSeeding();
return builder;
}

private static IUmbracoBuilder AddCacheSeeding(this IUmbracoBuilder builder)
{
builder.Services.AddSingleton<IDocumentSeedKeyProvider, ContentTypeSeedKeyProvider>();
builder.Services.AddSingleton<IDocumentSeedKeyProvider, DocumentBreadthFirstKeyProvider>();


builder.Services.AddSingleton<IMediaSeedKeyProvider, MediaBreadthFirstKeyProvider>();
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public CacheNodeFactory(IShortStringHelper shortStringHelper, UrlSegmentProvider

public ContentCacheNode ToContentCacheNode(IContent content, bool preview)
{
ContentData contentData = GetContentData(content, !preview, preview ? content.PublishTemplateId : content.TemplateId);
ContentData contentData = GetContentData(content, !preview, preview ? content.TemplateId : content.PublishTemplateId);
return new ContentCacheNode
{
Id = content.Id,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Infrastructure.HybridCache;

public interface IDocumentSeedKeyProvider : ISeedKeyProvider
{

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

public interface IMediaSeedKeyProvider : ISeedKeyProvider
{

}
10 changes: 10 additions & 0 deletions src/Umbraco.PublishedCache.HybridCache/ISeedKeyProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Umbraco.Cms.Infrastructure.HybridCache;

public interface ISeedKeyProvider
{
/// <summary>
/// Gets keys of documents that should be seeded into the cache.
/// </summary>
/// <returns>Keys to seed</returns>
ISet<Guid> GetSeedKeys();
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task HandleAsync(ContentDeletedNotification notification, Cancellat
foreach (IContent deletedEntity in notification.DeletedEntities)
{
await RefreshElementsCacheAsync(deletedEntity);
await _documentCacheService.DeleteItemAsync(deletedEntity.Id);
await _documentCacheService.DeleteItemAsync(deletedEntity);
}
}

Expand All @@ -66,7 +66,7 @@ public async Task HandleAsync(MediaDeletedNotification notification, Cancellatio
foreach (IMedia deletedEntity in notification.DeletedEntities)
{
await RefreshElementsCacheAsync(deletedEntity);
await _mediaCacheService.DeleteItemAsync(deletedEntity.Id);
await _mediaCacheService.DeleteItemAsync(deletedEntity);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.HybridCache.Services;

namespace Umbraco.Cms.Infrastructure.HybridCache.NotificationHandlers;

internal class SeedingNotificationHandler : INotificationAsyncHandler<UmbracoApplicationStartedNotification>
{
private readonly IDocumentCacheService _documentCacheService;
private readonly CacheSettings _cacheSettings;
private readonly IMediaCacheService _mediaCacheService;
private readonly IRuntimeState _runtimeState;

public SeedingNotificationHandler(IDocumentCacheService documentCacheService, IOptions<CacheSettings> cacheSettings)
public SeedingNotificationHandler(IDocumentCacheService documentCacheService, IMediaCacheService mediaCacheService, IRuntimeState runtimeState)
{
_documentCacheService = documentCacheService;
_cacheSettings = cacheSettings.Value;
_mediaCacheService = mediaCacheService;
_runtimeState = runtimeState;
}

public async Task HandleAsync(UmbracoApplicationStartedNotification notification, CancellationToken cancellationToken) => await _documentCacheService.SeedAsync(_cacheSettings.ContentTypeKeys);
public async Task HandleAsync(UmbracoApplicationStartedNotification notification,
CancellationToken cancellationToken)
{

if (_runtimeState.Level <= RuntimeLevel.Install)
{
return;
}

await Task.WhenAll(
_documentCacheService.SeedAsync(cancellationToken),
_mediaCacheService.SeedAsync(cancellationToken)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@ public async Task RefreshContentAsync(ContentCacheNode contentCacheNode, Publish
{
IContentCacheDataSerializer serializer = _contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);

// always refresh the edited data
await OnRepositoryRefreshed(serializer, contentCacheNode, true);
// We always cache draft and published separately, so we only want to cache drafts if the node is a draft type.
if (contentCacheNode.IsDraft)
{
await OnRepositoryRefreshed(serializer, contentCacheNode, true);
// if it's a draft node we don't need to worry about the published state
return;
}

switch (publishedState)
{
Expand Down Expand Up @@ -208,11 +213,36 @@ AND cmsContentNu.nodeId IS NULL
return CreateContentNodeKit(dto, serializer, preview);
}

public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys)
public async Task<ContentCacheNode?> GetContentSourceAsync(Guid key, bool preview = false)
{
Sql<ISqlContext>? sql = SqlContentSourcesSelect()
.Append(SqlObjectTypeNotTrashed(SqlContext, Constants.ObjectTypes.Document))
.Append(SqlWhereNodeKey(SqlContext, key))
.Append(SqlOrderByLevelIdSortOrder(SqlContext));

ContentSourceDto? dto = await Database.FirstOrDefaultAsync<ContentSourceDto>(sql);

if (dto == null)
{
return null;
}

if (preview is false && dto.PubDataRaw is null && dto.PubData is null)
{
return null;
}

IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
return CreateContentNodeKit(dto, serializer, preview);
}

private IEnumerable<ContentSourceDto> GetContentSourceByDocumentTypeKey(IEnumerable<Guid> documentTypeKeys)
{
Guid[] keys = documentTypeKeys.ToArray();
if (keys.Any() is false)
{
yield break;
return [];
}

Sql<ISqlContext>? sql = SqlContentSourcesSelect()
Expand All @@ -222,17 +252,26 @@ public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid
.WhereIn<NodeDto>(x => x.UniqueId, keys,"n")
.Append(SqlOrderByLevelIdSortOrder(SqlContext));

return GetContentNodeDtos(sql);
}

public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys)
{
IEnumerable<ContentSourceDto> dtos = GetContentSourceByDocumentTypeKey(keys);

IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);

IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);

foreach (ContentSourceDto row in dtos)
{
yield return CreateContentNodeKit(row, serializer, row.Published is false);
}
}

/// <inheritdoc />
public IEnumerable<Guid> GetContentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false)
=> GetContentSourceByDocumentTypeKey(keys).Where(x => x.Published == published).Select(x => x.Key);

public async Task<ContentCacheNode?> GetMediaSourceAsync(int id)
{
Sql<ISqlContext>? sql = SqlMediaSourcesSelect()
Expand All @@ -252,6 +291,25 @@ public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid
return CreateMediaNodeKit(dto, serializer);
}

public async Task<ContentCacheNode?> GetMediaSourceAsync(Guid key)
{
Sql<ISqlContext>? sql = SqlMediaSourcesSelect()
.Append(SqlObjectTypeNotTrashed(SqlContext, Constants.ObjectTypes.Media))
.Append(SqlWhereNodeKey(SqlContext, key))
.Append(SqlOrderByLevelIdSortOrder(SqlContext));

ContentSourceDto? dto = await Database.FirstOrDefaultAsync<ContentSourceDto>(sql);

if (dto is null)
{
return null;
}

IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
return CreateMediaNodeKit(dto, serializer);
}

private async Task OnRepositoryRefreshed(IContentCacheDataSerializer serializer, ContentCacheNode content, bool preview)
{
// use a custom SQL to update row version on each update
Expand Down Expand Up @@ -642,6 +700,19 @@ private Sql<ISqlContext> SqlWhereNodeId(ISqlContext sqlContext, int id)
return sql;
}

private Sql<ISqlContext> SqlWhereNodeKey(ISqlContext sqlContext, Guid key)
{
ISqlSyntaxProvider syntax = sqlContext.SqlSyntax;

SqlTemplate sqlTemplate = sqlContext.Templates.Get(
Constants.SqlTemplates.NuCacheDatabaseDataSource.WhereNodeKey,
builder =>
builder.Where<NodeDto>(x => x.UniqueId == SqlTemplate.Arg<Guid>("key")));

Sql<ISqlContext> sql = sqlTemplate.Sql(key);
return sql;
}

private Sql<ISqlContext> SqlOrderByLevelIdSortOrder(ISqlContext sqlContext)
{
ISqlSyntaxProvider syntax = sqlContext.SqlSyntax;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,22 @@ internal interface IDatabaseCacheRepository

Task<ContentCacheNode?> GetContentSourceAsync(int id, bool preview = false);

Task<ContentCacheNode?> GetContentSourceAsync(Guid key, bool preview = false);

Task<ContentCacheNode?> GetMediaSourceAsync(int id);

Task<ContentCacheNode?> GetMediaSourceAsync(Guid key);


IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys);

/// <summary>
/// Gets all content keys of specific document types
/// </summary>
/// <param name="keys">The document types to find content using.</param>
/// <returns>The keys of all content use specific document types.</returns>
IEnumerable<Guid> GetContentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false);

/// <summary>
/// Refreshes the nucache database row for the given cache node />
/// </summary>
Expand Down
Loading

0 comments on commit e342e79

Please sign in to comment.