From 73f585253ac97a2722507dce82533991b4e97cdc Mon Sep 17 00:00:00 2001 From: Hamid Reza Mohammadi Date: Sun, 3 Oct 2021 14:29:52 +0330 Subject: [PATCH] #217 actual counting --- RMuseum/RMuseum.xml | 14 +- .../Implementation/GanjoorNumberingService.cs | 145 +++++++++++++++++- 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml index d447f83a..0dc1029a 100644 --- a/RMuseum/RMuseum.xml +++ b/RMuseum/RMuseum.xml @@ -9917,16 +9917,28 @@ + + + start counting + + + Database Context - + + + Background Task Queue Instance + + + constructor + diff --git a/RMuseum/Services/Implementation/GanjoorNumberingService.cs b/RMuseum/Services/Implementation/GanjoorNumberingService.cs index 4469bd3a..15332dbb 100644 --- a/RMuseum/Services/Implementation/GanjoorNumberingService.cs +++ b/RMuseum/Services/Implementation/GanjoorNumberingService.cs @@ -2,7 +2,10 @@ using RMuseum.DbContext; using RMuseum.Models.Ganjoor; using RSecurityBackend.Models.Generic; +using RSecurityBackend.Services; +using RSecurityBackend.Services.Implementation; using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -30,6 +33,7 @@ namespace RMuseum.Services.Implementation { _context.GanjoorNumberings.Add(numbering); await _context.SaveChangesAsync(); + Count(numbering.Id); //start counting return new RServiceResult(numbering); } catch (Exception exp) @@ -144,7 +148,7 @@ namespace RMuseum.Services.Implementation { try { - var subcatIds = await _context.GanjoorCategories.Where(c => c.ParentId == parentCatId).Select(c => c.Id).ToListAsync(); + var subcatIds = await _context.GanjoorCategories.AsNoTracking().Where(c => c.ParentId == parentCatId).Select(c => c.Id).ToListAsync(); return new RServiceResult(await _context.GanjoorNumberings.Where(n => subcatIds.Contains(n.StartCatId)).OrderBy(l => l.Id).ToArrayAsync()); } catch (Exception exp) @@ -153,18 +157,155 @@ namespace RMuseum.Services.Implementation } } + private async Task> _FindAllSubCategories(RMuseumDbContext context, int catId) + { + List cats = new List(); + + foreach (var cat in await context.GanjoorCategories.AsNoTracking().Where(c => c.ParentId == catId).OrderBy(c => c.Id).ToListAsync()) + { + cats.Add(cat); + + var subCats = await _FindAllSubCategories(context, cat.Id); + + if(subCats.Count > 0) + { + cats.AddRange(subCats); + } + } + return cats; + } + + private async Task> _FindCategoryRanges(RMuseumDbContext context, GanjoorCat startCat, int endCatId) + { + var parents = await context.GanjoorCategories.AsNoTracking().Where(c => c.ParentId == startCat.ParentId && c.Id >= startCat.Id && c.Id <= endCatId).OrderBy(c => c.Id).ToListAsync(); + List cats = new List(); + foreach(GanjoorCat parentCat in parents) + { + cats.Add(parentCat); + var subCats = await _FindAllSubCategories(context, parentCat.Id); + if(subCats.Count > 0) + { + cats.AddRange(subCats); + } + } + return cats; + } + + + private async Task> _FindTargetCategories(RMuseumDbContext context, GanjoorCat startCat, int? endCatId) + { + if(endCatId == null || startCat.Id == endCatId) + { + List cats = new List(); + cats.Add(startCat); + cats.AddRange(await _FindAllSubCategories(context, startCat.Id)); + return cats; + } + else + { + return await _FindCategoryRanges(context, startCat, (int)endCatId); + } + } + + /// + /// start counting + /// + /// + public RServiceResult Count(int numberingId) + { + _backgroundTaskQueue.QueueBackgroundWorkItem + ( + async token => + { + using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions())) //this is long running job, so _context might be already been freed/collected by GC + { + LongRunningJobProgressServiceEF jobProgressServiceEF = new LongRunningJobProgressServiceEF(context); + var job = (await jobProgressServiceEF.NewJob("NumberingService::Count", "Query Cats")).Result; + + try + { + var numbering = await context.GanjoorNumberings.Include(n => n.StartCat).Where(n => n.Id == numberingId).SingleOrDefaultAsync(); + var cats = await _FindTargetCategories(context, numbering.StartCat, numbering.EndCatId); + + await jobProgressServiceEF.UpdateJob(job.Id, 0, "Deleting Old Data"); + + var oldNumbers = await context.GanjoorVerseNumbers.Where(n => n.NumberingId == numberingId).ToListAsync(); + context.GanjoorVerseNumbers.RemoveRange(oldNumbers); + await context.SaveChangesAsync(); + + await jobProgressServiceEF.UpdateJob(job.Id, 0, "Counting"); + + int number = 0; + int totalVerseCount = 0; + + foreach (var cat in cats) + { + var poems = await context.GanjoorPoems.AsNoTracking().Where(p => p.CatId == cat.Id).OrderBy(p => p.Id).ToListAsync(); + + await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Counting:: {cat.Title}"); + + foreach(var poem in poems) + { + totalVerseCount += await context.GanjoorVerses.Where(v => v.PoemId == poem.Id).CountAsync(); + var verses = await context.GanjoorVerses.AsNoTracking() + .Where(v => v.PoemId == poem.Id && (v.VersePosition == VersePosition.Right || v.VersePosition == VersePosition.CenteredVerse1)) + .OrderBy(v => v.VOrder) + .ToListAsync(); + for (int coupletIndex = 0; coupletIndex < verses.Count; coupletIndex++) + { + number++; + GanjoorVerseNumber verseNumber = new GanjoorVerseNumber() + { + NumberingId = numberingId, + PoemId = poem.Id, + CoupletIndex = coupletIndex, + Number = number + }; + context.GanjoorVerseNumbers.Add(verseNumber); + } + } + } + + numbering.TotalCouplets = number; + numbering.TotalVerses = totalVerseCount; + numbering.LastCountingDate = DateTime.Now; + context.GanjoorNumberings.Update(numbering); + + await context.SaveChangesAsync(); + + await jobProgressServiceEF.UpdateJob(job.Id, 100, "", true); + } + catch (Exception exp) + { + await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, exp.ToString()); + } + + } + } + ); + + return new RServiceResult(true); + } + /// /// Database Context /// protected readonly RMuseumDbContext _context; + /// + /// Background Task Queue Instance + /// + protected readonly IBackgroundTaskQueue _backgroundTaskQueue; + /// /// constructor /// /// - public GanjoorNumberingService(RMuseumDbContext context) + /// + public GanjoorNumberingService(RMuseumDbContext context, IBackgroundTaskQueue backgroundTaskQueue) { _context = context; + _backgroundTaskQueue = backgroundTaskQueue; } } }