From d8081b2694a96907e0a679ef42540baa25032b96 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Wed, 12 Feb 2025 16:20:20 +0200 Subject: [PATCH] add roleSetCacheService --- alkemio.yml | 2 + .../access/role-set/role.set.cache.service.ts | 65 +++++++++++++++++++ src/domain/access/role-set/role.set.module.ts | 2 + .../access/role-set/role.set.service.ts | 47 ++++++++------ src/types/alkemio.config.ts | 3 + 5 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 src/domain/access/role-set/role.set.cache.service.ts diff --git a/alkemio.yml b/alkemio.yml index 6c0afcbf4..6e5af8758 100644 --- a/alkemio.yml +++ b/alkemio.yml @@ -397,6 +397,8 @@ notifications: enabled: ${NOTIFICATIONS_ENABLED}:true collaboration: + memberships: + cache_ttl: ${MEMBERSHIP_TTL}:300 whiteboards: enabled: ${WHITEBOARDS_ENABLED}:true # the window in which contributions are accepted to be counted towards a single contribution event; diff --git a/src/domain/access/role-set/role.set.cache.service.ts b/src/domain/access/role-set/role.set.cache.service.ts new file mode 100644 index 000000000..efd317c14 --- /dev/null +++ b/src/domain/access/role-set/role.set.cache.service.ts @@ -0,0 +1,65 @@ +import { CommunityMembershipStatus } from '@common/enums/community.membership.status'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Injectable, Inject, LoggerService } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { AlkemioConfig } from '@src/types'; +import { Cache } from 'cache-manager'; +import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; + +@Injectable() +export class RoleSetCacheService { + private readonly cache_ttl: number; + + constructor( + @Inject(CACHE_MANAGER) + private readonly cacheManager: Cache, + @Inject(WINSTON_MODULE_NEST_PROVIDER) + private readonly logger: LoggerService, + private configService: ConfigService + ) { + this.cache_ttl = this.configService.get( + 'collaboration.membership.cache_ttl', + { infer: true } + ); + } + + public async getMembershipFromCache( + agentId: string, + roleSetId: string + ): Promise { + return await this.cacheManager.get( + this.getMembershipStatusCacheKey(agentId, roleSetId) + ); + } + + public async deleteAgentInfoFromCache( + agentId: string, + roleSetId: string + ): Promise { + return await this.cacheManager.del( + this.getMembershipStatusCacheKey(agentId, roleSetId) + ); + } + + public async setMembershipStatusCache( + agentId: string, + roleSetId: string, + membershipStatus: CommunityMembershipStatus + ): Promise { + const cacheKey = this.getMembershipStatusCacheKey(agentId, roleSetId); + return await this.cacheManager.set( + cacheKey, + membershipStatus, + { + ttl: this.cache_ttl, + } + ); + } + + private getMembershipStatusCacheKey( + agentId: string, + roleSetId: string + ): string { + return `membershipStatus:${agentId}:${roleSetId}`; + } +} diff --git a/src/domain/access/role-set/role.set.module.ts b/src/domain/access/role-set/role.set.module.ts index 3a48986d4..541ecf7a1 100644 --- a/src/domain/access/role-set/role.set.module.ts +++ b/src/domain/access/role-set/role.set.module.ts @@ -34,6 +34,7 @@ import { OrganizationLookupModule } from '@domain/community/organization-lookup/ import { UserModule } from '@domain/community/user/user.module'; import { RoleSetAgentRolesDataLoader } from './role.set.data.loaders'; import { RoleSetMembershipStatusDataLoader } from './role.set.data.loader.membership.status'; +import { RoleSetCacheService } from './role.set.cache.service'; @Module({ imports: [ @@ -73,6 +74,7 @@ import { RoleSetMembershipStatusDataLoader } from './role.set.data.loader.member RoleSetServiceLifecycleInvitation, RoleSetAgentRolesDataLoader, RoleSetMembershipStatusDataLoader, + RoleSetCacheService, ], exports: [RoleSetService, RoleSetAuthorizationService, RoleSetLicenseService], }) diff --git a/src/domain/access/role-set/role.set.service.ts b/src/domain/access/role-set/role.set.service.ts index 18da0f759..d8118d589 100644 --- a/src/domain/access/role-set/role.set.service.ts +++ b/src/domain/access/role-set/role.set.service.ts @@ -62,6 +62,7 @@ import { UserLookupService } from '@domain/community/user-lookup/user.lookup.ser import { RoleSetType } from '@common/enums/role.set.type'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; +import { RoleSetCacheService } from './role.set.cache.service'; @Injectable() export class RoleSetService { @@ -87,7 +88,8 @@ export class RoleSetService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, @Inject(CACHE_MANAGER) - private readonly cacheManager: Cache + private readonly cacheManager: Cache, + private readonly roleSetCacheService: RoleSetCacheService ) {} async createRoleSet(roleSetData: CreateRoleSetInput): Promise { @@ -395,19 +397,23 @@ export class RoleSetService { return CommunityMembershipStatus.NOT_MEMBER; } - const cacheKey = `membershipStatus:${agentInfo.agentID}:${roleSet.id}`; - const cached = - await this.cacheManager.get(cacheKey); - if (cached !== undefined && cached !== null) { + const cached = await this.roleSetCacheService.getMembershipFromCache( + agentInfo.agentID, + roleSet.id + ); + if (cached) { return cached; } const agent = await this.agentService.getAgentOrFail(agentInfo.agentID); const isMember = await this.isMember(agent, roleSet); if (isMember) { - await this.cacheManager.set(cacheKey, CommunityMembershipStatus.MEMBER, { - ttl: 300, - }); + await this.roleSetCacheService.setMembershipStatusCache( + agent.id, + roleSet.id, + CommunityMembershipStatus.MEMBER + ); + return CommunityMembershipStatus.MEMBER; } @@ -416,10 +422,10 @@ export class RoleSetService { roleSet.id ); if (openApplication) { - await this.cacheManager.set( - cacheKey, - CommunityMembershipStatus.APPLICATION_PENDING, - { ttl: 300 } + await this.roleSetCacheService.setMembershipStatusCache( + agent.id, + roleSet.id, + CommunityMembershipStatus.APPLICATION_PENDING ); return CommunityMembershipStatus.APPLICATION_PENDING; } @@ -432,19 +438,20 @@ export class RoleSetService { openInvitation && (await this.invitationService.canInvitationBeAccepted(openInvitation.id)) ) { - await this.cacheManager.set( - cacheKey, - CommunityMembershipStatus.INVITATION_PENDING, - { ttl: 300 } + await this.roleSetCacheService.setMembershipStatusCache( + agent.id, + roleSet.id, + CommunityMembershipStatus.INVITATION_PENDING ); return CommunityMembershipStatus.INVITATION_PENDING; } - await this.cacheManager.set( - cacheKey, - CommunityMembershipStatus.NOT_MEMBER, - { ttl: 300 } + await this.roleSetCacheService.setMembershipStatusCache( + agent.id, + roleSet.id, + CommunityMembershipStatus.NOT_MEMBER ); + return CommunityMembershipStatus.NOT_MEMBER; } diff --git a/src/types/alkemio.config.ts b/src/types/alkemio.config.ts index d46c935e2..d9782b6c0 100644 --- a/src/types/alkemio.config.ts +++ b/src/types/alkemio.config.ts @@ -184,6 +184,9 @@ export type AlkemioConfig = { enabled: boolean; }; collaboration: { + membership: { + cache_ttl: number; + }; whiteboards: { enabled: boolean; contribution_window: number;