Skip to content

Commit

Permalink
Refactor file handling and improve performance in FileDao
Browse files Browse the repository at this point in the history
The code refactor includes moving the declaration of currentRoom to a narrower scope, for better resource management. Moreover, I improved the performance in file handling by retrieving parent folders for multiple files in a single database call, instead of making separate calls for each file in the DocumentService. This should significantly reduce the time needed to retrieve parent folder information, especially when dealing with a large number of files.
  • Loading branch information
pavelbannov committed Mar 1, 2024
1 parent c777ae0 commit 81dfdb6
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 57 deletions.
107 changes: 53 additions & 54 deletions products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs
Original file line number Diff line number Diff line change
Expand Up @@ -377,10 +377,9 @@ public async Task<File<int>> SaveFileAsync(File<int> file, Stream fileStream, bo

var (roomId, _) = await folderDao.GetParentRoomInfoFromFileEntryAsync(currentFolder);

Folder<int> currentRoom = null;
if (roomId != -1)
{
currentRoom = await folderDao.GetFolderAsync(roomId);
var currentRoom = await folderDao.GetFolderAsync(roomId);
var quotaRoomSettings = await _settingsManager.LoadAsync<TenantRoomQuotaSettings>();
if (quotaRoomSettings.EnableQuota)
{
Expand Down Expand Up @@ -509,7 +508,7 @@ await strategy.ExecuteAsync(async () =>
{
try
{
await SaveFileStreamAsync(file, fileStream);
await SaveFileStreamAsync(file, fileStream, currentFolder);
}
catch (Exception saveException)
{
Expand Down Expand Up @@ -582,66 +581,66 @@ public async Task<File<int>> ReplaceFileVersionAsync(File<int> file, Stream file

await using (await distributedLockProvider.TryAcquireFairLockAsync(LockKey))
{
await using var filesDbContext = await _dbContextFactory.CreateDbContextAsync();
var strategy = filesDbContext.Database.CreateExecutionStrategy();
await using var filesDbContext = await _dbContextFactory.CreateDbContextAsync();
var strategy = filesDbContext.Database.CreateExecutionStrategy();

await strategy.ExecuteAsync(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
await using var tx = await context.Database.BeginTransactionAsync();
await strategy.ExecuteAsync(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
await using var tx = await context.Database.BeginTransactionAsync();

file.Title = Global.ReplaceInvalidCharsAndTruncate(file.Title);
//make lowerCase
file.Title = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetFileExtension(file.Title));
file.Title = Global.ReplaceInvalidCharsAndTruncate(file.Title);
//make lowerCase
file.Title = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetFileExtension(file.Title));

file.ModifiedBy = _authContext.CurrentAccount.ID;
file.ModifiedOn = _tenantUtil.DateTimeNow();
if (file.CreateBy == default)
{
file.CreateBy = _authContext.CurrentAccount.ID;
}
file.ModifiedBy = _authContext.CurrentAccount.ID;
file.ModifiedOn = _tenantUtil.DateTimeNow();
if (file.CreateBy == default)
{
file.CreateBy = _authContext.CurrentAccount.ID;
}

if (file.CreateOn == default)
{
file.CreateOn = _tenantUtil.DateTimeNow();
}
if (file.CreateOn == default)
{
file.CreateOn = _tenantUtil.DateTimeNow();
}

toUpdate = await Queries.DbFileByVersionAsync(context, tenantId, file.Id, file.Version);

toUpdate.Version = file.Version;
toUpdate.VersionGroup = file.VersionGroup;
toUpdate.ParentId = file.ParentId;
toUpdate.Title = file.Title;
toUpdate.ContentLength = file.ContentLength;
toUpdate.Category = (int)file.FilterType;
toUpdate.CreateBy = file.CreateBy;
toUpdate.CreateOn = _tenantUtil.DateTimeToUtc(file.CreateOn);
toUpdate.ModifiedBy = file.ModifiedBy;
toUpdate.ModifiedOn = _tenantUtil.DateTimeToUtc(file.ModifiedOn);
toUpdate.ConvertedType = file.ConvertedType;
toUpdate.Comment = file.Comment;
toUpdate.Encrypted = file.Encrypted;
toUpdate.Forcesave = file.Forcesave;
toUpdate.ThumbnailStatus = file.ThumbnailStatus;

context.Update(toUpdate);
await context.SaveChangesAsync();
toUpdate = await Queries.DbFileByVersionAsync(context, tenantId, file.Id, file.Version);

toUpdate.Version = file.Version;
toUpdate.VersionGroup = file.VersionGroup;
toUpdate.ParentId = file.ParentId;
toUpdate.Title = file.Title;
toUpdate.ContentLength = file.ContentLength;
toUpdate.Category = (int)file.FilterType;
toUpdate.CreateBy = file.CreateBy;
toUpdate.CreateOn = _tenantUtil.DateTimeToUtc(file.CreateOn);
toUpdate.ModifiedBy = file.ModifiedBy;
toUpdate.ModifiedOn = _tenantUtil.DateTimeToUtc(file.ModifiedOn);
toUpdate.ConvertedType = file.ConvertedType;
toUpdate.Comment = file.Comment;
toUpdate.Encrypted = file.Encrypted;
toUpdate.Forcesave = file.Forcesave;
toUpdate.ThumbnailStatus = file.ThumbnailStatus;

context.Update(toUpdate);
await context.SaveChangesAsync();

await tx.CommitAsync();
});
await tx.CommitAsync();
});

file.PureTitle = file.Title;
file.PureTitle = file.Title;

var parentFolders = await Queries.DbFolderTeesAsync(filesDbContext, file.ParentId).ToListAsync();
var parentFolders = await Queries.DbFolderTeesAsync(filesDbContext, file.ParentId).ToListAsync();

var parentFoldersIds = parentFolders.Select(r => r.ParentId).ToList();
var parentFoldersIds = parentFolders.Select(r => r.ParentId).ToList();

if (parentFoldersIds.Count > 0)
{
await Queries.UpdateFoldersAsync(filesDbContext, parentFoldersIds, _tenantUtil.DateTimeToUtc(file.ModifiedOn), file.ModifiedBy, tenantId);
}
if (parentFoldersIds.Count > 0)
{
await Queries.UpdateFoldersAsync(filesDbContext, parentFoldersIds, _tenantUtil.DateTimeToUtc(file.ModifiedOn), file.ModifiedBy, tenantId);
}

toUpdate.Folders = parentFolders;
toUpdate.Folders = parentFolders;
}

if (fileStream != null)
Expand Down Expand Up @@ -700,13 +699,13 @@ private async Task DeleteVersionStreamAsync(File<int> file)
await store.DeleteDirectoryAsync(GetUniqFileVersionPath(file.Id, file.Version));
}

private async Task SaveFileStreamAsync(File<int> file, Stream stream)
private async Task SaveFileStreamAsync(File<int> file, Stream stream, Folder<int> currentFolder = null)
{
var folderDao = daoFactory.GetFolderDao<int>();

await (await globalStore.GetStoreAsync()).SaveAsync(string.Empty, GetUniqFilePath(file), file.GetFileQuotaOwner(), stream, file.Title);

var currentFolder = await folderDao.GetFolderAsync(file.FolderIdDisplay);
currentFolder ??= await folderDao.GetFolderAsync(file.FolderIdDisplay);

await folderDao.ChangeTreeFolderSizeAsync(currentFolder.Id, file.ContentLength);
}
Expand Down
13 changes: 10 additions & 3 deletions products/ASC.Files/Core/Services/DocumentService/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,19 @@ public async IAsyncEnumerable<RecentConfig> GetRecent(FileType fileType, T fileI
};

var folderDao = daoFactory.GetFolderDao<int>();
var files = (await entryManager.GetRecentAsync(filter, false, Guid.Empty, string.Empty, null, false)).Cast<File<int>>();
foreach (var file in files.Where(file => !Equals(fileId, file.Id)))
var files = (await entryManager.GetRecentAsync(filter, false, Guid.Empty, string.Empty, null, false))
.Cast<File<int>>()
.Where(file => !Equals(fileId, file.Id))
.ToList();

var parentIds = files.Select(r => r.ParentId).Distinct().ToList();
var parentFolders = await folderDao.GetFoldersAsync(parentIds).ToListAsync();

foreach (var file in files)
{
yield return new RecentConfig
{
Folder = (await folderDao.GetFolderAsync(file.ParentId)).Title,
Folder = parentFolders.Find(r => file.ParentId == r.Id).Title,
Title = file.Title,
Url = baseCommonLinkUtility.GetFullAbsolutePath(filesLinkUtility.GetFileWebEditorUrl(file.Id))
};
Expand Down

0 comments on commit 81dfdb6

Please sign in to comment.