1
0
mirror of https://github.com/bitwarden/server synced 2025-12-27 13:43:18 +00:00

[PM-12642] Add new ExtendedCache to add caching to template parameters (#6608)

* Add new ExtendedCache to add caching to template parameters

* Added Cache constants for building consistent keys/name, clarified that we are using defaults including TTL, removed as much fusion cache references as possible
This commit is contained in:
Brant DeBow
2025-11-25 10:58:39 -05:00
committed by GitHub
parent f0f10bcb95
commit 1413dd7689
6 changed files with 353 additions and 108 deletions

View File

@@ -1,11 +1,15 @@
using System.Text.Json;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Models.Data.EventIntegrations;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.AdminConsole.Utilities;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Repositories;
using Bit.Core.Utilities;
using Microsoft.Extensions.Logging;
using ZiggyCreatures.Caching.Fusion;
namespace Bit.Core.Services;
@@ -14,6 +18,7 @@ public class EventIntegrationHandler<T>(
IEventIntegrationPublisher eventIntegrationPublisher,
IIntegrationFilterService integrationFilterService,
IIntegrationConfigurationDetailsCache configurationCache,
IFusionCache cache,
IGroupRepository groupRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
@@ -87,13 +92,18 @@ public class EventIntegrationHandler<T>(
}
}
private async Task<IntegrationTemplateContext> BuildContextAsync(EventMessage eventMessage, string template)
internal async Task<IntegrationTemplateContext> BuildContextAsync(EventMessage eventMessage, string template)
{
// Note: All of these cache calls use the default options, including TTL of 30 minutes
var context = new IntegrationTemplateContext(eventMessage);
if (IntegrationTemplateProcessor.TemplateRequiresGroup(template) && eventMessage.GroupId.HasValue)
{
context.Group = await groupRepository.GetByIdAsync(eventMessage.GroupId.Value);
context.Group = await cache.GetOrSetAsync<Group?>(
key: EventIntegrationsCacheConstants.BuildCacheKeyForGroup(eventMessage.GroupId.Value),
factory: async _ => await groupRepository.GetByIdAsync(eventMessage.GroupId.Value)
);
}
if (eventMessage.OrganizationId is not Guid organizationId)
@@ -103,25 +113,31 @@ public class EventIntegrationHandler<T>(
if (IntegrationTemplateProcessor.TemplateRequiresUser(template) && eventMessage.UserId.HasValue)
{
context.User = await organizationUserRepository.GetDetailsByOrganizationIdUserIdAsync(
organizationId: organizationId,
userId: eventMessage.UserId.Value
);
context.User = await GetUserFromCacheAsync(organizationId, eventMessage.UserId.Value);
}
if (IntegrationTemplateProcessor.TemplateRequiresActingUser(template) && eventMessage.ActingUserId.HasValue)
{
context.ActingUser = await organizationUserRepository.GetDetailsByOrganizationIdUserIdAsync(
organizationId: organizationId,
userId: eventMessage.ActingUserId.Value
);
context.ActingUser = await GetUserFromCacheAsync(organizationId, eventMessage.ActingUserId.Value);
}
if (IntegrationTemplateProcessor.TemplateRequiresOrganization(template))
{
context.Organization = await organizationRepository.GetByIdAsync(organizationId);
context.Organization = await cache.GetOrSetAsync<Organization?>(
key: EventIntegrationsCacheConstants.BuildCacheKeyForOrganization(organizationId),
factory: async _ => await organizationRepository.GetByIdAsync(organizationId)
);
}
return context;
}
private async Task<OrganizationUserUserDetails?> GetUserFromCacheAsync(Guid organizationId, Guid userId) =>
await cache.GetOrSetAsync<OrganizationUserUserDetails?>(
key: EventIntegrationsCacheConstants.BuildCacheKeyForOrganizationUser(organizationId, userId),
factory: async _ => await organizationUserRepository.GetDetailsByOrganizationIdUserIdAsync(
organizationId: organizationId,
userId: userId
)
);
}