mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-07 05:52:57 +00:00
@@ -67,7 +67,8 @@ describe('ConfigProvider', () => {
|
|||||||
|
|
||||||
it('should fetch app configuration', async () => {
|
it('should fetch app configuration', async () => {
|
||||||
spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse));
|
spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse));
|
||||||
const result = await configProvider.fetch();
|
await configProvider.fetch();
|
||||||
|
const result = configProvider.config;
|
||||||
expect(result).toEqual(sampleIndexResponse);
|
expect(result).toEqual(sampleIndexResponse);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ describe('ConfigProvider', () => {
|
|||||||
expect(storageProviderSpy.has).toHaveBeenCalled();
|
expect(storageProviderSpy.has).toHaveBeenCalled();
|
||||||
expect(storageProviderSpy.get).toHaveBeenCalledTimes(0);
|
expect(storageProviderSpy.get).toHaveBeenCalledTimes(0);
|
||||||
expect(configProvider.client.handshake).toHaveBeenCalled();
|
expect(configProvider.client.handshake).toHaveBeenCalled();
|
||||||
expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name);
|
expect(configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error on failed initialisation', async () => {
|
it('should throw error on failed initialisation', async () => {
|
||||||
@@ -192,4 +193,31 @@ describe('ConfigProvider', () => {
|
|||||||
|
|
||||||
expect(configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name);
|
expect(configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fetch new config from remote on init', async () => {
|
||||||
|
storageProviderSpy.has.and.returnValue(Promise.resolve(true));
|
||||||
|
storageProviderSpy.get.and.returnValue(Promise.resolve(sampleIndexResponse));
|
||||||
|
spyOn(configProvider, 'fetch');
|
||||||
|
await configProvider.init();
|
||||||
|
|
||||||
|
expect(configProvider.fetch).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the local config with the one from remote', async () => {
|
||||||
|
storageProviderSpy.has.and.returnValue(Promise.resolve(true));
|
||||||
|
storageProviderSpy.get.and.returnValue(Promise.resolve(sampleIndexResponse));
|
||||||
|
const newConfig = structuredClone(sampleIndexResponse);
|
||||||
|
newConfig.app.name = 'New app name';
|
||||||
|
spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(newConfig));
|
||||||
|
await configProvider.init();
|
||||||
|
|
||||||
|
// Validate that the initial configuration is loaded
|
||||||
|
expect(configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name);
|
||||||
|
|
||||||
|
// Fetch the new configuration from the remote
|
||||||
|
await configProvider.fetch();
|
||||||
|
|
||||||
|
// Validate that the new configuration is now set
|
||||||
|
expect(configProvider.getValue('name')).toEqual(newConfig.app.name);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -83,17 +83,20 @@ export class ConfigProvider {
|
|||||||
/**
|
/**
|
||||||
* Fetches configuration from backend
|
* Fetches configuration from backend
|
||||||
*/
|
*/
|
||||||
async fetch(): Promise<SCIndexResponse> {
|
async fetch(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const isOffline = await firstValueFrom(this.internetConnectionService.offline$);
|
const isOffline = await firstValueFrom(this.internetConnectionService.offline$);
|
||||||
if (isOffline) {
|
if (isOffline) {
|
||||||
throw new Error('Device is offline.');
|
throw new Error('Device is offline.');
|
||||||
} else {
|
} else {
|
||||||
return await this.client.handshake(this.scVersion);
|
const fetchedConfig: SCIndexResponse = await this.client.handshake(this.scVersion);
|
||||||
|
await this.set(fetchedConfig);
|
||||||
|
this.logger.log(`Configuration updated from remote`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const error_ = error instanceof Error ? new ConfigFetchError(error.message) : new ConfigFetchError();
|
const error_ = error instanceof Error ? new ConfigFetchError(error.message) : new ConfigFetchError();
|
||||||
throw error_;
|
this.logger.warn(`Failed to fetch remote configuration:`, error_);
|
||||||
|
throw error_; // Rethrow the error to handle it in init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,40 +124,33 @@ export class ConfigProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises the ConfigProvider
|
* Initialises the ConfigProvider
|
||||||
* @throws ConfigInitError if no configuration could be loaded.
|
* @throws ConfigInitError if no configuration could be loaded both locally and remote.
|
||||||
* @throws WrongConfigVersionInStorage if fetch failed and saved config has wrong SCVersion
|
|
||||||
*/
|
*/
|
||||||
async init(): Promise<void> {
|
async init(): Promise<void> {
|
||||||
let loadError;
|
|
||||||
let fetchError;
|
|
||||||
// load saved configuration
|
|
||||||
try {
|
try {
|
||||||
|
// Attempt to load the configuration from local storage
|
||||||
this.config = await this.loadLocal();
|
this.config = await this.loadLocal();
|
||||||
this.firstSession = false;
|
this.firstSession = false;
|
||||||
this.logger.log(`initialised configuration from storage`);
|
this.logger.log(`initialised configuration from storage`);
|
||||||
|
|
||||||
|
// Check if the stored configuration has the correct version
|
||||||
if (this.config.backend.SCVersion.split('.')[0] !== this.scVersion.split('.')[0]) {
|
if (this.config.backend.SCVersion.split('.')[0] !== this.scVersion.split('.')[0]) {
|
||||||
loadError = new WrongConfigVersionInStorage(this.scVersion, this.config.backend.SCVersion);
|
throw new WrongConfigVersionInStorage(this.scVersion, this.config.backend.SCVersion);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
loadError = error;
|
// Fetch the remote configuration in a non-blocking manner
|
||||||
}
|
void this.fetch();
|
||||||
// fetch remote configuration from backend
|
} catch (loadError) {
|
||||||
try {
|
|
||||||
const fetchedConfig: SCIndexResponse = await this.fetch();
|
|
||||||
await this.set(fetchedConfig);
|
|
||||||
this.logger.log(`initialised configuration from remote`);
|
|
||||||
} catch (error) {
|
|
||||||
fetchError = error;
|
|
||||||
}
|
|
||||||
// check for occurred errors and throw them
|
|
||||||
if (loadError !== undefined && fetchError !== undefined) {
|
|
||||||
throw new ConfigInitError();
|
|
||||||
}
|
|
||||||
if (loadError !== undefined) {
|
|
||||||
this.logger.warn(loadError);
|
this.logger.warn(loadError);
|
||||||
}
|
|
||||||
if (fetchError !== undefined) {
|
try {
|
||||||
this.logger.warn(fetchError);
|
// If local loading fails, immediately try to fetch the configuration from remote
|
||||||
|
await this.fetch();
|
||||||
|
} catch (fetchError) {
|
||||||
|
this.logger.warn(`Failed to fetch remote configuration:`, fetchError);
|
||||||
|
// If both local loading and remote fetching fail, throw ConfigInitError
|
||||||
|
throw new ConfigInitError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user