Skip to content

Commit

Permalink
Code reviews
Browse files Browse the repository at this point in the history
  • Loading branch information
Kartik Raj committed Sep 17, 2020
1 parent 37db846 commit 4fd7f38
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 90 deletions.
110 changes: 110 additions & 0 deletions src/client/pythonEnvironments/collection/environmentsReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { Event, EventEmitter } from 'vscode';
import { PythonEnvInfo } from '../base/info';
import {
ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, QueryForEvent,
} from '../base/locator';
import { PythonEnvsChangedEvent } from '../base/watcher';
import { mergeEnvironments } from '../info';

type PythonEnvsIteratorState = {
/**
* Set to true when all information from incoming iterator has been received
*/
done: boolean;
/**
* Carries the number of pending background calls ongoing at the moment
*/
pending: number;
};

export class PythonEnvsReducer implements ILocator {
public get onChanged(): Event<PythonEnvsChangedEvent> {
return this.pythonEnvsManager.onChanged;
}

constructor(private readonly pythonEnvsManager: ILocator) {}

public resolveEnv(env: string | PythonEnvInfo): Promise<PythonEnvInfo | undefined> {
return this.pythonEnvsManager.resolveEnv(env);
}

public iterEnvs(query?: QueryForEvent<PythonEnvsChangedEvent>): IPythonEnvsIterator {
const didUpdate = new EventEmitter<PythonEnvUpdatedEvent | null>();
return { ...this.iterEnvsIterator(didUpdate, query), onUpdated: didUpdate.event };
}

private async* iterEnvsIterator(
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
query?: QueryForEvent<PythonEnvsChangedEvent>,
): AsyncIterator<PythonEnvInfo, void> {
const state: PythonEnvsIteratorState = {
done: false,
pending: 0,
};
const seen: PythonEnvInfo[] = [];
const iterator = this.pythonEnvsManager.iterEnvs(query);

if (iterator.onUpdated !== undefined) {
iterator.onUpdated((event) => {
if (event === null) {
state.done = true;
checkIfFinishedAndNotify(state, didUpdate);
} else {
const old = seen.find((s) => s.location === event.old.location);
if (old !== undefined) {
state.pending += 1;
resolveDifferencesInBackground(old, event.new, state, didUpdate).ignoreErrors();
}
}
});
}

let result = await iterator.next();
while (!result.done) {
const currEnv = result.value;
const old = seen.find((s) => s.location === currEnv.location);
if (old !== undefined) {
state.pending += 1;
resolveDifferencesInBackground(old, currEnv, state, didUpdate).ignoreErrors();
} else {
yield currEnv;
seen.push(currEnv);
}
// eslint-disable-next-line no-await-in-loop
result = await iterator.next();
}
if (iterator.onUpdated === undefined) {
state.done = true;
}
}
}

async function resolveDifferencesInBackground(
oldEnv: PythonEnvInfo,
newEnv: PythonEnvInfo,
state: PythonEnvsIteratorState,
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
) {
const merged = mergeEnvironments([oldEnv, newEnv])[0];
didUpdate.fire({ old: oldEnv, new: merged });
state.pending -= 1;
checkIfFinishedAndNotify(state, didUpdate);
}

/**
* When all info from incoming iterator has been received and all background calls finishes, notify that we're done
* @param state Carries the current state of progress
* @param didUpdate Used to notify when finished
*/
function checkIfFinishedAndNotify(
state: PythonEnvsIteratorState,
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
) {
if (state.done && state.pending === 0) {
didUpdate.fire(null);
didUpdate.dispose();
}
}
90 changes: 0 additions & 90 deletions src/client/pythonEnvironments/environmentsReducer.ts

This file was deleted.

0 comments on commit 4fd7f38

Please sign in to comment.