From 056f850268196d1b8524761e9d2bad35c0f41946 Mon Sep 17 00:00:00 2001 From: Nicolas Dorier Date: Wed, 25 Sep 2024 23:10:13 +0900 Subject: [PATCH] Optimize load time of StoreRoles related pages/routes (#6245) --- .../GreenfieldServerRolesController.cs | 2 +- .../GreenfieldStoreRolesController.cs | 2 +- .../Controllers/UIServerController.Roles.cs | 2 +- .../Controllers/UIStoresController.Roles.cs | 2 +- .../Services/Stores/StoreRepository.cs | 21 ++++++++++++------- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldServerRolesController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldServerRolesController.cs index 3db6c1dfa..7448b76a4 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldServerRolesController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldServerRolesController.cs @@ -28,7 +28,7 @@ public class GreenfieldServerRolesController : ControllerBase [HttpGet("~/api/v1/server/roles")] public async Task GetServerRoles() { - return Ok(FromModel(await _storeRepository.GetStoreRoles(null, false, false))); + return Ok(FromModel(await _storeRepository.GetStoreRoles(null, false))); } private List FromModel(StoreRepository.StoreRole[] data) { diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreRolesController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreRolesController.cs index 5c6919866..14621f5fe 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreRolesController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreRolesController.cs @@ -31,7 +31,7 @@ namespace BTCPayServer.Controllers.Greenfield var store = HttpContext.GetStoreData(); return store == null ? StoreNotFound() - : Ok(FromModel(await _storeRepository.GetStoreRoles(storeId, false, false))); + : Ok(FromModel(await _storeRepository.GetStoreRoles(storeId, false))); } private List FromModel(StoreRepository.StoreRole[] data) diff --git a/BTCPayServer/Controllers/UIServerController.Roles.cs b/BTCPayServer/Controllers/UIServerController.Roles.cs index e4a2ea254..1e9f40405 100644 --- a/BTCPayServer/Controllers/UIServerController.Roles.cs +++ b/BTCPayServer/Controllers/UIServerController.Roles.cs @@ -19,7 +19,7 @@ namespace BTCPayServer.Controllers string sortOrder = null ) { - var roles = await _StoreRepository.GetStoreRoles(null, true); + var roles = await _StoreRepository.GetStoreRoles(null); var defaultRole = (await _StoreRepository.GetDefaultRole()).Role; model ??= new RolesViewModel(); model.DefaultRole = defaultRole; diff --git a/BTCPayServer/Controllers/UIStoresController.Roles.cs b/BTCPayServer/Controllers/UIStoresController.Roles.cs index b5bc9c34a..ea7a34e72 100644 --- a/BTCPayServer/Controllers/UIStoresController.Roles.cs +++ b/BTCPayServer/Controllers/UIStoresController.Roles.cs @@ -21,7 +21,7 @@ public partial class UIStoresController string sortOrder = null ) { - var roles = await storeRepository.GetStoreRoles(storeId, true); + var roles = await storeRepository.GetStoreRoles(storeId); var defaultRole = (await storeRepository.GetDefaultRole()).Role; model ??= new RolesViewModel(); model.DefaultRole = defaultRole; diff --git a/BTCPayServer/Services/Stores/StoreRepository.cs b/BTCPayServer/Services/Stores/StoreRepository.cs index 277dd1423..a6ecb3311 100644 --- a/BTCPayServer/Services/Stores/StoreRepository.cs +++ b/BTCPayServer/Services/Stores/StoreRepository.cs @@ -14,6 +14,7 @@ using Microsoft.EntityFrameworkCore; using NBitcoin; using NBitcoin.DataEncoders; using Newtonsoft.Json; +using static BTCPayServer.Services.Stores.StoreRepository; namespace BTCPayServer.Services.Stores { @@ -81,14 +82,20 @@ namespace BTCPayServer.Services.Stores public bool? IsUsed { get; set; } } #nullable enable - public async Task GetStoreRoles(string? storeId, bool includeUsers = false, bool storeOnly = false) + public async Task GetStoreRoles(string? storeId, bool storeOnly = false) { await using var ctx = _ContextFactory.CreateContext(); - var query = ctx.StoreRoles.Where(u => (storeOnly && u.StoreDataId == storeId) || (!storeOnly && (u.StoreDataId == null || u.StoreDataId == storeId))); - if (includeUsers) - { - query = query.Include(u => u.Users); - } + var query = ctx.StoreRoles + .Where(u => (storeOnly && u.StoreDataId == storeId) || (!storeOnly && (u.StoreDataId == null || u.StoreDataId == storeId))) + // Not calling ToStoreRole here because we don't want to load users in the DB query + .Select(u => new StoreRole() + { + Id = u.Id, + Role = u.Role, + Permissions = u.Permissions, + IsServerRole = u.StoreDataId == null, + IsUsed = u.Users.Any() + }); var roles = await query.ToArrayAsync(); // return ordered: default role comes first, then server-wide roles in specified order, followed by store roles @@ -99,7 +106,7 @@ namespace BTCPayServer.Services.Stores if (role.Role == defaultRole.Role) return -1; int index = Array.IndexOf(defaultOrder, role.Role); return index == -1 ? int.MaxValue : index; - }).Select(ToStoreRole).ToArray(); + }).ToArray(); } public async Task GetDefaultRole()