diff --git a/server/AyaNova/biz/AttachmentBiz.cs b/server/AyaNova/biz/AttachmentBiz.cs index 76a8c123..e0c90844 100644 --- a/server/AyaNova/biz/AttachmentBiz.cs +++ b/server/AyaNova/biz/AttachmentBiz.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging; using System; using Microsoft.EntityFrameworkCore; using System.Linq; +using System.Collections.Generic; namespace AyaNova.Biz @@ -64,53 +65,78 @@ namespace AyaNova.Biz await JobsBiz.LogJobAsync(job.GId, $"Starting..."); apiServerState.SetOpsOnly("Attachment file maintenance"); - - + //get a list of all attachment files currently on disk + var AllAttachmentFilesOnDisk = FileUtil.GetAllAttachmentFilePaths(); + List AllDBFileFullPath = new List(); // EXISTENCE CHECK - //iterate all records in chunks + //iterate all records in chunks, update the existence bool field if it's incorrect only bool moreRecords = true; int skip = 0; int chunkSize = 100; do { - var chunk = await ct.FileAttachment.AsNoTracking().OrderBy(z => z.Id).Skip(skip).Take(chunkSize).Select(z => new NameIdItem { Id = z.Id, Name = z.StoredFileName }).ToListAsync(); + var chunk = await ct.FileAttachment.AsNoTracking().OrderBy(z => z.Id).Skip(skip).Take(chunkSize).Select(z => new { z.Id, z.StoredFileName, z.Exists }).ToListAsync(); if (chunk.Count < chunkSize) { //we've reached the end moreRecords = false; } skip += chunkSize; - foreach (NameIdItem i in chunk) + foreach (var i in chunk) { - //Does file exists where it's supposed to be? - if (!FileUtil.AttachmentFileExists(i.Name)) + var FullPathName = FileUtil.GetPermanentAttachmentFilePath(i.StoredFileName); + AllDBFileFullPath.Add(FullPathName); + var FileExistsInReality = AllAttachmentFilesOnDisk.Contains(FullPathName); + //does the db record reflect the same status as reality? + if (FileExistsInReality != i.Exists) { + //Nope so update it to be the same var f = await ct.FileAttachment.FirstOrDefaultAsync(z => z.Id == i.Id); if (f != null) { - f.Exists = false; + f.Exists = FileExistsInReality; await ct.SaveChangesAsync(); } - } + } } } while (moreRecords); - // long totalRecs = await ct.FileAttachment.LongCountAsync(); - var allAttachments = FileUtil.GetAllAttachmentFilePaths(); + //I kept this block because I did a lot of work to figure it out but in the end I don't need it because + //a user will be moving attachments so they would no longer be existing on their old NOTYPE orphan location anyway + // //DE-ORPHANIZE ACTION (clean up former orphans) + // //people can attach an orphan to another record so this cleans that up + // //also, potentiallly + // //iterate orphaned file attachments to NOTHING type, if found to be attached to any other object remove the orphaned object attachment record in db + // //but keeping the physical file since it's attached to something else + // var AllOrphansInDb = await ct.FileAttachment.Where(z => z.AttachToObjectType == AyaType.NoType).ToListAsync(); + // foreach (FileAttachment OrphanInDb in AllOrphansInDb) + // { + // if (await ct.FileAttachment.AnyAsync(z => z.StoredFileName==OrphanInDb.StoredFileName && z.AttachToObjectType != AyaType.NoType)) + // { + // //It is also attached to something else so remove it from the nothing type + // ct.FileAttachment.Remove(OrphanInDb); + // await ct.SaveChangesAsync(); + // } + // } - // iterate FileAttachment records, if physically present then flag as such - // make sure it has a short circuit that if there are NO files physically then all are out of sync - // this scenario is someone moving a db and not moving physical files // ORPHANED FILES CHECK - // These should never be out of sync due to timing issues, the file would be deleted before teh db record - // iterate physical files, if not in db then make a FileAttachment record for it AyaType nothing id 0 - // if user want's to move them, they can download and then attach and then remove the generated attachment (Nothing id 0) the holder of orphaned files - // (Or move feature) - // DE-ORPHANIZE ACTION - // iterate orphaned file attachments to NOTHING type, if found to be attached to any other object remove the orphaned object attachement - + var FilesOnDiskNotInDb = AllAttachmentFilesOnDisk.Except(AllDBFileFullPath); + //Attach any found into the NOTHING object type with id 0 so they will be represented in attachment list for being dealt with + foreach (string orphan in FilesOnDiskNotInDb) + { + FileAttachment fa = new FileAttachment(); + fa.AttachToObjectId = 0; + fa.AttachToObjectType = AyaType.NoType; + fa.ContentType = "application/octet-stream";//most generic type, we don't know what it is + fa.DisplayFileName = "FOUND" + FileUtil.GetSafeDateFileName(); + fa.LastModified = DateTime.UtcNow; + fa.Notes = "Found in attachments folder not linked to an object"; + fa.StoredFileName = System.IO.Path.GetFileName(orphan); + await ct.FileAttachment.AddAsync(fa); + await ct.SaveChangesAsync(); + } await JobsBiz.LogJobAsync(job.GId, "Finished.");