Cache flush after database reset (#14873)

When starting the app on a fresh database reset the cache would be
filled with empty flat field metadata maps
Because the reset command hack through the repository directly in order
to create views and stuff
implemented an iso flush as the one existing initially
added it to a workspace deletion tambien
```
{
   byId: {],
   universalIdById: {}
}
```
This commit is contained in:
Paul Rastoin
2025-10-03 17:51:24 +02:00
committed by GitHub
parent 81e9a02101
commit d3a7241b6f
23 changed files with 210 additions and 162 deletions
@@ -1,18 +1,23 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { DiscoveryService } from '@nestjs/core';
import { AllFlatEntities } from 'src/engine/core-modules/common/types/all-flat-entities.type';
import { isDefined } from 'twenty-shared/utils';
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
import { WORKSPACE_FLAT_MAP_CACHE_KEY } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator';
import {
WorkspaceFlatMapCacheException,
WorkspaceFlatMapCacheExceptionCode,
} from 'src/engine/workspace-flat-map-cache/exceptions/workspace-flat-map-cache.exception';
import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service';
@Injectable()
export class WorkspaceFlatMapCacheRegistryService implements OnModuleInit {
private readonly cacheServiceMap = new Map<
keyof AllFlatEntityMaps,
WorkspaceFlatMapCacheService<FlatEntityMaps<AllFlatEntities>>
>();
private readonly cacheServiceRecord: {
[P in keyof AllFlatEntityMaps]?: WorkspaceFlatMapCacheService<
AllFlatEntityMaps[P]
>;
} = {};
constructor(private readonly discoveryService: DiscoveryService) {}
@@ -30,20 +35,31 @@ export class WorkspaceFlatMapCacheRegistryService implements OnModuleInit {
return;
}
const cacheKey = Reflect.getMetadata(
const cacheKey: keyof AllFlatEntityMaps | undefined = Reflect.getMetadata(
WORKSPACE_FLAT_MAP_CACHE_KEY,
metatype,
);
if (cacheKey && instance instanceof WorkspaceFlatMapCacheService) {
this.cacheServiceMap.set(cacheKey, instance);
this.cacheServiceRecord[cacheKey] = instance;
}
});
}
getCacheService(
flatEntityName: keyof AllFlatEntityMaps,
): WorkspaceFlatMapCacheService<FlatEntityMaps<AllFlatEntities>> | undefined {
return this.cacheServiceMap.get(flatEntityName);
getCacheService<K extends keyof AllFlatEntityMaps>(flatMapsKey: K) {
return this.cacheServiceRecord[flatMapsKey];
}
getCacheServiceOrThrow<K extends keyof AllFlatEntityMaps>(flatMapsKey: K) {
const service = this.getCacheService(flatMapsKey);
if (!isDefined(service)) {
throw new WorkspaceFlatMapCacheException(
`No cache service found for ${flatMapsKey}`,
WorkspaceFlatMapCacheExceptionCode.INTERNAL_SERVER_ERROR,
);
}
return service;
}
}
@@ -99,14 +99,9 @@ export abstract class WorkspaceFlatMapCacheService<
}: {
workspaceId: string;
}): Promise<void> {
const { flatMapKey, hashKey } = this.buildRemoteCacheKeys({ workspaceId });
await this.cacheStorageService.del(flatMapKey);
await this.cacheStorageService.del(hashKey);
this.localCacheFlatMaps.delete(workspaceId);
this.localCacheHashes.delete(workspaceId);
await this.flushCache({
workspaceId,
});
await this.recomputeAndStoreInCache({ workspaceId });
}
@@ -185,4 +180,14 @@ export abstract class WorkspaceFlatMapCacheService<
await this.cacheStorageService.set(flatMapKey, flatMap);
}
async flushCache({ workspaceId }: { workspaceId: string }): Promise<void> {
const { flatMapKey, hashKey } = this.buildRemoteCacheKeys({ workspaceId });
await this.cacheStorageService.del(flatMapKey);
await this.cacheStorageService.del(hashKey);
this.localCacheFlatMaps.delete(workspaceId);
this.localCacheHashes.delete(workspaceId);
}
}