/// <summary> /// Параллельная обработка перечисления на разных сессиях. /// </summary> /// <typeparam name="TSrc">Тип данных.</typeparam> /// <typeparam name="T">Тип результата.</typeparam> /// <param name="src">Перечисление.</param> /// <param name="parallelFunc">Функция обоработки.</param> /// <returns>Результат.</returns> protected async ValueTask <T[]> ParallelizeOnSessions <TSrc, T>(IEnumerable <TSrc> src, Func <IEsentSession, TSrc, T> parallelFunc) { ValueTask <T> Do(IEsentSession session, TSrc el) { return(session.Run(() => parallelFunc(session, el))); } if (src == null) { throw new ArgumentNullException(nameof(src)); } if (parallelFunc == null) { throw new ArgumentNullException(nameof(parallelFunc)); } var tasks = new List <ValueTask <T> >(); var toDispose = new CompositeDisposable(null); try { foreach (var el in src) { var session = await EsentProvider.GetSecondarySessionAndUse(); toDispose.AddDisposable(session.usage); tasks.Add(Do(session.session, el)); } return(await CoreTaskHelper.WhenAllValueTasks(tasks)); } finally { toDispose.Dispose(); } }
private async Task <IList <IBoardPostEntity> > LoadEntities(IList <PostStoreEntityId> ids, PostStoreLoadMode mode) { ValueTask <List <IBoardPostEntity> > DoLoad(IList <PostStoreEntityId> toLoad) { return(OpenSession(session => { var result = new List <IBoardPostEntity>(); var loadContext = CreateLoadContext(session, true, true); var loadContextToDispose = loadContext; using (loadContextToDispose) { foreach (var id in toLoad) { Api.MakeKey(loadContext.table.Session, loadContext.table, id.Id, MakeKeyGrbit.NewKey); if (Api.TrySeek(loadContext.table.Session, loadContext.table, SeekGrbit.SeekEQ)) { var r = LoadBoardEntity(session, ref loadContext, mode); result.Add(r); } } } return result; })); } if (ids == null) { throw new ArgumentNullException(nameof(ids)); } mode = mode ?? DefaultLoadMode; IList <IBoardPostEntity> loaded; if (ids.Count > 4) { var toLoad = ids.DistributeToProcess(3); var tasks = toLoad.Select(DoLoad).ToArray(); var taskResults = await CoreTaskHelper.WhenAllValueTasks(tasks); loaded = taskResults.SelectMany(r => r).ToList(); } else { loaded = await DoLoad(ids); } if (mode.EntityLoadMode == PostStoreEntityLoadMode.Full) { await FillChildrenInLoadResult(loaded); } return(loaded); }
private async ValueTask <Nothing> SetChildren(IBoardPostEntity entity) { if (entity == null) { return(Nothing.Value); } ValueTask <List <IBoardPostEntity> > DoLoad(IList <(PostStoreEntityId id, int counter)> toLoad) { return(OpenSession(session => { var result = new List <IBoardPostEntity>(); var loadContext = CreateLoadContext(session, true, true); var loadContextToDispose = loadContext; using (loadContextToDispose) { foreach (var id in toLoad) { Api.MakeKey(loadContext.table.Session, loadContext.table, id.id.Id, MakeKeyGrbit.NewKey); if (Api.TrySeek(loadContext.table.Session, loadContext.table, SeekGrbit.SeekEQ)) { var r = LoadBoardEntity(session, ref loadContext, FullLoadMode); if (r is IBoardPostLight l) { l.Counter = id.counter; } result.Add(r); } } } return result; })); } var collection = entity as IBoardPostCollection; var threadCollection = entity as IBoardPageThreadCollection; if ((entity.EntityType == PostStoreEntityType.Thread || entity.EntityType == PostStoreEntityType.ThreadPreview || entity.EntityType == PostStoreEntityType.Catalog || entity.EntityType == PostStoreEntityType.BoardPage) && entity is IPostModelStoreChildrenLoadStageInfo loadStage && (collection?.Posts != null || threadCollection?.Threads != null) && entity.StoreId != null) { if (loadStage.Stage == ChildrenLoadStageId.Completed) { var childrenIds = await OpenSession(session0 => EnumEntityChildren(session0, entity.StoreId.Value)); IList <IBoardPostEntity> loaded; if (childrenIds.Count > 4) { var toLoad = childrenIds.DistributeToProcess(3); var tasks = toLoad.Select(DoLoad).ToArray(); var taskResults = await CoreTaskHelper.WhenAllValueTasks(tasks); loaded = taskResults.SelectMany(r => r).ToList(); } else { loaded = await DoLoad(childrenIds); } if (collection?.Posts != null) { IEnumerable <IBoardPost> toAdd; if (entity.EntityType == PostStoreEntityType.Catalog) { int GetCatalogSequence(IBoardPost p) { if (p is IBoardPostEntityWithSequence s) { return(s.OnPageSequence); } return(int.MaxValue); } toAdd = loaded.OfType <IBoardPost>().Deduplicate(p => p.Link, BoardLinkEqualityComparer.Instance).OrderBy(GetCatalogSequence); } else { toAdd = loaded.OfType <IBoardPost>().Deduplicate(p => p.Link, BoardLinkEqualityComparer.Instance).OrderBy(p => p.Link, BoardLinkComparer.Instance); } foreach (var item in toAdd) { collection.Posts.Add(item); } } if (threadCollection?.Threads != null) { var toAdd = loaded.OfType <IThreadPreviewPostCollection>().Deduplicate(p => p.Link, BoardLinkEqualityComparer.Instance).OrderBy(p => p.OnPageSequence); foreach (var item in toAdd) { threadCollection.Threads.Add(item); } } } } return(Nothing.Value); }