1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-19 17:52:45 +02:00

chore: unknown flags should not include flags that exist in Unleash (#10568)

https://linear.app/unleash/issue/2-3825/fetching-unknown-flags-should-not-include-flags-that-currently-exist

Fetching unknown flags should not include flags that currently exist in
Unleash.

This is especially noticeable if you create a flag with an unknown
flag's name, since it won't go away from the list right away.
This commit is contained in:
Nuno Góis 2025-08-29 10:20:43 +01:00 committed by GitHub
parent 31a924dd4b
commit e7b757d7e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 152 additions and 9 deletions

View File

@ -66,18 +66,24 @@ export class UnknownFlagsStore implements IUnknownFlagsStore {
} }
async getAll({ limit, orderBy }: QueryParams = {}): Promise<UnknownFlag[]> { async getAll({ limit, orderBy }: QueryParams = {}): Promise<UnknownFlag[]> {
let query = this.db(`${TABLE} AS uf`).select( let query = this.db(`${TABLE} AS uf`)
'uf.name', .select(
'uf.app_name', 'uf.name',
'uf.seen_at', 'uf.app_name',
'uf.environment', 'uf.seen_at',
this.db.raw( 'uf.environment',
`(SELECT MAX(e.created_at) this.db.raw(
`(SELECT MAX(e.created_at)
FROM ${TABLE_EVENTS} AS e FROM ${TABLE_EVENTS} AS e
WHERE e.feature_name = uf.name) WHERE e.feature_name = uf.name)
AS last_event_at`, AS last_event_at`,
), ),
); )
.whereNotExists(
this.db('features as f')
.select(this.db.raw('1'))
.whereRaw('f.name = uf.name'),
);
if (orderBy) { if (orderBy) {
query = query.orderBy(orderBy); query = query.orderBy(orderBy);

View File

@ -182,3 +182,140 @@ describe('should register unknown flags', () => {
); );
}); });
}); });
describe('should fetch unknown flags', () => {
test('returns empty list by default', async () => {
const res = await request
.get('/api/admin/metrics/unknown-flags')
.expect(200)
.expect('Content-Type', /json/);
expect(res.body).toMatchObject({
unknownFlags: [],
});
});
test('returns list of unknown flags', async () => {
const unknownFlag: BulkRegistrationSchema = {
appName: 'demo',
instanceId: '1',
environment: 'development',
sdkVersion: 'unleash-client-js:1.0.0',
sdkType: 'frontend',
};
await request
.post('/api/client/metrics/bulk')
.send({
applications: [unknownFlag],
metrics: [
{
featureName: 'unknown_flag_1',
environment: 'development',
appName: 'demo',
timestamp: startOfHour(new Date()),
yes: 1337,
no: 0,
variants: {},
},
{
featureName: 'unknown_flag_2',
environment: 'development',
appName: 'demo',
timestamp: startOfHour(new Date()),
yes: 200,
no: 100,
variants: {},
},
],
})
.expect(202);
await services.unknownFlagsService.flush();
const res = await request
.get('/api/admin/metrics/unknown-flags')
.expect(200)
.expect('Content-Type', /json/);
expect(res.body.unknownFlags).toHaveLength(2);
expect(res.body.unknownFlags).toEqual([
expect.objectContaining({
name: 'unknown_flag_1',
environment: 'development',
appName: 'demo',
lastEventAt: null,
}),
expect.objectContaining({
name: 'unknown_flag_2',
environment: 'development',
appName: 'demo',
lastEventAt: null,
}),
]);
});
test('does not include flags that have since been created in Unleash', async () => {
const unknownFlag: BulkRegistrationSchema = {
appName: 'demo',
instanceId: '1',
environment: 'development',
sdkVersion: 'unleash-client-js:1.0.0',
sdkType: 'frontend',
};
await request
.post('/api/client/metrics/bulk')
.send({
applications: [unknownFlag],
metrics: [
{
featureName: 'flag_that_will_be_created',
environment: 'development',
appName: 'demo',
timestamp: startOfHour(new Date()),
yes: 1337,
no: 0,
variants: {},
},
{
featureName: 'unknown_flag_2',
environment: 'development',
appName: 'demo',
timestamp: startOfHour(new Date()),
yes: 200,
no: 100,
variants: {},
},
],
})
.expect(202);
await services.unknownFlagsService.flush();
await request
.post('/api/admin/projects/default/features')
.send({
name: 'flag_that_will_be_created',
description: '',
type: 'release',
impressionData: false,
})
.expect(201);
const res = await request
.get('/api/admin/metrics/unknown-flags')
.expect(200)
.expect('Content-Type', /json/);
expect(res.body.unknownFlags).toHaveLength(1);
expect(res.body.unknownFlags).toEqual([
expect.objectContaining({
name: 'unknown_flag_2',
environment: 'development',
appName: 'demo',
lastEventAt: null,
}),
]);
});
});