Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ability to get and search items without using cache #2820

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,20 @@ public static Task<IList<TModel>> GetByIdsAsync<TModel>(this ICrudService<TModel
{
return crudService.GetAsync(ids, responseGroup, clone);
}

/// <summary>
/// Returns data from the database without using cache.
/// </summary>
public static async Task<TModel> GetNoCacheAsync<TModel>(this ICrudService<TModel> crudService, string id, string responseGroup = null)
where TModel : Entity
{
if (id is null)
{
return null;
}

var entities = await crudService.GetNoCacheAsync([id], responseGroup);

return entities?.FirstOrDefault();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ public static async Task<IList<TModel>> SearchAllAsync<TCriteria, TResult, TMode
return result;
}

/// <summary>
/// Returns data from the database without using cache.
/// </summary>
public static async Task<IList<TModel>> SearchAllNoCacheAsync<TCriteria, TResult, TModel>(this ISearchService<TCriteria, TResult, TModel> searchService, TCriteria searchCriteria)
where TCriteria : SearchCriteriaBase
where TResult : GenericSearchResult<TModel>
where TModel : IEntity
{
var result = new List<TModel>();

await foreach (var searchResult in searchService.SearchBatchesNoCacheAsync(searchCriteria))
{
result.AddRange(searchResult.Results);
}

return result;
}

/// <summary>
/// Returns data from the cache without cloning. This consumes less memory, but the returned data must not be modified.
/// </summary>
Expand Down Expand Up @@ -71,10 +89,26 @@ public static IAsyncEnumerable<TResult> SearchBatchesNoCloneAsync<TCriteria, TRe
where TResult : GenericSearchResult<TModel>
where TModel : IEntity
{
return searchService.SearchBatchesAsync(searchCriteria, clone: false);
return SearchBatchesInternalAsync(searchService, searchCriteria, false);
}

public static IAsyncEnumerable<TResult> SearchBatchesAsync<TCriteria, TResult, TModel>(this ISearchService<TCriteria, TResult, TModel> searchService, TCriteria searchCriteria, bool clone = true)
where TCriteria : SearchCriteriaBase
where TResult : GenericSearchResult<TModel>
where TModel : IEntity
{
return SearchBatchesInternalAsync(searchService, searchCriteria, clone);
}

public static IAsyncEnumerable<TResult> SearchBatchesNoCacheAsync<TCriteria, TResult, TModel>(this ISearchService<TCriteria, TResult, TModel> searchService, TCriteria searchCriteria)
where TCriteria : SearchCriteriaBase
where TResult : GenericSearchResult<TModel>
where TModel : IEntity
{
return SearchBatchesInternalAsync(searchService, searchCriteria, noCache: true);
}

public static async IAsyncEnumerable<TResult> SearchBatchesAsync<TCriteria, TResult, TModel>(this ISearchService<TCriteria, TResult, TModel> searchService, TCriteria searchCriteria, bool clone = true)
private static async IAsyncEnumerable<TResult> SearchBatchesInternalAsync<TCriteria, TResult, TModel>(this ISearchService<TCriteria, TResult, TModel> searchService, TCriteria searchCriteria, bool clone = true, bool noCache = false)
where TCriteria : SearchCriteriaBase
where TResult : GenericSearchResult<TModel>
where TModel : IEntity
Expand All @@ -84,10 +118,12 @@ public static async IAsyncEnumerable<TResult> SearchBatchesAsync<TCriteria, TRes

do
{
var searchResult = await searchService.SearchAsync(searchCriteria, clone);
var searchTask = noCache
? searchService.SearchNoCacheAsync(searchCriteria)
: searchService.SearchAsync(searchCriteria, clone);
var searchResult = await searchTask;

if (searchCriteria.Take == 0 ||
searchResult.Results.Any())
if (searchCriteria.Take == 0 || searchResult.Results.Count > 0)
{
yield return searchResult;
}
Expand Down
13 changes: 13 additions & 0 deletions src/VirtoCommerce.Platform.Core/GenericCrud/ICrudService.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using VirtoCommerce.Platform.Core.Common;
Expand All @@ -20,7 +21,19 @@ public interface ICrudService<T>
/// <returns></returns>
Task<IList<T>> GetAsync(IList<string> ids, string responseGroup = null, bool clone = true);

/// <summary>
/// Returns a list of model instances for specified IDs without using cache.
/// </summary>
/// <param name="ids"></param>
/// <param name="responseGroup"></param>
/// <returns></returns>
Task<IList<T>> GetNoCacheAsync(IList<string> ids, string responseGroup = null)
{
throw new NotSupportedException("Underlying service does not support no cache search.");
}

Task SaveChangesAsync(IList<T> models);

Task DeleteAsync(IList<string> ids, bool softDelete = false);
}
}
11 changes: 11 additions & 0 deletions src/VirtoCommerce.Platform.Core/GenericCrud/ISearchService.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks;
using VirtoCommerce.Platform.Core.Common;

