Skip to content

Commit

Permalink
chore: rebrand cache to delta (#8986)
Browse files Browse the repository at this point in the history
The cache is too generic, we will be using delta from now on.
  • Loading branch information
sjaanus authored Dec 16, 2024
1 parent a2f8271 commit 3696420
Show file tree
Hide file tree
Showing 12 changed files with 89 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import type { Logger } from '../../logger';

import type { FeatureConfigurationClient } from '../feature-toggle/types/feature-toggle-strategies-store-type';
import type {
RevisionCacheEntry,
ClientFeatureToggleCache,
} from './cache/client-feature-toggle-cache';
RevisionDeltaEntry,
ClientFeatureToggleDelta,
} from './delta/client-feature-toggle-delta';

export class ClientFeatureToggleService {
private logger: Logger;
Expand All @@ -21,19 +21,19 @@ export class ClientFeatureToggleService {

private segmentReadModel: ISegmentReadModel;

private clientFeatureToggleCache: ClientFeatureToggleCache | null = null;
private clientFeatureToggleDelta: ClientFeatureToggleDelta | null = null;

constructor(
{
clientFeatureToggleStore,
}: Pick<IUnleashStores, 'clientFeatureToggleStore'>,
segmentReadModel: ISegmentReadModel,
clientFeatureToggleCache: ClientFeatureToggleCache | null,
clientFeatureToggleCache: ClientFeatureToggleDelta | null,
{ getLogger }: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
) {
this.logger = getLogger('services/client-feature-toggle-service.ts');
this.segmentReadModel = segmentReadModel;
this.clientFeatureToggleCache = clientFeatureToggleCache;
this.clientFeatureToggleDelta = clientFeatureToggleCache;
this.clientFeatureToggleStore = clientFeatureToggleStore;
}

Expand All @@ -44,9 +44,9 @@ export class ClientFeatureToggleService {
async getClientDelta(
revisionId: number | undefined,
query: IFeatureToggleQuery,
): Promise<RevisionCacheEntry | undefined> {
if (this.clientFeatureToggleCache !== null) {
return this.clientFeatureToggleCache.getDelta(revisionId, query);
): Promise<RevisionDeltaEntry | undefined> {
if (this.clientFeatureToggleDelta !== null) {
return this.clientFeatureToggleDelta.getDelta(revisionId, query);
} else {
throw new Error(
'Calling the partial updates but the cache is not initialized',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import FakeClientFeatureToggleStore from './fakes/fake-client-feature-toggle-sto
import { ClientFeatureToggleService } from './client-feature-toggle-service';
import { SegmentReadModel } from '../segment/segment-read-model';
import { FakeSegmentReadModel } from '../segment/fake-segment-read-model';
import { createClientFeatureToggleCache } from './cache/createClientFeatureToggleCache';
import { createClientFeatureToggleDelta } from './delta/createClientFeatureToggleDelta';

export const createClientFeatureToggleService = (
db: Db,
Expand All @@ -22,7 +22,7 @@ export const createClientFeatureToggleService = (

const segmentReadModel = new SegmentReadModel(db);

const clientFeatureToggleCache = createClientFeatureToggleCache(db, config);
const clientFeatureToggleCache = createClientFeatureToggleDelta(db, config);

const clientFeatureToggleService = new ClientFeatureToggleService(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { OpenApiService } from '../../../services/openapi-service';
import { NONE } from '../../../types/permissions';
import { createResponseSchema } from '../../../openapi/util/create-response-schema';
import type { ClientFeatureToggleService } from '../client-feature-toggle-service';
import type { RevisionCacheEntry } from './client-feature-toggle-cache';
import type { RevisionDeltaEntry } from './client-feature-toggle-delta';
import { clientFeaturesDeltaSchema } from '../../../openapi';
import type { QueryOverride } from '../client-feature-toggle.controller';

Expand Down Expand Up @@ -142,7 +142,7 @@ export default class ClientFeatureToggleDeltaController extends Controller {

async getDelta(
req: IAuthRequest,
res: Response<RevisionCacheEntry>,
res: Response<RevisionDeltaEntry>,
): Promise<void> {
if (!this.flagResolver.isEnabled('deltaApi')) {
throw new NotFoundError();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { IFeatureToggleQuery } from '../../../types';
import type { FeatureConfigurationClient } from '../../feature-toggle/types/feature-toggle-strategies-store-type';

export interface FeatureConfigurationCacheClient
export interface FeatureConfigurationDeltaClient
extends FeatureConfigurationClient {
description: string;
impressionData: false;
}

export interface IClientFeatureToggleCacheReadModel {
export interface IClientFeatureToggleDeltaReadModel {
getAll(
featureQuery: IFeatureToggleQuery,
): Promise<FeatureConfigurationCacheClient[]>;
): Promise<FeatureConfigurationDeltaClient[]>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import Raw = Knex.Raw;
import type EventEmitter from 'events';
import { ALL_PROJECTS, ensureStringValue, mapValues } from '../../../util';
import type {
FeatureConfigurationCacheClient,
IClientFeatureToggleCacheReadModel,
} from './client-feature-toggle-cache-read-model-type';
FeatureConfigurationDeltaClient,
IClientFeatureToggleDeltaReadModel,
} from './client-feature-toggle-delta-read-model-type';
import type { Db } from '../../../db/db';
import {
DB_TIME,
type IFeatureToggleCacheQuery,
type IFeatureToggleDeltaQuery,
type IStrategyConfig,
type PartialDeep,
} from '../../../internals';
import metricsHelper from '../../../util/metrics-helper';
import FeatureToggleStore from '../../feature-toggle/feature-toggle-store';

export default class ClientFeatureToggleCacheReadModel
implements IClientFeatureToggleCacheReadModel
export default class ClientFeatureToggleDeltaReadModel
implements IClientFeatureToggleDeltaReadModel
{
private db: Db;

Expand All @@ -29,14 +29,14 @@ export default class ClientFeatureToggleCacheReadModel
this.db = db;
this.timer = (action: string) =>
metricsHelper.wrapTimer(eventBus, DB_TIME, {
store: 'client-feature-toggle-cache-read-model',
store: 'client-feature-toggle-delta-read-model',
action,
});
}

public async getAll(
featureQuery: IFeatureToggleCacheQuery,
): Promise<FeatureConfigurationCacheClient[]> {
featureQuery: IFeatureToggleDeltaQuery,
): Promise<FeatureConfigurationDeltaClient[]> {
const environment = featureQuery.environment;
const stopTimer = this.timer(`getAll`);

Expand Down Expand Up @@ -128,7 +128,7 @@ export default class ClientFeatureToggleCacheReadModel
stopTimer();

const featureToggles = rows.reduce((acc, r) => {
const feature: PartialDeep<FeatureConfigurationCacheClient> = acc[
const feature: PartialDeep<FeatureConfigurationDeltaClient> = acc[
r.name
] ?? {
strategies: [],
Expand Down Expand Up @@ -168,7 +168,7 @@ export default class ClientFeatureToggleCacheReadModel
return acc;
}, {});

const features: FeatureConfigurationCacheClient[] =
const features: FeatureConfigurationDeltaClient[] =
Object.values(featureToggles);

// strip away unwanted properties
Expand All @@ -193,7 +193,7 @@ export default class ClientFeatureToggleCacheReadModel
}

private addSegmentIdsToStrategy(
feature: PartialDeep<FeatureConfigurationCacheClient>,
feature: PartialDeep<FeatureConfigurationDeltaClient>,
row: Record<string, any>,
) {
const strategy = feature.strategies?.find(
Expand Down Expand Up @@ -222,7 +222,7 @@ export default class ClientFeatureToggleCacheReadModel
}

private isUnseenStrategyRow(
feature: PartialDeep<FeatureConfigurationCacheClient>,
feature: PartialDeep<FeatureConfigurationDeltaClient>,
row: Record<string, any>,
): boolean {
return (
Expand All @@ -232,7 +232,7 @@ export default class ClientFeatureToggleCacheReadModel
}

private addSegmentToStrategy(
feature: PartialDeep<FeatureConfigurationCacheClient>,
feature: PartialDeep<FeatureConfigurationDeltaClient>,
row: Record<string, any>,
) {
feature.strategies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { calculateRequiredClientRevision } from './client-feature-toggle-cache';
import { calculateRequiredClientRevision } from './client-feature-toggle-delta';

const mockAdd = (params): any => {
const base = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import type {
IEventStore,
IFeatureToggleCacheQuery,
IFeatureToggleDeltaQuery,
IFeatureToggleQuery,
IFlagResolver,
} from '../../../types';
import type ConfigurationRevisionService from '../../feature-toggle/configuration-revision-service';
import { UPDATE_REVISION } from '../../feature-toggle/configuration-revision-service';
import { RevisionCache } from './revision-cache';
import { RevisionDelta } from './revision-delta';
import type {
FeatureConfigurationCacheClient,
IClientFeatureToggleCacheReadModel,
} from './client-feature-toggle-cache-read-model-type';
FeatureConfigurationDeltaClient,
IClientFeatureToggleDeltaReadModel,
} from './client-feature-toggle-delta-read-model-type';

type DeletedFeature = {
name: string;
project: string;
};

export type RevisionCacheEntry = {
updated: FeatureConfigurationCacheClient[];
export type RevisionDeltaEntry = {
updated: FeatureConfigurationDeltaClient[];
revisionId: number;
removed: DeletedFeature[];
};
Expand All @@ -29,7 +29,7 @@ export type Revision = {
removed: DeletedFeature[];
};

type Revisions = Record<string, RevisionCache>;
type Revisions = Record<string, RevisionDelta>;

const applyRevision = (first: Revision, last: Revision): Revision => {
const updatedMap = new Map(
Expand Down Expand Up @@ -91,10 +91,10 @@ export const calculateRequiredClientRevision = (
return projectFeatureRevisions.reduce(applyRevision);
};

export class ClientFeatureToggleCache {
private clientFeatureToggleCacheReadModel: IClientFeatureToggleCacheReadModel;
export class ClientFeatureToggleDelta {
private clientFeatureToggleDeltaReadModel: IClientFeatureToggleDeltaReadModel;

private cache: Revisions = {};
private delta: Revisions = {};

private eventStore: IEventStore;

Expand All @@ -107,18 +107,18 @@ export class ClientFeatureToggleCache {
private configurationRevisionService: ConfigurationRevisionService;

constructor(
clientFeatureToggleCacheReadModel: IClientFeatureToggleCacheReadModel,
clientFeatureToggleDeltaReadModel: IClientFeatureToggleDeltaReadModel,
eventStore: IEventStore,
configurationRevisionService: ConfigurationRevisionService,
flagResolver: IFlagResolver,
) {
this.eventStore = eventStore;
this.configurationRevisionService = configurationRevisionService;
this.clientFeatureToggleCacheReadModel =
clientFeatureToggleCacheReadModel;
this.clientFeatureToggleDeltaReadModel =
clientFeatureToggleDeltaReadModel;
this.flagResolver = flagResolver;
this.onUpdateRevisionEvent = this.onUpdateRevisionEvent.bind(this);
this.cache = {};
this.delta = {};

this.initRevisionId();
this.configurationRevisionService.on(
Expand All @@ -135,29 +135,29 @@ export class ClientFeatureToggleCache {
async getDelta(
sdkRevisionId: number | undefined,
query: IFeatureToggleQuery,
): Promise<RevisionCacheEntry | undefined> {
): Promise<RevisionDeltaEntry | undefined> {
const projects = query.project ? query.project : ['*'];
const environment = query.environment ? query.environment : 'default';
// TODO: filter by tags, what is namePrefix? anything else?
const requiredRevisionId = sdkRevisionId || 0;

const hasCache = this.cache[environment] !== undefined;
const hasDelta = this.delta[environment] !== undefined;

if (!hasCache) {
await this.initEnvironmentCache(environment);
if (!hasDelta) {
await this.initEnvironmentDelta(environment);
}

// Should get the latest state if revision does not exist or if sdkRevision is not present
// We should be able to do this without going to the database by merging revisions from the cache with
// We should be able to do this without going to the database by merging revisions from the delta with
// the base case
const firstTimeCalling = !sdkRevisionId;
if (
firstTimeCalling ||
(sdkRevisionId &&
sdkRevisionId !== this.currentRevisionId &&
!this.cache[environment].hasRevision(sdkRevisionId))
!this.delta[environment].hasRevision(sdkRevisionId))
) {
//TODO: populate cache based on this?
//TODO: populate delta based on this?
return {
revisionId: this.currentRevisionId,
// @ts-ignore
Expand All @@ -170,7 +170,7 @@ export class ClientFeatureToggleCache {
return undefined;
}

const environmentRevisions = this.cache[environment].getRevisions();
const environmentRevisions = this.delta[environment].getRevisions();

const compressedRevision = calculateRequiredClientRevision(
environmentRevisions,
Expand All @@ -188,7 +188,7 @@ export class ClientFeatureToggleCache {
}

public async listenToRevisionChange() {
const keys = Object.keys(this.cache);
const keys = Object.keys(this.delta);

if (keys.length === 0) return;
const latestRevision =
Expand Down Expand Up @@ -221,7 +221,7 @@ export class ClientFeatureToggleCache {
environment,
changedToggles,
);
this.cache[environment].addRevision({
this.delta[environment].addRevision({
updated: newToggles,
revisionId: latestRevision,
removed,
Expand All @@ -234,15 +234,15 @@ export class ClientFeatureToggleCache {
async getChangedToggles(
environment: string,
toggles: string[],
): Promise<FeatureConfigurationCacheClient[]> {
): Promise<FeatureConfigurationDeltaClient[]> {
const foundToggles = await this.getClientFeatures({
toggleNames: toggles,
environment,
});
return foundToggles;
}

public async initEnvironmentCache(environment: string) {
public async initEnvironmentDelta(environment: string) {
// Todo: replace with method that gets all features for an environment
const baseFeatures = await this.getClientFeatures({
environment,
Expand All @@ -251,22 +251,22 @@ export class ClientFeatureToggleCache {
this.currentRevisionId =
await this.configurationRevisionService.getMaxRevisionId();

const cache = new RevisionCache([
const delta = new RevisionDelta([
{
revisionId: this.currentRevisionId,
updated: baseFeatures,
removed: [],
},
]);

this.cache[environment] = cache;
this.delta[environment] = delta;
}

async getClientFeatures(
query: IFeatureToggleCacheQuery,
): Promise<FeatureConfigurationCacheClient[]> {
query: IFeatureToggleDeltaQuery,
): Promise<FeatureConfigurationDeltaClient[]> {
const result =
await this.clientFeatureToggleCacheReadModel.getAll(query);
await this.clientFeatureToggleDeltaReadModel.getAll(query);
return result;
}
}
Loading

0 comments on commit 3696420

Please sign in to comment.