1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-07 01:16:28 +02:00

fix: version-service should not use process.nextTick (#6124)

In the beginning we used process.nextTick() as a trick to load some data
initally in the constructor of a service.

This is a bad pattern and we should generally avoid any async operations
in the constructor. Today we have two alternatives:

1. Defer loading until data is needed (wrap it in async)
2. Use the schdule-service.
This commit is contained in:
Ivar Conradi Østhus 2024-02-05 11:24:37 +01:00 committed by GitHub
parent 354b88383c
commit 897500dd54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 20 additions and 21 deletions

View File

@ -211,7 +211,7 @@ export class InstanceStatsService {
* use getStatsSnapshot for low latency, sacrificing data-freshness * use getStatsSnapshot for low latency, sacrificing data-freshness
*/ */
async getStats(): Promise<InstanceStats> { async getStats(): Promise<InstanceStats> {
const versionInfo = this.versionService.getVersionInfo(); const versionInfo = await this.versionService.getVersionInfo();
const [ const [
featureToggles, featureToggles,
users, users,

View File

@ -167,7 +167,7 @@ class ConfigController extends Controller {
segmentValuesLimit: this.config.segmentValuesLimit, segmentValuesLimit: this.config.segmentValuesLimit,
strategySegmentsLimit: this.config.strategySegmentsLimit, strategySegmentsLimit: this.config.strategySegmentsLimit,
frontendApiOrigins: frontendSettings.frontendApiOrigins, frontendApiOrigins: frontendSettings.frontendApiOrigins,
versionInfo: this.versionService.getVersionInfo(), versionInfo: await this.versionService.getVersionInfo(),
networkViewEnabled: this.config.prometheusApi !== undefined, networkViewEnabled: this.config.prometheusApi !== undefined,
disablePasswordAuth, disablePasswordAuth,
maintenanceMode, maintenanceMode,

View File

@ -44,7 +44,7 @@ test('yields current versions', async () => {
createFakeGetProductionChanges(), createFakeGetProductionChanges(),
); );
await service.checkLatestVersion(); await service.checkLatestVersion();
const versionInfo = service.getVersionInfo(); const versionInfo = await service.getVersionInfo();
expect(scope.isDone()).toEqual(true); expect(scope.isDone()).toEqual(true);
expect(versionInfo.current.oss).toBe(version); expect(versionInfo.current.oss).toBe(version);
expect(versionInfo.current.enterprise).toBeFalsy(); expect(versionInfo.current.enterprise).toBeFalsy();
@ -83,7 +83,7 @@ test('supports setting enterprise version as well', async () => {
createFakeGetProductionChanges(), createFakeGetProductionChanges(),
); );
await service.checkLatestVersion(); await service.checkLatestVersion();
const versionInfo = service.getVersionInfo(); const versionInfo = await service.getVersionInfo();
expect(scope.isDone()).toEqual(true); expect(scope.isDone()).toEqual(true);
expect(versionInfo.current.oss).toBe(version); expect(versionInfo.current.oss).toBe(version);
expect(versionInfo.current.enterprise).toBe(enterpriseVersion); expect(versionInfo.current.enterprise).toBe(enterpriseVersion);
@ -122,7 +122,7 @@ test('if version check is not enabled should not make any calls', async () => {
createFakeGetProductionChanges(), createFakeGetProductionChanges(),
); );
await service.checkLatestVersion(); await service.checkLatestVersion();
const versionInfo = service.getVersionInfo(); const versionInfo = await service.getVersionInfo();
expect(scope.isDone()).toEqual(false); expect(scope.isDone()).toEqual(false);
expect(versionInfo.current.oss).toBe(version); expect(versionInfo.current.oss).toBe(version);
expect(versionInfo.current.enterprise).toBe(enterpriseVersion); expect(versionInfo.current.enterprise).toBe(enterpriseVersion);

View File

@ -178,35 +178,36 @@ export default class VersionService {
this.telemetryEnabled = telemetry; this.telemetryEnabled = telemetry;
this.versionCheckUrl = versionCheck.url; this.versionCheckUrl = versionCheck.url;
this.isLatest = true; this.isLatest = true;
process.nextTick(() => this.setup());
} }
async setup(): Promise<void> { private async readInstanceId(): Promise<string | undefined> {
await this.readInstanceId();
await this.checkLatestVersion();
}
private async readInstanceId(): Promise<void> {
try { try {
const { id } = (await this.settingStore.get<{ id: string }>( const { id } = (await this.settingStore.get<{ id: string }>(
'instanceInfo', 'instanceInfo',
)) ?? { id: undefined }; )) ?? { id: undefined };
this.instanceId = id; return id;
} catch (err) { } catch (err) {
this.logger.warn('Could not find instanceInfo', err); this.logger.warn('Could not find instanceInfo', err);
} }
} }
getInstanceId() { async getInstanceId() {
if (!this.instanceId) {
this.instanceId = await this.readInstanceId();
}
return this.instanceId; return this.instanceId;
} }
async checkLatestVersion(): Promise<void> { async checkLatestVersion(): Promise<void> {
const instanceId = await this.getInstanceId();
this.logger.debug(
`Checking for newest version for instanceId=${instanceId}`,
);
if (this.enabled) { if (this.enabled) {
try { try {
const versionPayload: any = { const versionPayload: any = {
versions: this.current, versions: this.current,
instanceId: this.instanceId, instanceId: instanceId,
}; };
if (this.telemetryEnabled) { if (this.telemetryEnabled) {
@ -282,7 +283,7 @@ export default class VersionService {
this.userStats(), this.userStats(),
this.productionChanges(), this.productionChanges(),
]); ]);
const versionInfo = this.getVersionInfo(); const versionInfo = await this.getVersionInfo();
const customStrategies = const customStrategies =
await this.strategyStore.getEditableStrategies(); await this.strategyStore.getEditableStrategies();
const customStrategiesInUse = const customStrategiesInUse =
@ -351,15 +352,13 @@ export default class VersionService {
return settings?.enabled || false; return settings?.enabled || false;
} }
getVersionInfo(): IVersionHolder { async getVersionInfo(): Promise<IVersionHolder> {
const instanceId = await this.getInstanceId();
return { return {
current: this.current, current: this.current,
latest: this.latest || {}, latest: this.latest || {},
isLatest: this.isLatest, isLatest: this.isLatest,
// @ts-ignore instance id can be undefined but not on the version. What should we do is still unclear. instanceId: instanceId || 'unresolved-instance-id',
instanceId: this.instanceId,
}; };
} }
} }
module.exports = VersionService;