/// <summary> /// Find all artists involved with release and update their rank /// </summary> protected async Task UpdateArtistsRankForRelease(data.Release release) { if (release != null) { var artistsForRelease = new List <int> { release.ArtistId }; var trackArtistsForRelease = (from t in DbContext.Tracks join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id where rm.ReleaseId == release.Id where t.ArtistId.HasValue select t.ArtistId.Value).ToArray(); artistsForRelease.AddRange(trackArtistsForRelease); foreach (var artistId in artistsForRelease.Distinct()) { await UpdateArtistRank(artistId); } } }
public async Task <OperationResult <bool> > ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = false, bool doUpdateRanks = true) { var sw = new Stopwatch(); sw.Start(); var releaseIdsInCollection = new List <int>(); var updatedReleaseIds = new List <int>(); var result = new List <data.PositionArtistRelease>(); var errors = new List <Exception>(); var collection = DbContext.Collections.FirstOrDefault(x => x.RoadieId == collectionId); if (collection == null) { await LogAndPublish($"ScanCollection Unknown Collection [{collectionId}]", LogLevel.Warning); return(new OperationResult <bool>(true, $"Collection Not Found [{collectionId}]")); } try { if (doPurgeFirst) { await LogAndPublish($"ScanCollection Purgeing Collection [{collectionId}]", LogLevel.Warning); var crs = DbContext.CollectionReleases.Where(x => x.CollectionId == collection.Id).ToArray(); DbContext.CollectionReleases.RemoveRange(crs); await DbContext.SaveChangesAsync(); } var collectionMissingRecords = DbContext.CollectionMissings.Where(x => x.CollectionId == collection.Id); DbContext.CollectionMissings.RemoveRange(collectionMissingRecords); await DbContext.SaveChangesAsync(); var par = collection.PositionArtistReleases(); if (par != null) { var now = DateTime.UtcNow; foreach (var csvRelease in par) { data.Artist artist = null; data.Release release = null; var searchName = csvRelease.Artist.NormalizeName(); var specialSearchName = csvRelease.Artist.ToAlphanumericName(); var artistResults = (from a in DbContext.Artists where a.Name.Contains(searchName) || a.SortName.Contains(searchName) || a.AlternateNames.Contains(searchName) || a.AlternateNames.Contains(specialSearchName) select a).ToArray(); if (!artistResults.Any()) { await LogAndPublish( $"Unable To Find Artist [{csvRelease.Artist}], SearchName [{searchName}]", LogLevel.Warning); csvRelease.Status = Statuses.Missing; DbContext.CollectionMissings.Add(new data.CollectionMissing { CollectionId = collection.Id, Position = csvRelease.Position, Artist = searchName, Release = csvRelease.Release.NormalizeName() }); continue; } foreach (var artistResult in artistResults) { artist = artistResult; searchName = csvRelease.Release.NormalizeName().ToLower(); specialSearchName = csvRelease.Release.ToAlphanumericName(); release = (from r in DbContext.Releases where r.ArtistId == artist.Id where r.Title.Contains(searchName) || r.AlternateNames.Contains(searchName) || r.AlternateNames.Contains(specialSearchName) select r ).FirstOrDefault(); if (release != null) { break; } } if (release == null) { await LogAndPublish( $"Unable To Find Release [{csvRelease.Release}] for Artist [{csvRelease.Artist}], SearchName [{searchName}]", LogLevel.Warning); csvRelease.Status = Statuses.Missing; DbContext.CollectionMissings.Add(new data.CollectionMissing { CollectionId = collection.Id, IsArtistFound = true, Position = csvRelease.Position, Artist = csvRelease.Artist, Release = searchName }); continue; } var isInCollection = DbContext.CollectionReleases.FirstOrDefault(x => x.CollectionId == collection.Id && x.ListNumber == csvRelease.Position && x.ReleaseId == release.Id); var updated = false; // Found in Database but not in collection add to Collection if (isInCollection == null) { DbContext.CollectionReleases.Add(new data.CollectionRelease { CollectionId = collection.Id, ReleaseId = release.Id, ListNumber = csvRelease.Position }); updated = true; } // If Item in Collection is at different List number update CollectionRelease else if (isInCollection.ListNumber != csvRelease.Position) { isInCollection.LastUpdated = now; isInCollection.ListNumber = csvRelease.Position; updated = true; } if (updated && !updatedReleaseIds.Any(x => x == release.Id)) { updatedReleaseIds.Add(release.Id); } releaseIdsInCollection.Add(release.Id); } collection.LastUpdated = now; await DbContext.SaveChangesAsync(); var dto = new CollectionList { CollectionCount = collection.CollectionCount, CollectionFoundCount = (from cr in DbContext.CollectionReleases where cr.CollectionId == collection.Id select cr.CollectionId).Count() }; if (dto.PercentComplete == 100) { // Lock so future implicit scans dont happen, with DB RI when releases are deleted they are removed from collection collection.IsLocked = true; collection.Status = Statuses.Complete; } else { collection.Status = Statuses.Incomplete; } var collectionReleasesToRemove = (from cr in DbContext.CollectionReleases where cr.CollectionId == collection.Id where !releaseIdsInCollection.Contains(cr.ReleaseId) select cr).ToArray(); if (collectionReleasesToRemove.Any()) { await LogAndPublish( $"Removing [{collectionReleasesToRemove.Count()}] Stale Release Records from Collection.", LogLevel.Information); DbContext.CollectionReleases.RemoveRange(collectionReleasesToRemove); } await DbContext.SaveChangesAsync(); if (doUpdateRanks) { foreach (var updatedReleaseId in updatedReleaseIds) { await UpdateReleaseRank(updatedReleaseId); } } CacheManager.ClearRegion(collection.CacheRegion); } } catch (Exception ex) { Logger.LogError(ex); errors.Add(ex); } sw.Stop(); Logger.LogInformation(string.Format("RescanCollection `{0}`, By User `{1}`, ElapsedTime [{2}]", collection, user, sw.ElapsedMilliseconds)); return(new OperationResult <bool> { AdditionalData = new Dictionary <string, object> { { "updatedReleaseIds", updatedReleaseIds.ToArray() } }, IsSuccess = !errors.Any(), Data = true, OperationTime = sw.ElapsedMilliseconds, Errors = errors }); }