Skip to content

Commit 4f20755

Browse files
Kartik Rajkarthiknadig
authored andcommitted
Deprecate inExperiment API in favor of inExperimentSync (#16848)
* Deprecate inExperiment API in favour of inExperimentSync * Ensure experiments are activated before they are used * News entry
1 parent d93ef08 commit 4f20755

File tree

5 files changed

+7
-197
lines changed

5 files changed

+7
-197
lines changed

news/2 Fixes/16768.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix random delay before several actions.

src/client/common/experiments/service.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -88,30 +88,7 @@ export class ExperimentService implements IExperimentService {
8888
}
8989

9090
public async inExperiment(experiment: string): Promise<boolean> {
91-
if (!this.experimentationService) {
92-
return false;
93-
}
94-
95-
// Currently the service doesn't support opting in and out of experiments.
96-
// so we need to perform these checks manually.
97-
if (this._optOutFrom.includes('All') || this._optOutFrom.includes(experiment)) {
98-
return false;
99-
}
100-
101-
if (this._optInto.includes('All') || this._optInto.includes(experiment)) {
102-
// Check if the user was already in the experiment server-side. We need to do
103-
// this to ensure the experiment service is ready and internal states are fully
104-
// synced with the experiment server.
105-
await this.experimentationService.getTreatmentVariableAsync(EXP_CONFIG_ID, experiment, true);
106-
return true;
107-
}
108-
109-
const treatmentVariable = await this.experimentationService.getTreatmentVariableAsync(
110-
EXP_CONFIG_ID,
111-
experiment,
112-
true,
113-
);
114-
return treatmentVariable !== undefined;
91+
return this.inExperimentSync(experiment);
11592
}
11693

11794
public inExperimentSync(experiment: string): boolean {

src/client/extension.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { ProgressLocation, ProgressOptions, window } from 'vscode';
3030
import { buildApi, IExtensionApi } from './api';
3131
import { IApplicationShell } from './common/application/types';
3232
import { traceError } from './common/logger';
33-
import { IAsyncDisposableRegistry, IExtensionContext } from './common/types';
33+
import { IAsyncDisposableRegistry, IExperimentService, IExtensionContext } from './common/types';
3434
import { createDeferred } from './common/utils/async';
3535
import { Common } from './common/utils/localize';
3636
import { activateComponents } from './extensionActivation';
@@ -103,6 +103,10 @@ async function activateUnsafe(
103103
// Note standard utils especially experiment and platform code are fundamental to the extension
104104
// and should be available before we activate anything else.Hence register them first.
105105
initializeStandard(ext);
106+
// We need to activate experiments before initializing components as objects are created or not created based on experiments.
107+
const experimentService = activatedServiceContainer.get<IExperimentService>(IExperimentService);
108+
// This guarantees that all experiment information has loaded & all telemetry will contain experiment info.
109+
await experimentService.activate();
106110
const components = await initializeComponents(ext);
107111

108112
// Then we finish activating.

src/client/extensionActivation.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ async function activateLegacy(ext: ExtensionState): Promise<ActivationResult> {
123123
tensorBoardRegisterTypes(serviceManager);
124124

125125
const experimentService = serviceContainer.get<IExperimentService>(IExperimentService);
126-
// This guarantees that all experiment information has loaded & all telemetry will contain experiment info.
127-
await experimentService.activate();
128126

129127
const workspaceService = serviceContainer.get<IWorkspaceService>(IWorkspaceService);
130128
const extensions = serviceContainer.get<IExtensions>(IExtensions);

src/test/common/experiments/service.unit.test.ts

Lines changed: 0 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -155,176 +155,6 @@ suite('Experimentation service', () => {
155155
});
156156
});
157157

158-
suite('In-experiment check', () => {
159-
const experiment = 'Test Experiment - experiment';
160-
let telemetryEvents: { eventName: string; properties: Record<string, unknown> }[] = [];
161-
let getTreatmentVariableAsyncStub: sinon.SinonStub;
162-
let sendTelemetryEventStub: sinon.SinonStub;
163-
164-
setup(() => {
165-
sendTelemetryEventStub = sinon
166-
.stub(Telemetry, 'sendTelemetryEvent')
167-
.callsFake((eventName: string, _, properties: Record<string, unknown>) => {
168-
const telemetry = { eventName, properties };
169-
telemetryEvents.push(telemetry);
170-
});
171-
172-
getTreatmentVariableAsyncStub = sinon.stub().returns(Promise.resolve(true));
173-
sinon.stub(tasClient, 'getExperimentationService').returns(({
174-
getTreatmentVariableAsync: getTreatmentVariableAsyncStub,
175-
} as unknown) as tasClient.IExperimentationService);
176-
177-
configureApplicationEnvironment('stable', extensionVersion);
178-
});
179-
180-
teardown(() => {
181-
telemetryEvents = [];
182-
});
183-
184-
test('If the opt-in and opt-out arrays are empty, return the value from the experimentation framework for a given experiment', async () => {
185-
configureSettings(true, [], []);
186-
187-
const experimentService = new ExperimentService(
188-
instance(workspaceService),
189-
instance(appEnvironment),
190-
globalMemento,
191-
outputChannel,
192-
);
193-
const result = await experimentService.inExperiment(experiment);
194-
195-
assert.isTrue(result);
196-
sinon.assert.notCalled(sendTelemetryEventStub);
197-
sinon.assert.calledOnce(getTreatmentVariableAsyncStub);
198-
});
199-
200-
test('If the experiment setting is disabled, inExperiment should return false', async () => {
201-
configureSettings(false, [], []);
202-
203-
const experimentService = new ExperimentService(
204-
instance(workspaceService),
205-
instance(appEnvironment),
206-
globalMemento,
207-
outputChannel,
208-
);
209-
const result = await experimentService.inExperiment(experiment);
210-
211-
assert.isFalse(result);
212-
sinon.assert.notCalled(sendTelemetryEventStub);
213-
sinon.assert.notCalled(getTreatmentVariableAsyncStub);
214-
});
215-
216-
test('If the opt-in setting contains "All", inExperiment should return true', async () => {
217-
configureSettings(true, ['All'], []);
218-
219-
const experimentService = new ExperimentService(
220-
instance(workspaceService),
221-
instance(appEnvironment),
222-
globalMemento,
223-
outputChannel,
224-
);
225-
const result = await experimentService.inExperiment(experiment);
226-
227-
assert.isTrue(result);
228-
assert.strictEqual(telemetryEvents.length, 0);
229-
});
230-
231-
test('If the opt-in setting contains `All`, inExperiment should check the value cached by the experiment service', async () => {
232-
configureSettings(true, ['All'], []);
233-
234-
const experimentService = new ExperimentService(
235-
instance(workspaceService),
236-
instance(appEnvironment),
237-
globalMemento,
238-
outputChannel,
239-
);
240-
const result = await experimentService.inExperiment(experiment);
241-
242-
assert.isTrue(result);
243-
sinon.assert.notCalled(sendTelemetryEventStub);
244-
sinon.assert.calledOnce(getTreatmentVariableAsyncStub);
245-
});
246-
247-
test('If the opt-in setting contains `All` and the experiment setting is disabled, inExperiment should return false', async () => {
248-
configureSettings(false, ['All'], []);
249-
250-
const experimentService = new ExperimentService(
251-
instance(workspaceService),
252-
instance(appEnvironment),
253-
globalMemento,
254-
outputChannel,
255-
);
256-
const result = await experimentService.inExperiment(experiment);
257-
258-
assert.isFalse(result);
259-
sinon.assert.notCalled(sendTelemetryEventStub);
260-
sinon.assert.notCalled(getTreatmentVariableAsyncStub);
261-
});
262-
263-
test('If the opt-in setting contains the experiment name, inExperiment should return true', async () => {
264-
configureSettings(true, [experiment], []);
265-
266-
const experimentService = new ExperimentService(
267-
instance(workspaceService),
268-
instance(appEnvironment),
269-
globalMemento,
270-
outputChannel,
271-
);
272-
const result = await experimentService.inExperiment(experiment);
273-
274-
assert.isTrue(result);
275-
assert.strictEqual(telemetryEvents.length, 0);
276-
sinon.assert.calledOnce(getTreatmentVariableAsyncStub);
277-
});
278-
279-
test('If the opt-out setting contains "All", inExperiment should return false', async () => {
280-
configureSettings(true, [], ['All']);
281-
282-
const experimentService = new ExperimentService(
283-
instance(workspaceService),
284-
instance(appEnvironment),
285-
globalMemento,
286-
outputChannel,
287-
);
288-
const result = await experimentService.inExperiment(experiment);
289-
290-
assert.isFalse(result);
291-
sinon.assert.notCalled(sendTelemetryEventStub);
292-
sinon.assert.notCalled(getTreatmentVariableAsyncStub);
293-
});
294-
295-
test('If the opt-out setting contains "All" and the experiment setting is enabled, inExperiment should return false', async () => {
296-
configureSettings(true, [], ['All']);
297-
298-
const experimentService = new ExperimentService(
299-
instance(workspaceService),
300-
instance(appEnvironment),
301-
globalMemento,
302-
outputChannel,
303-
);
304-
const result = await experimentService.inExperiment(experiment);
305-
306-
assert.isFalse(result);
307-
sinon.assert.notCalled(sendTelemetryEventStub);
308-
sinon.assert.notCalled(getTreatmentVariableAsyncStub);
309-
});
310-
311-
test('If the opt-out setting contains the experiment name, inExperiment should return false', async () => {
312-
configureSettings(true, [], [experiment]);
313-
314-
const experimentService = new ExperimentService(
315-
instance(workspaceService),
316-
instance(appEnvironment),
317-
globalMemento,
318-
outputChannel,
319-
);
320-
const result = await experimentService.inExperiment(experiment);
321-
322-
assert.isFalse(result);
323-
assert.strictEqual(telemetryEvents.length, 0);
324-
sinon.assert.notCalled(getTreatmentVariableAsyncStub);
325-
});
326-
});
327-
328158
suite('In-experiment-sync check', () => {
329159
const experiment = 'Test Experiment - experiment';
330160
let telemetryEvents: { eventName: string; properties: Record<string, unknown> }[] = [];

0 commit comments

Comments
 (0)