1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-27 11:02:16 +01:00

chore(AI): etagVariant flag cleanup (#10714)

This PR cleans up the etagVariant flag. These changes were automatically
generated by AI and should be reviewed carefully.

Fixes #10711

## 🧹 AI Flag Cleanup Summary
This PR removes the `etagVariant` feature flag, making the versioned
ETag format
(`v2`) the default and only behavior for the client features API.
### 🚮 Removed
- **Feature Flag**
- Removed the `etagVariant` flag definition from `experimental.ts`.
- Removed conditional logic for ETag generation in
`client-feature-toggle.controller.ts`.
- **Testing**
- Removed parameterized tests for both states of the flag in
`feature.optimal304.e2e.test.ts`.
- Removed configuration of the `etagVariant` flag in test setup.
### 🛠 Kept
- **ETag Generation**
- The logic to generate ETags with a version suffix (`v1`) is now the
standard
behavior.
- **Testing**
- Tests have been updated to exclusively assert the presence of the `v1`
suffix in ETags.
### 📝 Why
The `etagVariant` feature flag has been successfully rolled out and is
now
considered complete. By removing the flag, we are simplifying the
codebase by
eliminating conditional paths and making the improved ETag format
permanent.
This change ensures all client API responses for features include a
versioned
ETag, which helps with cache-busting when the ETag format changes in the
future.

---------

Co-authored-by: unleash-bot <194219037+unleash-bot[bot]@users.noreply.github.com>
Co-authored-by: Gastón Fournier <gaston@getunleash.io>
This commit is contained in:
unleash-bot[bot] 2025-10-02 11:26:53 +02:00 committed by GitHub
parent c2b598d8d9
commit da22cb0d65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 97 additions and 162 deletions

View File

@ -357,14 +357,8 @@ export default class FeatureController extends Controller {
); );
const queryHash = hashSum(query); const queryHash = hashSum(query);
const etagVariant = this.flagResolver.getVariant('etagVariant'); const etag = `"${queryHash}:${revisionId}:v1"`;
if (etagVariant.feature_enabled && etagVariant.enabled) { return { revisionId, etag, queryHash };
const etag = `"${queryHash}:${revisionId}:${etagVariant.name}"`;
return { revisionId, etag, queryHash };
} else {
const etag = `"${queryHash}:${revisionId}"`;
return { revisionId, etag, queryHash };
}
} }
async getFeatureToggle( async getFeatureToggle(

View File

@ -63,7 +63,7 @@ exports[`should match snapshot from /api/client/features 1`] = `
}, },
], ],
"meta": { "meta": {
"etag": ""76d8bb0e:19"", "etag": ""76d8bb0e:19:v1"",
"queryHash": "76d8bb0e", "queryHash": "76d8bb0e",
"revisionId": 19, "revisionId": 19,
}, },

View File

@ -46,7 +46,6 @@ export type IFlagKey =
| 'showUserDeviceCount' | 'showUserDeviceCount'
| 'memorizeStats' | 'memorizeStats'
| 'streaming' | 'streaming'
| 'etagVariant'
| 'deltaApi' | 'deltaApi'
| 'uniqueSdkTracking' | 'uniqueSdkTracking'
| 'consumptionModel' | 'consumptionModel'
@ -220,11 +219,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_SHOW_USER_DEVICE_COUNT, process.env.UNLEASH_EXPERIMENTAL_SHOW_USER_DEVICE_COUNT,
false, false,
), ),
etagVariant: {
name: 'disabled',
feature_enabled: false,
enabled: false,
},
deltaApi: parseEnvVarBoolean( deltaApi: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_DELTA_API, process.env.UNLEASH_EXPERIMENTAL_DELTA_API,
false, false,

View File

@ -38,11 +38,7 @@ const devTokenSecret = validTokens[0].secret;
const prodTokenSecret = validTokens[1].secret; const prodTokenSecret = validTokens[1].secret;
const allEnvsTokenSecret = validTokens[2].secret; const allEnvsTokenSecret = validTokens[2].secret;
async function setup({ async function setup(): Promise<{ app: IUnleashTest; db: ITestDb }> {
etagVariant,
}: {
etagVariant: string | undefined;
}): Promise<{ app: IUnleashTest; db: ITestDb }> {
const db = await dbInit(`ignored`, getLogger); const db = await dbInit(`ignored`, getLogger);
// Create per-environment client tokens so we can request specific environment snapshots // Create per-environment client tokens so we can request specific environment snapshots
@ -56,11 +52,6 @@ async function setup({
experimental: { experimental: {
flags: { flags: {
strictSchemaValidation: true, strictSchemaValidation: true,
etagVariant: {
name: etagVariant,
enabled: etagVariant !== undefined,
feature_enabled: etagVariant !== undefined,
},
}, },
}, },
}, },
@ -172,159 +163,115 @@ async function validateInitialState({
} }
} }
describe.each([ describe('feature 304 api client', () => {
{ let app: IUnleashTest;
etagVariant: undefined, let db: ITestDb;
}, const expectedDevEventId = 13;
{ beforeAll(async () => {
etagVariant: 'v2', ({ app, db } = await setup());
}, await initialize({ app, db });
])( await validateInitialState({ app, db });
'feature 304 api client (etag variant = $etagVariant)', });
({ etagVariant }) => {
let app: IUnleashTest;
let db: ITestDb;
const etagVariantEnabled = etagVariant !== undefined;
const etagVariantName = etagVariant ?? 'disabled';
const expectedDevEventId = 13;
beforeAll(async () => {
({ app, db } = await setup({
etagVariant,
}));
await initialize({ app, db });
await validateInitialState({ app, db });
});
afterAll(async () => { afterAll(async () => {
await app.destroy(); await app.destroy();
await db.destroy(); await db.destroy();
}); });
test('returns calculated hash without if-none-match header (dev env token)', async () => { test('returns calculated hash without if-none-match header (dev env token)', async () => {
const res = await app.request const res = await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', devTokenSecret) .set('Authorization', devTokenSecret)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200); .expect(200);
if (etagVariantEnabled) { expect(res.headers.etag).toBe(`"76d8bb0e:${expectedDevEventId}:v1"`);
expect(res.headers.etag).toBe( expect(res.body.meta.etag).toBe(`"76d8bb0e:${expectedDevEventId}:v1"`);
`"76d8bb0e:${expectedDevEventId}:${etagVariantName}"`, });
);
expect(res.body.meta.etag).toBe(
`"76d8bb0e:${expectedDevEventId}:${etagVariantName}"`,
);
} else {
expect(res.headers.etag).toBe(
`"76d8bb0e:${expectedDevEventId}"`,
);
expect(res.body.meta.etag).toBe(
`"76d8bb0e:${expectedDevEventId}"`,
);
}
});
test(`returns ${etagVariantEnabled ? 200 : 304} for pre-calculated hash${etagVariantEnabled ? ' because hash changed' : ''} (dev env token)`, async () => { test(`returns 200 for pre-calculated hash because hash changed (dev env token)`, async () => {
const res = await app.request const res = await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', devTokenSecret) .set('Authorization', devTokenSecret)
.set('if-none-match', `"76d8bb0e:${expectedDevEventId}"`) .set('if-none-match', `"76d8bb0e:${expectedDevEventId}"`)
.expect(etagVariantEnabled ? 200 : 304); .expect(200);
if (etagVariantEnabled) { expect(res.headers.etag).toBe(`"76d8bb0e:${expectedDevEventId}:v1"`);
expect(res.headers.etag).toBe( expect(res.body.meta.etag).toBe(`"76d8bb0e:${expectedDevEventId}:v1"`);
`"76d8bb0e:${expectedDevEventId}:${etagVariantName}"`, });
);
expect(res.body.meta.etag).toBe(
`"76d8bb0e:${expectedDevEventId}:${etagVariantName}"`,
);
}
});
test('creating a new feature does not modify etag', async () => { test('creating a new feature does not modify etag', async () => {
await app.createFeature('new'); await app.createFeature('new');
await app.services.configurationRevisionService.updateMaxRevisionId(); await app.services.configurationRevisionService.updateMaxRevisionId();
await app.request await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', devTokenSecret) .set('Authorization', devTokenSecret)
.set( .set('if-none-match', `"76d8bb0e:${expectedDevEventId}:v1"`)
'if-none-match', .expect(304);
`"76d8bb0e:${expectedDevEventId}${etagVariantEnabled ? `:${etagVariantName}` : ''}"`, });
)
.expect(304);
});
test('a token with all envs should get the max id regardless of the environment', async () => { test('a token with all envs should get the max id regardless of the environment', async () => {
const currentProdEtag = `"67e24428:15${etagVariantEnabled ? `:${etagVariantName}` : ''}"`; const currentProdEtag = `"67e24428:15:v1"`;
const { headers } = await app.request const { headers } = await app.request
.get('/api/client/features') .get('/api/client/features')
.set('if-none-match', currentProdEtag) .set('if-none-match', currentProdEtag)
.set('Authorization', allEnvsTokenSecret) .set('Authorization', allEnvsTokenSecret)
.expect(200); .expect(200);
// it's a different hash than prod, but gets the max id // it's a different hash than prod, but gets the max id
expect(headers.etag).toEqual( expect(headers.etag).toEqual(`"ae443048:15:v1"`);
`"ae443048:15${etagVariantEnabled ? `:${etagVariantName}` : ''}"`, });
);
});
test('production environment gets a different etag than development', async () => { test('production environment gets a different etag than development', async () => {
const { headers: prodHeaders } = await app.request const { headers: prodHeaders } = await app.request
.get('/api/client/features?bla=1') .get('/api/client/features?bla=1')
.set('Authorization', prodTokenSecret) .set('Authorization', prodTokenSecret)
.expect(200); .expect(200);
expect(prodHeaders.etag).toEqual( expect(prodHeaders.etag).toEqual(`"67e24428:15:v1"`);
`"67e24428:15${etagVariantEnabled ? `:${etagVariantName}` : ''}"`,
);
const { headers: devHeaders } = await app.request const { headers: devHeaders } = await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', devTokenSecret) .set('Authorization', devTokenSecret)
.expect(200); .expect(200);
expect(devHeaders.etag).toEqual( expect(devHeaders.etag).toEqual(`"76d8bb0e:13:v1"`);
`"76d8bb0e:13${etagVariantEnabled ? `:${etagVariantName}` : ''}"`, });
);
});
test('modifying dev environment should only invalidate dev tokens', async () => { test('modifying dev environment should only invalidate dev tokens', async () => {
const currentDevEtag = `"76d8bb0e:13${etagVariantEnabled ? `:${etagVariantName}` : ''}"`; const currentDevEtag = `"76d8bb0e:13:v1"`;
const currentProdEtag = `"67e24428:15${etagVariantEnabled ? `:${etagVariantName}` : ''}"`; const currentProdEtag = `"67e24428:15:v1"`;
await app.request await app.request
.get('/api/client/features') .get('/api/client/features')
.set('if-none-match', currentProdEtag) .set('if-none-match', currentProdEtag)
.set('Authorization', prodTokenSecret) .set('Authorization', prodTokenSecret)
.expect(304); .expect(304);
await app.request await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', devTokenSecret) .set('Authorization', devTokenSecret)
.set('if-none-match', currentDevEtag) .set('if-none-match', currentDevEtag)
.expect(304); .expect(304);
await app.enableFeature('X', DEFAULT_ENV); await app.enableFeature('X', DEFAULT_ENV);
await app.services.configurationRevisionService.updateMaxRevisionId(); await app.services.configurationRevisionService.updateMaxRevisionId();
await app.request await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', prodTokenSecret) .set('Authorization', prodTokenSecret)
.set('if-none-match', currentProdEtag) .set('if-none-match', currentProdEtag)
.expect(304); .expect(304);
const { headers: devHeaders } = await app.request const { headers: devHeaders } = await app.request
.get('/api/client/features') .get('/api/client/features')
.set('Authorization', devTokenSecret) .set('Authorization', devTokenSecret)
.set('if-none-match', currentDevEtag) .set('if-none-match', currentDevEtag)
.expect(200); .expect(200);
// Note: this test yields a different result if run in isolation // Note: this test yields a different result if run in isolation
// this is because the id 19 depends on a previous test adding a feature // this is because the id 19 depends on a previous test adding a feature
// otherwise the id will be 18 // otherwise the id will be 18
expect(devHeaders.etag).toEqual( expect(devHeaders.etag).toEqual(`"76d8bb0e:19:v1"`);
`"76d8bb0e:19${etagVariantEnabled ? `:${etagVariantName}` : ''}"`, });
); });
});
},
);