Skip to content

Commit 0ff2561

Browse files
committed
rename new feature flags to 'enhanced*', drop 'classic' for old feature flags
1 parent b7dc2f9 commit 0ff2561

4 files changed

Lines changed: 72 additions & 72 deletions

File tree

src/appConfigurationImpl.ts

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,15 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
128128
*/
129129
#kvPageWatchers: PagedSettingsWatcher[] = [];
130130
/**
131-
* Page watchers for classic feature flags, derived from
131+
* Page watchers for feature flags, derived from
132132
* @see AzureAppConfigurationOptions.featureFlagOptions.selectors with each key filter prefixed by `.appconfig.featureflag/`.
133133
*/
134-
#classicFfPageWatchers: PagedSettingsWatcher[] = [];
134+
#ffPageWatchers: PagedSettingsWatcher[] = [];
135135
/**
136-
* Page watchers for feature flags loaded from feature flag endpoint, derived from
136+
* Page watchers for enhanced feature flags loaded from the dedicated feature flag endpoint, derived from
137137
* @see AzureAppConfigurationOptions.featureFlagOptions.selectors.
138138
*/
139-
#ffPageWatchers: PagedSettingsWatcher[] = [];
139+
#enhancedFfPageWatchers: PagedSettingsWatcher[] = [];
140140

141141
// Load balancing
142142
#lastSuccessfulEndpoint: string = "";
@@ -198,8 +198,8 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
198198
if (options?.featureFlagOptions?.enabled === true) {
199199
this.#featureFlagEnabled = true;
200200
// validate feature flag selectors, only load feature flags when enabled
201-
this.#classicFfPageWatchers = getClassicFeatureFlagPageWatchers(options.featureFlagOptions.selectors);
202-
this.#ffPageWatchers = getPageWatchers(options.featureFlagOptions.selectors);
201+
this.#ffPageWatchers = getFeatureFlagPageWatchers(options.featureFlagOptions.selectors);
202+
this.#enhancedFfPageWatchers = getPageWatchers(options.featureFlagOptions.selectors);
203203

204204
if (options.featureFlagOptions.refresh?.enabled === true) {
205205
this.#featureFlagRefreshEnabled = true;
@@ -419,9 +419,9 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
419419
await this.#loadSelectedKeyValues();
420420

421421
if (this.#featureFlagEnabled) {
422-
const classicFeatureFlags: ConfigurationSetting[] = await this.#loadClassicFeatureFlags();
423-
const featureFlags: FeatureFlag[] = await this.#loadFeatureFlags();
424-
await this.#setFeatureFlags(classicFeatureFlags, featureFlags);
422+
const featureFlags: ConfigurationSetting[] = await this.#loadFeatureFlags();
423+
const enhancedFeatureFlags: FeatureFlag[] = await this.#loadEnhancedFeatureFlags();
424+
await this.#setFeatureFlags(featureFlags, enhancedFeatureFlags);
425425
}
426426
this.#isInitialLoadCompleted = true;
427427
break;
@@ -614,10 +614,10 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
614614
}
615615
}
616616

