MOBILE-3977 config: Add database optimizations

main
Noel De Martin 2022-02-03 13:35:01 +01:00
parent effe53807a
commit a65919debc
5 changed files with 105 additions and 21 deletions

View File

@ -12,8 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreConstants } from '@/core/constants';
import { CorePromisedValue } from '@classes/promised-value';
import { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb';
import { CoreConfigProvider } from '@services/config';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreDatabaseReducer, CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey } from './database-table';
import { CoreEagerDatabaseTable } from './eager-database-table';
import { CoreLazyDatabaseTable } from './lazy-database-table';
@ -31,6 +34,7 @@ export class CoreDatabaseTableProxy<
protected config: CoreDatabaseConfiguration;
protected target: CorePromisedValue<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> = new CorePromisedValue();
protected environmentObserver?: CoreEventObserver;
constructor(
config: Partial<CoreDatabaseConfiguration>,
@ -47,11 +51,16 @@ export class CoreDatabaseTableProxy<
* @inheritdoc
*/
async initialize(): Promise<void> {
const target = this.createTarget();
this.environmentObserver = CoreEvents.on(CoreConfigProvider.ENVIRONMENT_UPDATED, () => this.updateTarget());
await target.initialize();
await this.updateTarget();
}
this.target.resolve(target);
/**
* @inheritdoc
*/
async destroy(): Promise<void> {
this.environmentObserver?.off();
}
/**
@ -146,13 +155,46 @@ export class CoreDatabaseTableProxy<
};
}
/**
* Get database configuration to use at runtime.
*
* @returns Database configuration.
*/
protected getRuntimeConfig(): CoreDatabaseConfiguration {
return {
...this.config,
...CoreConstants.CONFIG.databaseOptimizations,
...CoreConstants.CONFIG.databaseTableOptimizations?.[this.tableName],
};
}
/**
* Update underlying target instance.
*/
protected async updateTarget(): Promise<void> {
const oldTarget = this.target.value;
const newTarget = this.createTarget();
if (oldTarget) {
await oldTarget.destroy();
this.target.reset();
}
await newTarget.initialize();
this.target.resolve(newTarget);
}
/**
* Create proxy target.
*
* @returns Target instance.
*/
protected createTarget(): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> {
return this.createTable(this.config.cachingStrategy);
const config = this.getRuntimeConfig();
return this.createTable(config.cachingStrategy);
}
/**

View File

@ -134,6 +134,16 @@ export class CorePromisedValue<T = unknown> implements Promise<T> {
this._reject(reason);
}
/**
* Reset status and value.
*/
reset(): void {
delete this._resolvedValue;
delete this._rejectedReason;
this.initPromise();
}
/**
* Initialize the promise and the callbacks.
*/

View File

@ -145,23 +145,6 @@ export class CoreConstants {
static readonly CONFIG = { ...envJson.config } as unknown as EnvironmentConfig; // Data parsed from config.json files.
static readonly BUILD = envJson.build as unknown as EnvironmentBuild; // Build info.
/**
* Update config with the given values.
*
* @param config Config updates.
*/
static patchConfig(config: Partial<EnvironmentConfig>): void {
Object.assign(this.CONFIG, config);
}
/**
* Reset config values to its original state.
*/
static resetConfig(): void {
Object.keys(this.CONFIG).forEach(key => delete this.CONFIG[key]);
Object.assign(this.CONFIG, envJson.config);
}
}
interface EnvironmentBuild {

View File

@ -12,14 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { EnvironmentConfig } from '@/types/config';
import { Injectable } from '@angular/core';
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
import { CoreApp } from '@services/app';
import { APP_SCHEMA, ConfigDBEntry, CONFIG_TABLE_NAME } from '@services/database/config';
import { makeSingleton } from '@singletons';
import { CoreConstants } from '../constants';
import { CoreEvents } from '@singletons/events';
import { CoreDatabaseTable } from '@classes/database/database-table';
import { CorePromisedValue } from '@classes/promised-value';
declare module '@singletons/events' {
/**
* Augment CoreEventsData interface with events specific to this service.
*
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
*/
export interface CoreEventsData {
[CoreConfigProvider.ENVIRONMENT_UPDATED]: EnvironmentConfig;
}
}
/**
* Factory to provide access to dynamic and permanent config and settings.
* It should not be abused into a temporary storage.
@ -27,7 +43,10 @@ import { CorePromisedValue } from '@classes/promised-value';
@Injectable({ providedIn: 'root' })
export class CoreConfigProvider {
static readonly ENVIRONMENT_UPDATED = 'environment_updated';
protected table: CorePromisedValue<CoreDatabaseTable<ConfigDBEntry, 'name'>> = new CorePromisedValue();
protected defaultEnvironment?: EnvironmentConfig;
/**
* Initialize database.
@ -98,6 +117,33 @@ export class CoreConfigProvider {
await table.insert({ name, value });
}
/**
* Update config with the given values.
*
* @param config Config updates.
*/
patchEnvironment(config: Partial<EnvironmentConfig>): void {
this.defaultEnvironment = this.defaultEnvironment ?? CoreConstants.CONFIG;
Object.assign(CoreConstants.CONFIG, config);
CoreEvents.trigger(CoreConfigProvider.ENVIRONMENT_UPDATED, CoreConstants.CONFIG);
}
/**
* Reset config values to its original state.
*/
resetEnvironment(): void {
if (!this.defaultEnvironment) {
// The environment config hasn't been modified; there's not need to reset.
return;
}
Object.keys(CoreConstants.CONFIG).forEach(key => delete CoreConstants.CONFIG[key]);
Object.assign(CoreConstants.CONFIG, this.defaultEnvironment);
CoreEvents.trigger(CoreConfigProvider.ENVIRONMENT_UPDATED, CoreConstants.CONFIG);
}
}
export const CoreConfig = makeSingleton(CoreConfigProvider);

View File

@ -17,6 +17,7 @@ import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mai
import { CoreSitesDemoSiteData } from '@services/sites';
import { OpenFileAction } from '@services/utils/utils';
import { CoreLoginSiteSelectorListMethod } from '@features/login/services/login-helper';
import { CoreDatabaseConfiguration } from '@classes/database/database-table-proxy';
/* eslint-disable @typescript-eslint/naming-convention */
@ -31,6 +32,8 @@ export interface EnvironmentConfig {
cache_update_frequency_rarely: number;
default_lang: string;
languages: Record<string, string>;
databaseOptimizations?: Partial<CoreDatabaseConfiguration>;
databaseTableOptimizations?: Record<string, Partial<CoreDatabaseConfiguration>>;
wsservice: string;
demo_sites: Record<string, CoreSitesDemoSiteData>;
zoomlevels: Record<CoreZoomLevel, number>;