Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor/last seen at archived #5102

Merged
merged 3 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Request, Response } from 'express';
import { IUnleashConfig } from '../../types/option';
import { IUnleashServices } from '../../types';
import Controller from '../controller';
import Controller from '../../routes/controller';
import { extractUsername } from '../../util/extract-user';
import { DELETE_FEATURE, NONE, UPDATE_FEATURE } from '../../types/permissions';
import FeatureToggleService from '../../features/feature-toggle/feature-toggle-service';
import { IAuthRequest } from '../unleash-types';
import FeatureToggleService from './feature-toggle-service';
import { IAuthRequest } from '../../routes/unleash-types';
import {
featuresSchema,
FeaturesSchema,
Expand Down Expand Up @@ -140,7 +140,7 @@ export default class ArchiveController extends Controller {
res: Response<FeaturesSchema>,
): Promise<void> {
const { user } = req;
const features = await this.featureService.getMetadataForAllFeatures(
const features = await this.featureService.getAllArchivedFeatures(
true,
user.id,
);
Expand All @@ -158,7 +158,7 @@ export default class ArchiveController extends Controller {
): Promise<void> {
const { projectId } = req.params;
const features =
await this.featureService.getMetadataForAllFeaturesByProjectId(
await this.featureService.getArchivedFeaturesByProjectId(
true,
projectId,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class FeatureToggleRowConverter {
const newEnvironment = {
name: row.last_seen_at_env,
lastSeenAt: row.env_last_seen_at,
enabled: row.enabled,
enabled: row.enabled || false,
};

feature.environments.push(newEnvironment);
Expand Down Expand Up @@ -253,4 +253,32 @@ export class FeatureToggleRowConverter {

return this.formatToggles(result);
};

buildArchivedFeatureToggleListFromRows = (
rows: any[],
): IFeatureToggleListItem[] => {
const result = rows.reduce((acc, row) => {
const feature: PartialDeep<IFeatureToggleListItem> =
acc[row.name] ?? {};

feature.name = row.name;
feature.description = row.description;
feature.type = row.type;
feature.project = row.project;
feature.stale = row.stale;
feature.createdAt = row.created_at;
feature.impressionData = row.impression_data;
feature.lastSeenAt = row.last_seen_at;
feature.archivedAt = row.archived_at;

if (this.flagResolver.isEnabled('useLastSeenRefactor')) {
this.addLastSeenByEnvironment(feature, row);
}

acc[row.name] = feature;
return acc;
}, {});

return Object.values(result);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ export default class FakeFeatureToggleStore implements IFeatureToggleStore {
return this.features.filter((feature) => feature.archived !== archived);
}

async getArchivedFeatures(project: string): Promise<FeatureToggle[]> {
return this.features.filter((feature) => feature.archived === true);
}

async getPlaygroundFeatures(
query?: IFeatureToggleQuery,
): Promise<FeatureConfigurationClient[]> {
Expand Down
19 changes: 15 additions & 4 deletions src/lib/features/feature-toggle/feature-toggle-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2016,11 +2016,18 @@ class FeatureToggleService {
);
}

async getMetadataForAllFeatures(
async getAllArchivedFeatures(
archived: boolean,
userId: number,
): Promise<FeatureToggle[]> {
const features = await this.featureToggleStore.getAll({ archived });
let features;

if (this.flagResolver.isEnabled('useLastSeenRefactor')) {
features = await this.featureToggleStore.getArchivedFeatures();
} else {
features = await this.featureToggleStore.getAll({ archived });
}

if (this.flagResolver.isEnabled('privateProjects')) {
const projectAccess =
await this.privateProjectChecker.getUserAccessibleProjects(
Expand All @@ -2037,11 +2044,15 @@ class FeatureToggleService {
return features;
}

async getMetadataForAllFeaturesByProjectId(
async getArchivedFeaturesByProjectId(
archived: boolean,
project: string,
): Promise<FeatureToggle[]> {
return this.featureToggleStore.getAll({ archived, project });
if (this.flagResolver.isEnabled('useLastSeenRefactor')) {
return this.featureToggleStore.getArchivedFeatures(project);
} else {
return this.featureToggleStore.getAll({ archived, project });
}
}

async getProjectId(name: string): Promise<string | undefined> {
Expand Down
63 changes: 61 additions & 2 deletions src/lib/features/feature-toggle/feature-toggle-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { FeatureToggleListBuilder } from './query-builders/feature-toggle-list-b
import { FeatureConfigurationClient } from './types/feature-toggle-strategies-store-type';
import { IFlagResolver } from '../../../lib/types';
import { FeatureToggleRowConverter } from './converters/feature-toggle-row-converter';
import FlagResolver from 'lib/util/flag-resolver';

export type EnvironmentFeatureNames = { [key: string]: string[] };

Expand Down Expand Up @@ -53,6 +52,17 @@ interface VariantDTO {
variants: IVariant[];
}

const commonSelectColumns = [
'features.name as name',
'features.description as description',
'features.type as type',
'features.project as project',
'features.stale as stale',
'features.impression_data as impression_data',
'features.last_seen_at as last_seen_at',
'features.created_at as created_at',
];

const TABLE = 'features';
const FEATURE_ENVIRONMENTS_TABLE = 'feature_environments';

Expand Down Expand Up @@ -117,7 +127,22 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
}

private getBaseFeatureQuery = (archived: boolean, environment: string) => {
const builder = new FeatureToggleListBuilder(this.db);
const builder = new FeatureToggleListBuilder(this.db, [
...commonSelectColumns,
'fe.variants as variants',
'fe.enabled as enabled',
'fe.environment as environment',
'fs.id as strategy_id',
'fs.strategy_name as strategy_name',
'fs.title as strategy_title',
'fs.disabled as strategy_disabled',
'fs.parameters as parameters',
'fs.constraints as constraints',
'fs.sort_order as sort_order',
'fs.variants as strategy_variants',
'segments.id as segment_id',
'segments.constraints as segment_constraints',
]);

builder
.query('features')
Expand Down Expand Up @@ -223,9 +248,43 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
.from(TABLE)
.where(rest)
.modify(FeatureToggleStore.filterByArchived, archived);

return rows.map(this.rowToFeature);
}

async getArchivedFeatures(project?: string): Promise<FeatureToggle[]> {
const builder = new FeatureToggleListBuilder(this.db, [
...commonSelectColumns,
'features.archived_at as archived_at',
]);

builder.query('features').withLastSeenByEnvironment();

builder.addSelectColumn(
'last_seen_at_metrics.last_seen_at as env_last_seen_at',
);
builder.addSelectColumn(
'last_seen_at_metrics.environment as last_seen_at_env',
);

let rows;

if (project) {
rows = await builder.internalQuery
.select(builder.getSelectColumns())
.where({ project })
.whereNotNull('archived_at');
} else {
rows = await builder.internalQuery
.select(builder.getSelectColumns())
.whereNotNull('archived_at');
}

return this.featureToggleRowConverter.buildArchivedFeatureToggleListFromRows(
rows,
);
}

async getAllByNames(names: string[]): Promise<FeatureToggle[]> {
const query = this.db<FeaturesTable>(TABLE).orderBy('name', 'asc');
query.whereIn('name', names);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,9 @@ export class FeatureToggleListBuilder {

private selectColumns: (string | Knex.Raw<any>)[];

constructor(db) {
constructor(db, selectColumns) {
this.db = db;
this.selectColumns = [
'features.name as name',
'features.description as description',
'features.type as type',
'features.project as project',
'features.stale as stale',
'features.impression_data as impression_data',
'features.last_seen_at as last_seen_at',
'features.created_at as created_at',
'fe.variants as variants',
'fe.enabled as enabled',
'fe.environment as environment',
'fs.id as strategy_id',
'fs.strategy_name as strategy_name',
'fs.title as strategy_title',
'fs.disabled as strategy_disabled',
'fs.parameters as parameters',
'fs.constraints as constraints',
'fs.sort_order as sort_order',
'fs.variants as strategy_variants',
'segments.id as segment_id',
'segments.constraints as segment_constraints',
] as (string | Knex.Raw<any>)[];
this.selectColumns = selectColumns;
}

getSelectColumns = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import dbInit, { ITestDb } from '../../helpers/database-init';
import dbInit, { ITestDb } from '../../../../test/e2e/helpers/database-init';
import {
IUnleashTest,
setupAppWithCustomConfig,
} from '../../helpers/test-helper';
import getLogger from '../../../fixtures/no-logger';
} from '../../../../test/e2e/helpers/test-helper';
import getLogger from '../../../../test/fixtures/no-logger';

let app: IUnleashTest;
let db: ITestDb;
Expand Down
Loading
Loading