Read feature flags from cache (#11556)
We are now storing a workspace's feature flag map in our redis cache. The cache is invalidated upon feature flag update through the lab resolver.
This commit is contained in:
@ -64,11 +64,11 @@ export class WorkspaceDataSource extends DataSource {
|
||||
this.permissionsPerRoleId = permissionsPerRoleId;
|
||||
}
|
||||
|
||||
setFeatureFlagMap(featureFlagMap: FeatureFlagMap) {
|
||||
setFeatureFlagsMap(featureFlagMap: FeatureFlagMap) {
|
||||
this.featureFlagMap = featureFlagMap;
|
||||
}
|
||||
|
||||
setFeatureFlagMapVersion(featureFlagMapVersion: string) {
|
||||
setFeatureFlagsMapVersion(featureFlagMapVersion: string) {
|
||||
this.featureFlagMapVersion = featureFlagMapVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interface
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { WorkspaceFeatureFlagMapCacheService } from 'src/engine/metadata-modules/workspace-feature-flag-map-cache.service.ts/workspace-feature-flag-map-cache.service';
|
||||
import { WorkspaceFeatureFlagsMapCacheService } from 'src/engine/metadata-modules/workspace-feature-flags-map-cache/workspace-feature-flags-map-cache.service';
|
||||
import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service';
|
||||
import { WorkspaceRolesPermissionsCacheService } from 'src/engine/metadata-modules/workspace-roles-permissions-cache/workspace-roles-permissions-cache.service';
|
||||
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
||||
@ -21,6 +21,7 @@ import {
|
||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||
import { PromiseMemoizer } from 'src/engine/twenty-orm/storage/promise-memoizer.storage';
|
||||
import { CacheKey } from 'src/engine/twenty-orm/storage/types/cache-key.type';
|
||||
import { getFromCacheWithRecompute } from 'src/engine/utils/get-data-from-cache-with-recompute.util';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
type CacheResult<T, U> = {
|
||||
@ -40,7 +41,7 @@ export class WorkspaceDatasourceFactory {
|
||||
private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService,
|
||||
private readonly entitySchemaFactory: EntitySchemaFactory,
|
||||
private readonly workspaceRolesPermissionsCacheService: WorkspaceRolesPermissionsCacheService,
|
||||
private readonly workspaceFeatureFlagMapCacheService: WorkspaceFeatureFlagMapCacheService,
|
||||
private readonly workspaceFeatureFlagsMapCacheService: WorkspaceFeatureFlagsMapCacheService,
|
||||
) {}
|
||||
|
||||
public async create(
|
||||
@ -55,7 +56,9 @@ export class WorkspaceDatasourceFactory {
|
||||
);
|
||||
|
||||
const { data: cachedFeatureFlagMap, version: cachedFeatureFlagMapVersion } =
|
||||
await this.getFeatureFlagMapFromCache({ workspaceId });
|
||||
await this.workspaceFeatureFlagsMapCacheService.getWorkspaceFeatureFlagsMapAndVersion(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const isPermissionsV2Enabled =
|
||||
cachedFeatureFlagMap[FeatureFlagKey.IsPermissionsV2Enabled];
|
||||
@ -201,7 +204,7 @@ export class WorkspaceDatasourceFactory {
|
||||
});
|
||||
}
|
||||
|
||||
await this.updateWorkspaceDataSourceFeatureFlagMapIfNeeded({
|
||||
await this.updateWorkspaceDataSourceFeatureFlagsMapIfNeeded({
|
||||
workspaceDataSource,
|
||||
cachedFeatureFlagMapVersion,
|
||||
cachedFeatureFlagMap,
|
||||
@ -210,47 +213,6 @@ export class WorkspaceDatasourceFactory {
|
||||
return workspaceDataSource;
|
||||
}
|
||||
|
||||
private async getFromCacheWithRecompute<T, U>({
|
||||
workspaceId,
|
||||
getCacheData,
|
||||
getCacheVersion,
|
||||
recomputeCache,
|
||||
cachedEntityName,
|
||||
exceptionCode,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
getCacheData: (workspaceId: string) => Promise<U | undefined>;
|
||||
getCacheVersion: (workspaceId: string) => Promise<T | undefined>;
|
||||
recomputeCache: (params: { workspaceId: string }) => Promise<void>;
|
||||
cachedEntityName: string;
|
||||
exceptionCode: TwentyORMExceptionCode;
|
||||
}): Promise<CacheResult<T, U>> {
|
||||
let cachedVersion: T | undefined;
|
||||
let cachedData: U | undefined;
|
||||
|
||||
cachedVersion = await getCacheVersion(workspaceId);
|
||||
cachedData = await getCacheData(workspaceId);
|
||||
|
||||
if (!isDefined(cachedData) || !isDefined(cachedVersion)) {
|
||||
await recomputeCache({ workspaceId });
|
||||
|
||||
cachedData = await getCacheData(workspaceId);
|
||||
cachedVersion = await getCacheVersion(workspaceId);
|
||||
|
||||
if (!isDefined(cachedData) || !isDefined(cachedVersion)) {
|
||||
throw new TwentyORMException(
|
||||
`${cachedEntityName} not found after recompute for workspace ${workspaceId}`,
|
||||
exceptionCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
version: cachedVersion,
|
||||
data: cachedData,
|
||||
};
|
||||
}
|
||||
|
||||
private async getRolesPermissionsFromCache({
|
||||
workspaceId,
|
||||
isPermissionsV2Enabled,
|
||||
@ -267,7 +229,7 @@ export class WorkspaceDatasourceFactory {
|
||||
return { version: undefined, data: undefined };
|
||||
}
|
||||
|
||||
return this.getFromCacheWithRecompute<
|
||||
return getFromCacheWithRecompute<
|
||||
string | undefined,
|
||||
ObjectRecordsPermissionsByRoleId | undefined
|
||||
>({
|
||||
@ -287,28 +249,6 @@ export class WorkspaceDatasourceFactory {
|
||||
});
|
||||
}
|
||||
|
||||
private async getFeatureFlagMapFromCache({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<CacheResult<string, FeatureFlagMap>> {
|
||||
return this.getFromCacheWithRecompute<string, FeatureFlagMap>({
|
||||
workspaceId,
|
||||
getCacheData: () =>
|
||||
this.workspaceCacheStorageService.getFeatureFlagMap(workspaceId),
|
||||
getCacheVersion: () =>
|
||||
this.workspaceCacheStorageService.getFeatureFlagMapVersionFromCache(
|
||||
workspaceId,
|
||||
),
|
||||
recomputeCache: (params) =>
|
||||
this.workspaceFeatureFlagMapCacheService.recomputeFeatureFlagMapCache(
|
||||
params,
|
||||
),
|
||||
cachedEntityName: 'Feature flag map',
|
||||
exceptionCode: TwentyORMExceptionCode.FEATURE_FLAG_MAP_VERSION_NOT_FOUND,
|
||||
});
|
||||
}
|
||||
|
||||
private updateWorkspaceDataSourceIfNeeded<T>({
|
||||
workspaceDataSource,
|
||||
currentVersion,
|
||||
@ -355,7 +295,7 @@ export class WorkspaceDatasourceFactory {
|
||||
});
|
||||
}
|
||||
|
||||
private async updateWorkspaceDataSourceFeatureFlagMapIfNeeded({
|
||||
private async updateWorkspaceDataSourceFeatureFlagsMapIfNeeded({
|
||||
workspaceDataSource,
|
||||
cachedFeatureFlagMapVersion,
|
||||
cachedFeatureFlagMap,
|
||||
@ -369,9 +309,9 @@ export class WorkspaceDatasourceFactory {
|
||||
currentVersion: workspaceDataSource.featureFlagMapVersion,
|
||||
newVersion: cachedFeatureFlagMapVersion,
|
||||
newData: cachedFeatureFlagMap,
|
||||
setData: (data) => workspaceDataSource.setFeatureFlagMap(data),
|
||||
setData: (data) => workspaceDataSource.setFeatureFlagsMap(data),
|
||||
setVersion: (version) =>
|
||||
workspaceDataSource.setFeatureFlagMapVersion(version),
|
||||
workspaceDataSource.setFeatureFlagsMapVersion(version),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { WorkspaceFeatureFlagMapCacheModule } from 'src/engine/metadata-modules/workspace-feature-flag-map-cache.service.ts/workspace-roles-feature-flag-map-cache.module';
|
||||
import { WorkspaceFeatureFlagsMapCacheModule } from 'src/engine/metadata-modules/workspace-feature-flags-map-cache/workspace-feature-flags-map-cache.module';
|
||||
import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module';
|
||||
import { WorkspaceRolesPermissionsCacheModule } from 'src/engine/metadata-modules/workspace-roles-permissions-cache/workspace-roles-permissions-cache.module';
|
||||
import { entitySchemaFactories } from 'src/engine/twenty-orm/factories';
|
||||
@ -27,7 +27,7 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/
|
||||
WorkspaceMetadataCacheModule,
|
||||
PermissionsModule,
|
||||
WorkspaceRolesPermissionsCacheModule,
|
||||
WorkspaceFeatureFlagMapCacheModule,
|
||||
WorkspaceFeatureFlagsMapCacheModule,
|
||||
FeatureFlagModule,
|
||||
],
|
||||
providers: [
|
||||
|
||||
Reference in New Issue
Block a user