Skip to content

Commit 66076e3

Browse files
feat: implement caching of doctor result
Currently each project related CLI command checks the status of the machine. This takes between 4 and 9 seconds on different machines. Cache the result per project and based on the environment variables used in the checks.
1 parent 38e7dd7 commit 66076e3

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

lib/services/doctor-service.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ export class DoctorService implements IDoctorService {
99
private static WindowsSetupScriptExecutable = "powershell.exe";
1010
private static WindowsSetupScriptArguments = ["start-process", "-FilePath", "PowerShell.exe", "-NoNewWindow", "-Wait", "-ArgumentList", '"-NoProfile -ExecutionPolicy Bypass -Command iex ((new-object net.webclient).DownloadString(\'https://www.nativescript.org/setup/win\'))"'];
1111

12+
private get $jsonFileSettingsService(): IJsonFileSettingsService {
13+
const jsonFileSettingsPath = path.join(this.$settingsService.getProfileDir(), "doctor-cache.json");
14+
return this.$injector.resolve<IJsonFileSettingsService>("jsonFileSettingsService", { jsonFileSettingsPath });
15+
}
16+
1217
constructor(private $analyticsService: IAnalyticsService,
1318
private $hostInfo: IHostInfo,
1419
private $logger: ILogger,
@@ -17,12 +22,14 @@ export class DoctorService implements IDoctorService {
1722
private $projectDataService: IProjectDataService,
1823
private $fs: IFileSystem,
1924
private $terminalSpinnerService: ITerminalSpinnerService,
20-
private $versionsService: IVersionsService) { }
25+
private $versionsService: IVersionsService,
26+
private $settingsService: ISettingsService) { }
2127

2228
public async printWarnings(configOptions?: { trackResult: boolean, projectDir?: string, runtimeVersion?: string, options?: IOptions }): Promise<void> {
29+
const getInfosData: any = { projectDir: configOptions && configOptions.projectDir, androidRuntimeVersion: configOptions && configOptions.runtimeVersion };
2330
const infos = await this.$terminalSpinnerService.execute<NativeScriptDoctor.IInfo[]>({
2431
text: `Getting environment information ${EOL}`
25-
}, () => doctor.getInfos({ projectDir: configOptions && configOptions.projectDir, androidRuntimeVersion: configOptions && configOptions.runtimeVersion }));
32+
}, () => this.getInfos(getInfosData));
2633

2734
const warnings = infos.filter(info => info.type === constants.WARNING_TYPE_NAME);
2835
const hasWarnings = warnings.length > 0;
@@ -41,6 +48,7 @@ export class DoctorService implements IDoctorService {
4148
this.$logger.info("There seem to be issues with your configuration.");
4249
} else {
4350
this.$logger.info("No issues were detected.".bold);
51+
await this.$jsonFileSettingsService.saveSetting(this.getKeyForConfiguration(getInfosData), infos);
4452
this.printInfosCore(infos);
4553
}
4654

@@ -95,8 +103,8 @@ export class DoctorService implements IDoctorService {
95103
action: TrackActionNames.CheckLocalBuildSetup,
96104
additionalData: "Starting",
97105
});
98-
const infos = await doctor.getInfos({ platform, projectDir, androidRuntimeVersion: runtimeVersion });
99-
106+
const sysInfoConfig: NativeScriptDoctor.ISysInfoConfig = { platform, projectDir, androidRuntimeVersion: runtimeVersion };
107+
const infos = await this.getInfos(sysInfoConfig);
100108
const warnings = this.filterInfosByType(infos, constants.WARNING_TYPE_NAME);
101109
const hasWarnings = warnings.length > 0;
102110
if (hasWarnings) {
@@ -107,6 +115,7 @@ export class DoctorService implements IDoctorService {
107115
this.printInfosCore(infos);
108116
} else {
109117
infos.map(info => this.$logger.trace(info.message));
118+
await this.$jsonFileSettingsService.saveSetting(this.getKeyForConfiguration(sysInfoConfig), infos);
110119
}
111120

112121
await this.$analyticsService.trackEventActionInGoogleAnalytics({
@@ -221,5 +230,35 @@ export class DoctorService implements IDoctorService {
221230
private filterInfosByType(infos: NativeScriptDoctor.IInfo[], type: string): NativeScriptDoctor.IInfo[] {
222231
return infos.filter(info => info.type === type);
223232
}
233+
234+
private getKeyForConfiguration(sysInfoConfig?: NativeScriptDoctor.ISysInfoConfig): string {
235+
const nativeScriptData = sysInfoConfig && sysInfoConfig.projectDir && JSON.stringify(this.$fs.readJson(path.join(sysInfoConfig.projectDir, "package.json")).nativescript);
236+
const delimiter = "__";
237+
const key = [
238+
JSON.stringify(sysInfoConfig),
239+
process.env.ANDROID_HOME,
240+
process.env.JAVA_HOME,
241+
process.env["CommonProgramFiles(x86)"],
242+
process.env["CommonProgramFiles"],
243+
process.env.PROCESSOR_ARCHITEW6432,
244+
process.env.ProgramFiles,
245+
process.env["ProgramFiles(x86)"],
246+
nativeScriptData
247+
]
248+
.filter(a => !!a)
249+
.join(delimiter);
250+
251+
const data = helpers.getHash(key, { algorithm: "md5" });
252+
return data;
253+
}
254+
255+
private async getInfos(sysInfoConfig?: NativeScriptDoctor.ISysInfoConfig): Promise<NativeScriptDoctor.IInfo[]> {
256+
const key = this.getKeyForConfiguration(sysInfoConfig);
257+
// check if we already have cache for the results here
258+
const infosFromCache = await this.$jsonFileSettingsService.getSettingValue<NativeScriptDoctor.IInfo[]>(key);
259+
const infos = infosFromCache || await doctor.getInfos(sysInfoConfig);
260+
261+
return infos;
262+
}
224263
}
225264
$injector.register("doctorService", DoctorService);

test/services/doctor-service.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ class DoctorServiceInheritor extends DoctorService {
1313
$projectDataService: IProjectDataService,
1414
$fs: IFileSystem,
1515
$terminalSpinnerService: ITerminalSpinnerService,
16-
$versionsService: IVersionsService) {
17-
super($analyticsService, $hostInfo, $logger, $childProcess, $injector, $projectDataService, $fs, $terminalSpinnerService, $versionsService);
16+
$versionsService: IVersionsService,
17+
$settingsService: ISettingsService) {
18+
super($analyticsService, $hostInfo, $logger, $childProcess, $injector, $projectDataService, $fs, $terminalSpinnerService, $versionsService, $settingsService);
1819
}
1920

2021
public getDeprecatedShortImportsInFiles(files: string[], projectDir: string): { file: string, line: string }[] {
@@ -34,6 +35,13 @@ describe("doctorService", () => {
3435
testInjector.register("fs", {});
3536
testInjector.register("terminalSpinnerService", {});
3637
testInjector.register("versionsService", {});
38+
testInjector.register("settingsService", {
39+
getProfileDir: (): string => ""
40+
});
41+
testInjector.register("jsonFileSettingsService", {
42+
getSettingValue: async (settingName: string, cacheOpts?: ICacheTimeoutOpts): Promise<any> => undefined,
43+
saveSetting: async (key: string, value: any, cacheOpts?: IUseCacheOpts): Promise<void> => undefined
44+
});
3745

3846
return testInjector;
3947
};

0 commit comments

Comments
 (0)