()
| 78 | } |
| 79 | |
| 80 | async initialize(): Promise<void> { |
| 81 | if (this.cacheLoaded) { |
| 82 | return; |
| 83 | } |
| 84 | |
| 85 | await this.loadCacheFromDisk(); |
| 86 | this.cacheLoaded = true; |
| 87 | |
| 88 | // Populate telemetry properties from cache immediately so variant breakdowns |
| 89 | // are present even before a background refresh completes. |
| 90 | for (const [experimentId, cached] of this.cachedVariants) { |
| 91 | if (!this.isExperimentSupported(experimentId)) { |
| 92 | this.telemetryService.setFeatureFlagVariant(this.getFlagKey(experimentId), null); |
| 93 | continue; |
| 94 | } |
| 95 | |
| 96 | this.telemetryService.setFeatureFlagVariant(this.getFlagKey(experimentId), cached.value); |
| 97 | } |
| 98 | |
| 99 | // Renderer overrides must win over cached/remote assignments so server-side gates |
| 100 | // and telemetry reflect the same explicit user choice on fresh launches. |
| 101 | for (const [experimentId, enabled] of this.overrides) { |
| 102 | if (!this.isExperimentSupported(experimentId)) { |
| 103 | this.telemetryService.setFeatureFlagVariant(this.getFlagKey(experimentId), null); |
| 104 | continue; |
| 105 | } |
| 106 | |
| 107 | this.telemetryService.setFeatureFlagVariant(this.getFlagKey(experimentId), enabled); |
| 108 | } |
| 109 | |
| 110 | // Refresh in background (best effort). We only refresh values that are stale or missing |
| 111 | // to avoid unnecessary network calls during startup. |
| 112 | if (this.isRemoteEvaluationEnabled()) { |
| 113 | for (const experimentId of Object.keys(EXPERIMENTS) as ExperimentId[]) { |
| 114 | this.maybeRefreshInBackground(experimentId); |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | isRemoteEvaluationEnabled(): boolean { |
| 120 | return ( |
no test coverage detected