diff --git a/backend/src/@types/fastify.d.ts b/backend/src/@types/fastify.d.ts index 92c22874e..77db3e59e 100644 --- a/backend/src/@types/fastify.d.ts +++ b/backend/src/@types/fastify.d.ts @@ -71,6 +71,7 @@ import { TIdentityTokenAuthServiceFactory } from "@app/services/identity-token-a import { TIdentityUaServiceFactory } from "@app/services/identity-ua/identity-ua-service"; import { TIntegrationServiceFactory } from "@app/services/integration/integration-service"; import { TIntegrationAuthServiceFactory } from "@app/services/integration-auth/integration-auth-service"; +import { TMicrosoftTeamsServiceFactory } from "@app/services/microsoft-teams/microsoft-teams-service"; import { TOrgRoleServiceFactory } from "@app/services/org/org-role-service"; import { TOrgServiceFactory } from "@app/services/org/org-service"; import { TOrgAdminServiceFactory } from "@app/services/org-admin/org-admin-service"; @@ -100,7 +101,6 @@ import { TUserServiceFactory } from "@app/services/user/user-service"; import { TUserEngagementServiceFactory } from "@app/services/user-engagement/user-engagement-service"; import { TWebhookServiceFactory } from "@app/services/webhook/webhook-service"; import { TWorkflowIntegrationServiceFactory } from "@app/services/workflow-integration/workflow-integration-service"; -import { TMicrosoftTeamsServiceFactory } from "@app/services/microsoft-teams/microsoft-teams-service"; declare module "@fastify/request-context" { interface RequestContextData { diff --git a/backend/src/queue/queue-service.ts b/backend/src/queue/queue-service.ts index ae1a3e821..807d6c286 100644 --- a/backend/src/queue/queue-service.ts +++ b/backend/src/queue/queue-service.ts @@ -25,6 +25,7 @@ import { TQueueSecretSyncSyncSecretsByIdDTO, TQueueSendSecretSyncActionFailedNotificationsDTO } from "@app/services/secret-sync/secret-sync-types"; +import { CacheType } from "@app/services/super-admin/super-admin-types"; import { TWebhookPayloads } from "@app/services/webhook/webhook-types"; export enum QueueName { @@ -49,7 +50,8 @@ export enum QueueName { AccessTokenStatusUpdate = "access-token-status-update", ImportSecretsFromExternalSource = "import-secrets-from-external-source", AppConnectionSecretSync = "app-connection-secret-sync", - SecretRotationV2 = "secret-rotation-v2" + SecretRotationV2 = "secret-rotation-v2", + InvalidateCache = "invalidate-cache" } export enum QueueJobs { @@ -81,7 +83,8 @@ export enum QueueJobs { SecretSyncSendActionFailedNotifications = "secret-sync-send-action-failed-notifications", SecretRotationV2QueueRotations = "secret-rotation-v2-queue-rotations", SecretRotationV2RotateSecrets = "secret-rotation-v2-rotate-secrets", - SecretRotationV2SendNotification = "secret-rotation-v2-send-notification" + SecretRotationV2SendNotification = "secret-rotation-v2-send-notification", + InvalidateCache = "invalidate-cache" } export type TQueueJobTypes = { @@ -234,6 +237,14 @@ export type TQueueJobTypes = { name: QueueJobs.SecretRotationV2SendNotification; payload: TSecretRotationSendNotificationJobPayload; }; + [QueueName.InvalidateCache]: { + name: QueueJobs.InvalidateCache; + payload: { + data: { + type: CacheType; + }; + }; + }; }; export type TQueueServiceFactory = ReturnType; diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 7e999cfb8..fb9c2fc32 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -238,6 +238,7 @@ import { projectSlackConfigDALFactory } from "@app/services/slack/project-slack- import { slackIntegrationDALFactory } from "@app/services/slack/slack-integration-dal"; import { slackServiceFactory } from "@app/services/slack/slack-service"; import { TSmtpService } from "@app/services/smtp/smtp-service"; +import { invalidateCacheQueueFactory } from "@app/services/super-admin/invalidate-cache-queue"; import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal"; import { getServerCfg, superAdminServiceFactory } from "@app/services/super-admin/super-admin-service"; import { telemetryDALFactory } from "@app/services/telemetry/telemetry-dal"; @@ -605,6 +606,11 @@ export const registerRoutes = async ( queueService }); + const invalidateCacheQueue = invalidateCacheQueueFactory({ + keyStore, + queueService + }); + const userService = userServiceFactory({ userDAL, userAliasDAL, @@ -715,7 +721,8 @@ export const registerRoutes = async ( keyStore, licenseService, kmsService, - microsoftTeamsService + microsoftTeamsService, + invalidateCacheQueue }); const orgAdminService = orgAdminServiceFactory({ diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index 322419609..13d4e2728 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -572,19 +572,18 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => { }); }, handler: async (req) => { - const keysCleared = await server.services.superAdmin.invalidateCache(req.body.type); + await server.services.superAdmin.invalidateCache(req.body.type); await server.services.telemetry.sendPostHogEvents({ event: PostHogEventTypes.InvalidateCache, distinctId: getTelemetryDistinctId(req), properties: { - keysCleared, ...req.auditLogInfo } }); return { - message: `Successfully invalidated ${keysCleared} cached items` + message: "Cache invalidation job started" }; } }); diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts index d2ba35a7e..a50299555 100644 --- a/backend/src/server/routes/v1/index.ts +++ b/backend/src/server/routes/v1/index.ts @@ -26,6 +26,7 @@ import { registerIdentityUaRouter } from "./identity-universal-auth-router"; import { registerIntegrationAuthRouter } from "./integration-auth-router"; import { registerIntegrationRouter } from "./integration-router"; import { registerInviteOrgRouter } from "./invite-org-router"; +import { registerMicrosoftTeamsRouter } from "./microsoft-teams-router"; import { registerOrgAdminRouter } from "./org-admin-router"; import { registerOrgRouter } from "./organization-router"; import { registerPasswordRouter } from "./password-router"; @@ -47,7 +48,6 @@ import { registerUserEngagementRouter } from "./user-engagement-router"; import { registerUserRouter } from "./user-router"; import { registerWebhookRouter } from "./webhook-router"; import { registerWorkflowIntegrationRouter } from "./workflow-integration-router"; -import { registerMicrosoftTeamsRouter } from "./microsoft-teams-router"; export const registerV1Routes = async (server: FastifyZodProvider) => { await server.register(registerSsoRouter, { prefix: "/sso" }); diff --git a/backend/src/services/super-admin/invalidate-cache-queue.ts b/backend/src/services/super-admin/invalidate-cache-queue.ts new file mode 100644 index 000000000..2bc897df6 --- /dev/null +++ b/backend/src/services/super-admin/invalidate-cache-queue.ts @@ -0,0 +1,43 @@ +import { TKeyStoreFactory } from "@app/keystore/keystore"; +import { logger } from "@app/lib/logger"; +import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; + +import { CacheType } from "./super-admin-types"; + +export type TInvalidateCacheQueueFactoryDep = { + queueService: TQueueServiceFactory; + + keyStore: Pick; +}; + +export type TInvalidateCacheQueueFactory = ReturnType; + +export const invalidateCacheQueueFactory = ({ queueService, keyStore }: TInvalidateCacheQueueFactoryDep) => { + const startInvalidate = async (dto: { + data: { + type: CacheType; + }; + }) => { + await queueService.queue(QueueName.InvalidateCache, QueueJobs.InvalidateCache, dto, { + removeOnComplete: true, + removeOnFail: true + }); + }; + + queueService.start(QueueName.InvalidateCache, async (job) => { + try { + const { + data: { type } + } = job.data; + + if (type === CacheType.ALL || type === CacheType.SECRETS) + await keyStore.deleteItems({ pattern: "secret-manager:*" }); + } catch (err) { + logger.error(err, "Failed to invalidate cache"); + } + }); + + return { + startInvalidate + }; +}; diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index c35b68d52..2e169f064 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -25,6 +25,7 @@ import { TOrgServiceFactory } from "../org/org-service"; import { TUserDALFactory } from "../user/user-dal"; import { TUserAliasDALFactory } from "../user-alias/user-alias-dal"; import { UserAliasType } from "../user-alias/user-alias-types"; +import { TInvalidateCacheQueueFactory } from "./invalidate-cache-queue"; import { TSuperAdminDALFactory } from "./super-admin-dal"; import { CacheType, @@ -50,6 +51,7 @@ type TSuperAdminServiceFactoryDep = { keyStore: Pick; licenseService: Pick; microsoftTeamsService: Pick; + invalidateCacheQueue: TInvalidateCacheQueueFactory; }; export type TSuperAdminServiceFactory = ReturnType; @@ -81,7 +83,8 @@ export const superAdminServiceFactory = ({ identityAccessTokenDAL, identityTokenAuthDAL, identityOrgMembershipDAL, - microsoftTeamsService + microsoftTeamsService, + invalidateCacheQueue }: TSuperAdminServiceFactoryDep) => { const initServerCfg = async () => { // TODO(akhilmhdh): bad pattern time less change this later to me itself @@ -633,12 +636,9 @@ export const superAdminServiceFactory = ({ }; const invalidateCache = async (type: CacheType) => { - let totalKeysCleared = 0; - - if (type === CacheType.ALL || type === CacheType.SECRETS) - totalKeysCleared += await keyStore.deleteItems({ pattern: "secret-manager:*" }); - - return totalKeysCleared; + await invalidateCacheQueue.startInvalidate({ + data: { type } + }); }; return { diff --git a/backend/src/services/telemetry/telemetry-types.ts b/backend/src/services/telemetry/telemetry-types.ts index 74dd7448c..9e046cdbd 100644 --- a/backend/src/services/telemetry/telemetry-types.ts +++ b/backend/src/services/telemetry/telemetry-types.ts @@ -207,7 +207,6 @@ export type TIssueCertificateEvent = { export type TInvalidateCacheEvent = { event: PostHogEventTypes.InvalidateCache; properties: { - keysCleared: number; userAgent?: string; }; };