From 15cbcfb78d072529b37967bd38750a1c2df71516 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:51:53 +0100 Subject: [PATCH] fix(integration): purge per-user unfurl cache on disconnect --- .../integration-connection.service.ts | 4 ++++ .../core/integration/unfurl/unfurl.service.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/apps/server/src/core/integration/integration-connection.service.ts b/apps/server/src/core/integration/integration-connection.service.ts index 24015962c..ca21c4d64 100644 --- a/apps/server/src/core/integration/integration-connection.service.ts +++ b/apps/server/src/core/integration/integration-connection.service.ts @@ -2,12 +2,14 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { IntegrationConnectionRepo } from './repos/integration-connection.repo'; import { IntegrationRepo } from './repos/integration.repo'; import { IntegrationConnection } from '@docmost/db/types/entity.types'; +import { UnfurlService } from './unfurl/unfurl.service'; @Injectable() export class IntegrationConnectionService { constructor( private readonly connectionRepo: IntegrationConnectionRepo, private readonly integrationRepo: IntegrationRepo, + private readonly unfurlService: UnfurlService, ) {} async getConnectionStatus( @@ -79,5 +81,7 @@ export class IntegrationConnectionService { integrationId, userId, ); + + await this.unfurlService.purgeUserCache(workspaceId, userId); } } diff --git a/apps/server/src/core/integration/unfurl/unfurl.service.ts b/apps/server/src/core/integration/unfurl/unfurl.service.ts index 1dc91bb81..77efe85da 100644 --- a/apps/server/src/core/integration/unfurl/unfurl.service.ts +++ b/apps/server/src/core/integration/unfurl/unfurl.service.ts @@ -113,6 +113,22 @@ export class UnfurlService { } } + async purgeUserCache(workspaceId: string, userId: string): Promise { + const pattern = `${UNFURL_CACHE_PREFIX}${workspaceId}:${userId}:*`; + try { + const stream = this.redis.scanStream({ match: pattern, count: 100 }); + for await (const keys of stream as AsyncIterable) { + if (keys.length) { + await this.redis.unlink(...keys); + } + } + } catch (err) { + this.logger.error( + `Failed to purge unfurl cache for user ${userId}: ${(err as Error).message}`, + ); + } + } + private buildNeedsConnection( provider: IntegrationProvider, integrationId: string,