Expand All @@ -21,5 +22,15 @@ public interface ISearchService<TCriteria, TResult, TModel>
/// <param name="clone">If false, returns data from the cache without cloning. This consumes less memory, but the returned data must not be modified.</param>
/// <returns></returns>
Task<TResult> SearchAsync(TCriteria criteria, bool clone = true);

/// <summary>
/// Returns model instances that meet specified criteria without using cache.
/// </summary>
/// <param name="criteria"></param>
/// <returns></returns>
Task<TResult> SearchNoCacheAsync(TCriteria criteria)
{
throw new NotSupportedException("Underlying service does not support no cache search.");
}
}
}
22 changes: 13 additions & 9 deletions src/VirtoCommerce.Platform.Data/GenericCrud/CrudService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,25 @@ public virtual async Task<IList<TModel>> GetAsync(IList<string> ids, string resp
missingIds => GetByIdsNoCache(missingIds, responseGroup),
ConfigureCache);

if (!clone)
{
return models;
}
return !clone ? models : models.Select(x => x.CloneTyped()).ToList();
}

return models
.Select(x => x.CloneTyped())
.ToList();
/// <summary>
/// Returns a list of model instances for specified IDs without using cache.
/// </summary>
/// <param name="ids"></param>
/// <param name="responseGroup"></param>
/// <returns></returns>
public virtual Task<IList<TModel>> GetNoCacheAsync(IList<string> ids, string responseGroup = null)
{
return GetByIdsNoCache(ids, responseGroup);
}

protected virtual async Task<IList<TModel>> GetByIdsNoCache(IList<string> ids, string responseGroup)
{
using var repository = _repositoryFactory();

// Disable DBContext change tracking for better performance
// Disable DBContext change tracking for better performance
repository.DisableChangesTracking();

var entities = await LoadEntities(repository, ids, responseGroup);
Expand Down Expand Up @@ -341,7 +345,7 @@ protected virtual TEntity FromModel(TModel model, PrimaryKeyResolvingMap keyMap)

protected virtual GenericChangedEntryEvent<TModel> EventFactory<TEvent>(IList<GenericChangedEntry<TModel>> changedEntries)
{
return (GenericChangedEntryEvent<TModel>)typeof(TEvent).GetConstructor(new[] { typeof(IEnumerable<GenericChangedEntry<TModel>>) }).Invoke(new object[] { changedEntries });
return (GenericChangedEntryEvent<TModel>)typeof(TEvent).GetConstructor([typeof(IEnumerable<GenericChangedEntry<TModel>>)])?.Invoke([changedEntries]);
}
}
}
23 changes: 23 additions & 0 deletions src/VirtoCommerce.Platform.Data/GenericCrud/SearchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,29 @@ public virtual async Task<TResult> SearchAsync(TCriteria criteria, bool clone =
return await ProcessSearchResultAsync(result, criteria);
}

/// <summary>
/// Returns model instances that meet specified criteria without using cache.
/// </summary>
/// <param name="criteria"></param>
/// <returns></returns>
public virtual async Task<TResult> SearchNoCacheAsync(TCriteria criteria)
{
ValidateSearchCriteria(criteria);

var idsResult = await SearchIdsNoCacheAsync(criteria);

var result = AbstractTypeFactory<TResult>.TryCreateInstance();
result.TotalCount = idsResult.TotalCount;

if (idsResult.Results?.Count > 0)
{
var models = await _crudService.GetNoCacheAsync(idsResult.Results, criteria.ResponseGroup);
result.Results.AddRange(models.OrderBy(x => idsResult.Results.IndexOf(x.Id)));
}

return await ProcessSearchResultAsync(result, criteria);
}


protected virtual void ValidateSearchCriteria(TCriteria criteria)
{
Expand Down
Loading