617-
async #loadClassicFeatureFlags(): Promise<ConfigurationSetting[]> {
618-
const classicFeatureFlags: Map<string, ConfigurationSetting> = new Map<string, ConfigurationSetting>();
617+
async #loadFeatureFlags(): Promise<ConfigurationSetting[]> {
618+
const featureFlags: Map<string, ConfigurationSetting> = new Map<string, ConfigurationSetting>();
619619
// Deep copy selectors to avoid modification if current client fails.
620-
const watchersToUpdate: PagedSettingsWatcher[] = structuredClone(this.#classicFfPageWatchers);
620+
const watchersToUpdate: PagedSettingsWatcher[] = structuredClone(this.#ffPageWatchers);
621621

622622
for (const selector of watchersToUpdate) {
623623
let settings: ConfigurationSetting[] = [];
@@ -637,19 +637,19 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
637637

638638
for (const setting of settings) {
639639
if (isFeatureFlag(setting)) {
640-
classicFeatureFlags.set(setting.key, setting);
640+
featureFlags.set(setting.key, setting);
641641
}
642642
}
643643
}
644644

645-
this.#classicFfPageWatchers = watchersToUpdate;
646-
return Array.from(classicFeatureFlags.values());
645+
this.#ffPageWatchers = watchersToUpdate;
646+
return Array.from(featureFlags.values());
647647
}
648648

649-
async #loadFeatureFlags(): Promise<FeatureFlag[]> {
649+
async #loadEnhancedFeatureFlags(): Promise<FeatureFlag[]> {
650650
const loadedFeatureFlags: Map<string, FeatureFlag> = new Map<string, FeatureFlag>();
651651
// Deep copy selectors to avoid modification if current client fails.
652-
const watchersToUpdate: PagedSettingsWatcher[] = structuredClone(this.#ffPageWatchers);
652+
const watchersToUpdate: PagedSettingsWatcher[] = structuredClone(this.#enhancedFfPageWatchers);
653653

654654
for (const selector of watchersToUpdate) {
655655
if (selector.snapshotName) {
@@ -660,39 +660,39 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
660660
labelFilter: selector.labelFilter,
661661
tagsFilter: selector.tagFilters
662662
};
663-
const { items, pageWatchers } = await this.#listFeatureFlags(listOptions);
663+
const { items, pageWatchers } = await this.#listEnhancedFeatureFlags(listOptions);
664664
selector.pageWatchers = pageWatchers;
665665
for (const featureFlag of items) {
666666
loadedFeatureFlags.set(featureFlag.name, featureFlag);
667667
}
668668
}
669669

670-
this.#ffPageWatchers = watchersToUpdate;
670+
this.#enhancedFfPageWatchers = watchersToUpdate;
671671
return Array.from(loadedFeatureFlags.values());
672672
}
673673

674-
async #setFeatureFlags(classicFeatureFlags: ConfigurationSetting[], featureFlags: FeatureFlag[]): Promise<void> {
674+
async #setFeatureFlags(featureFlags: ConfigurationSetting[], enhancedFeatureFlags: FeatureFlag[]): Promise<void> {
675675
if (this.#requestTracingEnabled && this.#featureFlagTracing !== undefined) {
676676
// Reset old feature flag tracing in order to track the information present in the current response from server.
677677
this.#featureFlagTracing.reset();
678678
}
679679

680680
// Track whether enhanced feature flags were loaded.
681-
this.#useEnhancedFeatureFlag = featureFlags.length > 0;
682-
683-
// Exclude any classic feature flags that are superseded by a standalone feature flag with the same name.
684-
const ineligibleClassicFfKeys = new Set(featureFlags.map(ff => featureFlagPrefix + ff.name));
685-
const eligibleClassicFeatureFlags = await Promise.all(
686-
classicFeatureFlags
687-
.filter(setting => !ineligibleClassicFfKeys.has(setting.key))
688-
.map(setting => this.#parseClassicFeatureFlag(setting))
681+
this.#useEnhancedFeatureFlag = enhancedFeatureFlags.length > 0;
682+
683+
// Exclude any feature flags that are superseded by an enhanced feature flag with the same name.
684+
const ineligibleFeatureFlagKeys = new Set(enhancedFeatureFlags.map(ff => featureFlagPrefix + ff.name));
685+
const eligibleFeatureFlags = await Promise.all(
686+
featureFlags
687+
.filter(setting => !ineligibleFeatureFlagKeys.has(setting.key))
688+
.map(setting => this.#parseFeatureFlag(setting))
689689
);
690-
const parsedFeatureFlags = await Promise.all(
691-
featureFlags.map(ff => this.#parseFeatureFlag(ff))
690+
const parsedEnhancedFeatureFlags = await Promise.all(
691+
enhancedFeatureFlags.map(ff => this.#parseEnhancedFeatureFlag(ff))
692692
);
693693

694694
// feature_management is a reserved key, and feature_flags is an array of feature flags
695-
this.#configMap.set(FEATURE_MANAGEMENT_KEY_NAME, { [FEATURE_FLAGS_KEY_NAME]: [...eligibleClassicFeatureFlags, ...parsedFeatureFlags] });
695+
this.#configMap.set(FEATURE_MANAGEMENT_KEY_NAME, { [FEATURE_FLAGS_KEY_NAME]: [...eligibleFeatureFlags, ...parsedEnhancedFeatureFlags] });
696696
}
697697

698698
/**
@@ -755,13 +755,13 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
755755
return Promise.resolve(false);
756756
}
757757

758-
const needRefresh = await this.#checkConfigurationSettingsChange(this.#classicFfPageWatchers) ||
759-
await this.#checkFeatureFlagsChange(this.#ffPageWatchers);
758+
const needRefresh = await this.#checkConfigurationSettingsChange(this.#ffPageWatchers) ||
759+
await this.#checkEnhancedFeatureFlagsChange(this.#enhancedFfPageWatchers);
760760

761761
if (needRefresh) {
762-
const classicFeatureFlags: ConfigurationSetting[] = await this.#loadClassicFeatureFlags();
763-
const featureFlags: FeatureFlag[] = await this.#loadFeatureFlags();
764-
await this.#setFeatureFlags(classicFeatureFlags, featureFlags);
762+
const featureFlags: ConfigurationSetting[] = await this.#loadFeatureFlags();
763+
const enhancedFeatureFlags: FeatureFlag[] = await this.#loadEnhancedFeatureFlags();
764+
await this.#setFeatureFlags(featureFlags, enhancedFeatureFlags);
765765
}
766766

767767
this.#ffRefreshTimer!.reset();
@@ -850,11 +850,11 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
850850
}
851851

852852
/**
853-
* Checks whether the feature flag collection from the dedicated feature flag endpoint has changed.
854-
* @param selectors - The @see PagedSettingsWatcher of the feature flag collection.
855-
* @returns true if the feature flag collection has changed, false otherwise.
853+
* Checks whether the enhanced feature flag collection from the dedicated feature flag endpoint has changed.
854+
* @param selectors - The @see PagedSettingsWatcher of the enhanced feature flag collection.
855+
* @returns true if the enhanced feature flag collection has changed, false otherwise.
856856
*/
857-
async #checkFeatureFlagsChange(selectors: PagedSettingsWatcher[]): Promise<boolean> {
857+
async #checkEnhancedFeatureFlagsChange(selectors: PagedSettingsWatcher[]): Promise<boolean> {
858858
const funcToExecute = async (client: IAppConfigurationClient) => {
859859
for (const selector of selectors) {
860860
if (selector.snapshotName) {
@@ -948,7 +948,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
948948
return await this.#executeWithFailoverPolicy(funcToExecute);
949949
}
950950

951-
async #listFeatureFlags(listOptions: ListFeatureFlagsOptions): Promise<{ items: FeatureFlag[]; pageWatchers: SettingWatcher[] }> {
951+
async #listEnhancedFeatureFlags(listOptions: ListFeatureFlagsOptions): Promise<{ items: FeatureFlag[]; pageWatchers: SettingWatcher[] }> {
952952
const funcToExecute = async (client: IAppConfigurationClient) => {
953953
const pageWatchers: SettingWatcher[] = [];
954954
const pageIterator = client.listFeatureFlags(
@@ -1099,7 +1099,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
10991099
return key;
11001100
}
11011101

1102-
async #parseClassicFeatureFlag(setting: ConfigurationSetting<string>): Promise<any> {
1102+
async #parseFeatureFlag(setting: ConfigurationSetting<string>): Promise<any> {
11031103
const rawFlag = setting.value;
11041104
if (rawFlag === undefined) {
11051105
throw new ArgumentError(ErrorMessages.CONFIGURATION_SETTING_VALUE_UNDEFINED);
@@ -1117,7 +1117,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
11171117
return featureFlag;
11181118
}
11191119

1120-
async #parseFeatureFlag(featureFlag: FeatureFlag): Promise<any> {
1120+
async #parseEnhancedFeatureFlag(featureFlag: FeatureFlag): Promise<any> {
11211121
const parsedFeatureFlag = convertToMicrosoftSchema(featureFlag);
11221122

11231123
let featureFlagReference = `${this.#clientManager.endpoint.origin}/ff/${featureFlagPrefix}${featureFlag.name}`;
@@ -1365,7 +1365,7 @@ function getPageWatchers(selectors?: SettingSelector[]): PagedSettingsWatcher[]
13651365
return getValidSettingSelectors(selectors);
13661366
}
13671367

1368-
function getClassicFeatureFlagPageWatchers(selectors?: SettingSelector[]): PagedSettingsWatcher[] {
1368+
function getFeatureFlagPageWatchers(selectors?: SettingSelector[]): PagedSettingsWatcher[] {
13691369
if (selectors === undefined || selectors.length === 0) {
13701370
// Default selector: key/name: *, label: \0
13711371
return [{ keyFilter: `${featureFlagPrefix}${KeyFilter.Any}`, labelFilter: LabelFilter.Null }];

test/featureFlag.test.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as chai from "chai";
66
import chaiAsPromised from "chai-as-promised";
77
import { featureFlagContentType } from "@azure/app-configuration";
88
import { load } from "../src/index.js";
9-
import { mockAppConfigurationClientGetSnapshot, mockAppConfigurationClientListConfigurationSettingsForSnapshot, createMockedConnectionString, createMockedEndpoint, createMockedFeatureFlag, createMockedNewFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sleepInMs } from "./utils/testHelper.js";
9+
import { mockAppConfigurationClientGetSnapshot, mockAppConfigurationClientListConfigurationSettingsForSnapshot, createMockedConnectionString, createMockedEndpoint, createMockedFeatureFlag, createMockedEnhancedFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sleepInMs } from "./utils/testHelper.js";
1010
chai.use(chaiAsPromised);
1111
const expect = chai.expect;
1212

@@ -501,17 +501,17 @@ describe("feature flags", function () {
501501
});
502502
});
503503

504-
describe("feature flags from the new endpoint", function () {
504+
describe("enhanced feature flags", function () {
505505

506506
afterEach(() => {
507507
restoreMocks();
508508
});
509509

510510
it("should load feature flags from the dedicated feature flag endpoint", async () => {
511-
// no classic feature flags; two feature flags returned by the new endpoint
511+
// no feature flags; two enhanced feature flags returned by the dedicated endpoint
512512
mockAppConfigurationClientListConfigurationSettings([[]], undefined, [[
513-
createMockedNewFeatureFlag("NewAlpha", { enabled: true }),
514-
createMockedNewFeatureFlag("NewBeta", { enabled: false })
513+
createMockedEnhancedFeatureFlag("NewAlpha", { enabled: true }),
514+
createMockedEnhancedFeatureFlag("NewBeta", { enabled: false })
515515
]]);
516516

517517
const settings = await load(createMockedConnectionString(), {
@@ -524,30 +524,30 @@ describe("feature flags from the new endpoint", function () {
524524
expect(featureFlags.find(ff => ff.id === "NewBeta").enabled).equals(false);
525525
});
526526

527-
it("should let a new feature flag supersede a classic feature flag with the same name", async () => {
528-
// classic "Shared" is enabled and "ClassicOnly" exists; the new endpoint returns "Shared" disabled
529-
const classicFeatureFlags = [
527+
it("should let an enhanced feature flag supersede a feature flag with the same name", async () => {
528+
// "Shared" is enabled and "ClassicOnly" exists; the dedicated endpoint returns "Shared" disabled
529+
const featureFlagSettings = [
530530
createMockedFeatureFlag("Shared", { enabled: true }),
531531
createMockedFeatureFlag("ClassicOnly", { enabled: true })
532532
];
533-
mockAppConfigurationClientListConfigurationSettings([classicFeatureFlags], undefined, [[
534-
createMockedNewFeatureFlag("Shared", { enabled: false })
533+
mockAppConfigurationClientListConfigurationSettings([featureFlagSettings], undefined, [[
534+
createMockedEnhancedFeatureFlag("Shared", { enabled: false })
535535
]]);
536536

537537
const settings = await load(createMockedConnectionString(), {
538538
featureFlagOptions: { enabled: true }
539539
});
540540

541541
const featureFlags = settings.get<any>("feature_management").feature_flags as any[];
542-
// "Shared" appears once (from the new endpoint, disabled); "ClassicOnly" remains
542+
// "Shared" appears once (from the dedicated endpoint, disabled); "ClassicOnly" remains
543543
expect(featureFlags.length).equals(2);
544544
expect(featureFlags.filter(ff => ff.id === "Shared").length).equals(1);
545545
expect(featureFlags.find(ff => ff.id === "Shared").enabled).equals(false);
546546
expect(featureFlags.find(ff => ff.id === "ClassicOnly").enabled).equals(true);
547547
});
548548

549-
it("should convert a new feature flag into the feature management schema", async () => {
550-
const newFeatureFlag = createMockedNewFeatureFlag("Variant", {
549+
it("should convert an enhanced feature flag into the feature management schema", async () => {
550+
const enhancedFeatureFlag = createMockedEnhancedFeatureFlag("Variant", {
551551
conditions: {
552552
requirementType: "All",
553553
filters: [{ name: "Microsoft.TimeWindow", parameters: { Start: "Mon, 01 Jan 2024 00:00:00 GMT" } }]
@@ -564,7 +564,7 @@ describe("feature flags from the new endpoint", function () {
564564
},
565565
telemetry: { enabled: true }
566566
});
567-
mockAppConfigurationClientListConfigurationSettings([[]], undefined, [[newFeatureFlag]]);
567+
mockAppConfigurationClientListConfigurationSettings([[]], undefined, [[enhancedFeatureFlag]]);
568568

569569
const settings = await load(createMockedConnectionString(), {
570570
featureFlagOptions: { enabled: true }
@@ -586,9 +586,9 @@ describe("feature flags from the new endpoint", function () {
586586
expect(featureFlag.telemetry.metadata.AllocationId).not.undefined;
587587
});
588588

589-
it("should refresh feature flags when the new endpoint changes", async () => {
589+
it("should refresh feature flags when the dedicated endpoint changes", async () => {
590590
mockAppConfigurationClientListConfigurationSettings([[]], undefined, [[
591-
createMockedNewFeatureFlag("NewFlag", { enabled: true })
591+
createMockedEnhancedFeatureFlag("NewFlag", { enabled: true })
592592
]]);
593593

594594
const settings = await load(createMockedConnectionString(), {
@@ -601,10 +601,10 @@ describe("feature flags from the new endpoint", function () {
601601
let featureFlag = (settings.get<any>("feature_management").feature_flags as any[]).find(ff => ff.id === "NewFlag");
602602
expect(featureFlag.enabled).equals(true);
603603

604-
// the feature flag on the new endpoint changes
604+
// the enhanced feature flag on the dedicated endpoint changes
605605
restoreMocks();
606606
mockAppConfigurationClientListConfigurationSettings([[]], undefined, [[
607-
createMockedNewFeatureFlag("NewFlag", { enabled: false })
607+
createMockedEnhancedFeatureFlag("NewFlag", { enabled: false })
608608
]]);
609609

610610
await sleepInMs(1000 + 1);

test/loadBalance.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ describe("load balance", function () {
5151
}
5252
}
5353
});
54-
// one request for key values, one for classic feature flags, one for the new feature flag endpoint
54+
// one request for key values, one for feature flags, one for the dedicated feature flag endpoint
5555
expect(clientRequestCounter_1.count).eq(2);
5656
expect(clientRequestCounter_2.count).eq(1);
5757

5858
await sleepInMs(2 * 1000 + 1);
5959
await settings.refresh();
60-
// refresh: one request to check classic feature flags, one to check the new feature flag endpoint
60+
// refresh: one request to check feature flags, one to check the dedicated feature flag endpoint
6161
expect(clientRequestCounter_1.count).eq(3);
6262
expect(clientRequestCounter_2.count).eq(2);
6363

@@ -88,13 +88,13 @@ describe("load balance", function () {
8888
}
8989
}
9090
});
91-
// one request for key values, one for classic feature flags, one for the new feature flag endpoint
91+
// one request for key values, one for feature flags, one for the dedicated feature flag endpoint
9292
expect(clientRequestCounter_1.count).eq(3);
9393
expect(clientRequestCounter_2.count).eq(0);
9494

9595
await sleepInMs(2 * 1000 + 1);
9696
await settings.refresh();
97-
// refresh: check classic feature flags + check the new feature flag endpoint, all to the first client
97+
// refresh: check feature flags + check the dedicated feature flag endpoint, all to the first client
9898
expect(clientRequestCounter_1.count).eq(5);
9999
expect(clientRequestCounter_2.count).eq(0);
100100
});

0 commit comments

Comments
 (0)