Skip to content

Commit f2b5f80

Browse files
author
Kartik Raj
committed
Code reviews
1 parent e6a9260 commit f2b5f80

File tree

1 file changed

+55
-43
lines changed

1 file changed

+55
-43
lines changed

src/client/pythonEnvironments/collection/environmentsReducer.ts

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
import { isEqual } from 'lodash';
45
import { Event, EventEmitter } from 'vscode';
6+
import { traceVerbose } from '../../common/logger';
57
import { areSameEnvironment, PythonEnvInfo, PythonEnvKind } from '../base/info';
68
import {
79
ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, QueryForEvent,
810
} from '../base/locator';
911
import { PythonEnvsChangedEvent } from '../base/watcher';
1012

13+
/**
14+
* Combines duplicate environments received from the incoming locator into one and passes on unique environments
15+
*/
1116
export class PythonEnvsReducer implements ILocator {
1217
public get onChanged(): Event<PythonEnvsChangedEvent> {
1318
return this.pythonEnvsManager.onChanged;
@@ -21,68 +26,75 @@ export class PythonEnvsReducer implements ILocator {
2126

2227
public iterEnvs(query?: QueryForEvent<PythonEnvsChangedEvent>): IPythonEnvsIterator {
2328
const didUpdate = new EventEmitter<PythonEnvUpdatedEvent | null>();
24-
const iterator: IPythonEnvsIterator = this.iterEnvsIterator(didUpdate, query);
29+
const incomingIterator = this.pythonEnvsManager.iterEnvs(query);
30+
const iterator: IPythonEnvsIterator = iterEnvsIterator(incomingIterator, didUpdate);
2531
iterator.onUpdated = didUpdate.event;
2632
return iterator;
2733
}
34+
}
2835

29-
private async* iterEnvsIterator(
30-
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
31-
query?: QueryForEvent<PythonEnvsChangedEvent>,
32-
): AsyncIterator<PythonEnvInfo, void> {
33-
const state = {
34-
done: false,
35-
pending: 0,
36-
};
37-
const seen: PythonEnvInfo[] = [];
38-
const iterator = this.pythonEnvsManager.iterEnvs(query);
36+
async function* iterEnvsIterator(
37+
iterator: IPythonEnvsIterator,
38+
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
39+
): AsyncIterator<PythonEnvInfo, void> {
40+
const state = {
41+
done: false,
42+
pending: 0,
43+
};
44+
const seen: PythonEnvInfo[] = [];
3945

40-
if (iterator.onUpdated !== undefined) {
41-
iterator.onUpdated((event) => {
42-
if (event === null) {
43-
state.done = true;
44-
checkIfFinishedAndNotify(state, didUpdate);
46+
if (iterator.onUpdated !== undefined) {
47+
iterator.onUpdated((event) => {
48+
if (event === null) {
49+
state.done = true;
50+
checkIfFinishedAndNotify(state, didUpdate);
51+
} else {
52+
const oldIndex = seen.findIndex((s) => areSameEnvironment(s, event.old));
53+
if (oldIndex !== -1) {
54+
state.pending += 1;
55+
resolveDifferencesInBackground(oldIndex, event.new, state, didUpdate, seen).ignoreErrors();
4556
} else {
46-
const old = seen.find((s) => areSameEnvironment(s, event.old));
47-
if (old !== undefined) {
48-
state.pending += 1;
49-
resolveDifferencesInBackground(old, event.new, state, didUpdate, seen).ignoreErrors();
50-
}
57+
// This implies a problem in a downstream locator
58+
traceVerbose(`Expected already iterated env, got ${event.old}`);
5159
}
52-
});
53-
}
54-
55-
let result = await iterator.next();
56-
while (!result.done) {
57-
const currEnv = result.value;
58-
const old = seen.find((s) => areSameEnvironment(s, currEnv));
59-
if (old !== undefined) {
60-
state.pending += 1;
61-
resolveDifferencesInBackground(old, currEnv, state, didUpdate, seen).ignoreErrors();
62-
} else {
63-
yield currEnv;
64-
seen.push(currEnv);
6560
}
66-
// eslint-disable-next-line no-await-in-loop
67-
result = await iterator.next();
68-
}
69-
if (iterator.onUpdated === undefined) {
70-
state.done = true;
71-
checkIfFinishedAndNotify(state, didUpdate);
61+
});
62+
}
63+
64+
let result = await iterator.next();
65+
while (!result.done) {
66+
const currEnv = result.value;
67+
const oldIndex = seen.findIndex((s) => areSameEnvironment(s, currEnv));
68+
if (oldIndex !== -1) {
69+
state.pending += 1;
70+
resolveDifferencesInBackground(oldIndex, currEnv, state, didUpdate, seen).ignoreErrors();
71+
} else {
72+
// We haven't yielded a matching env so yield this one as-is.
73+
yield currEnv;
74+
seen.push(currEnv);
7275
}
76+
// eslint-disable-next-line no-await-in-loop
77+
result = await iterator.next();
78+
}
79+
if (iterator.onUpdated === undefined) {
80+
state.done = true;
81+
checkIfFinishedAndNotify(state, didUpdate);
7382
}
7483
}
7584

7685
async function resolveDifferencesInBackground(
77-
oldEnv: PythonEnvInfo,
86+
oldIndex: number,
7887
newEnv: PythonEnvInfo,
7988
state: { done: boolean; pending: number },
8089
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
8190
seen: PythonEnvInfo[],
8291
) {
92+
const oldEnv = seen[oldIndex];
8393
const merged = mergeEnvironments(oldEnv, newEnv);
84-
didUpdate.fire({ old: oldEnv, new: merged });
85-
seen[seen.indexOf(oldEnv)] = merged;
94+
if (!isEqual(oldEnv, merged)) {
95+
didUpdate.fire({ old: oldEnv, new: merged });
96+
seen[oldIndex] = merged;
97+
}
8698
state.pending -= 1;
8799
checkIfFinishedAndNotify(state, didUpdate);
88100
}

0 commit comments

Comments
 (0)