forked from CIT/Vmeda.Online
		
	MOBILE-3821 core: Configure lazy cache lifetime
This commit is contained in:
		
							parent
							
								
									37bde23418
								
							
						
					
					
						commit
						1b24f0955d
					
				@ -14,10 +14,11 @@
 | 
			
		||||
 | 
			
		||||
import { CoreConstants } from '@/core/constants';
 | 
			
		||||
import { asyncInstance } from '@/core/utils/async-instance';
 | 
			
		||||
import { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb';
 | 
			
		||||
import { SQLiteDBRecordValues } from '@classes/sqlitedb';
 | 
			
		||||
import { CoreConfig, CoreConfigProvider } from '@services/config';
 | 
			
		||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
import {
 | 
			
		||||
    CoreDatabaseConfiguration,
 | 
			
		||||
    CoreDatabaseReducer,
 | 
			
		||||
    CoreDatabaseTable,
 | 
			
		||||
    CoreDatabaseConditions,
 | 
			
		||||
@ -40,7 +41,8 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
    PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
 | 
			
		||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
 | 
			
		||||
 | 
			
		||||
    protected config: CoreDatabaseConfiguration;
 | 
			
		||||
    protected readonly DEFAULT_CACHING_STRATEGY = CoreDatabaseCachingStrategy.None;
 | 
			
		||||
 | 
			
		||||
    protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>();
 | 
			
		||||
    protected environmentObserver?: CoreEventObserver;
 | 
			
		||||
    protected targetConstructors: Record<
 | 
			
		||||
@ -52,21 +54,12 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
        [CoreDatabaseCachingStrategy.None]: CoreDatabaseTable,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        config: Partial<CoreDatabaseConfiguration>,
 | 
			
		||||
        database: SQLiteDB,
 | 
			
		||||
        tableName: string,
 | 
			
		||||
        primaryKeyColumns?: PrimaryKeyColumn[],
 | 
			
		||||
    ) {
 | 
			
		||||
        super(database, tableName, primaryKeyColumns);
 | 
			
		||||
 | 
			
		||||
        this.config = { ...this.getConfigDefaults(), ...config };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async initialize(): Promise<void> {
 | 
			
		||||
        await super.initialize();
 | 
			
		||||
 | 
			
		||||
        this.environmentObserver = CoreEvents.on(CoreConfigProvider.ENVIRONMENT_UPDATED, async () => {
 | 
			
		||||
            if (!(await this.shouldUpdateTarget())) {
 | 
			
		||||
                return;
 | 
			
		||||
@ -82,9 +75,23 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async destroy(): Promise<void> {
 | 
			
		||||
        await super.destroy();
 | 
			
		||||
 | 
			
		||||
        this.environmentObserver?.off();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    matchesConfig(config: Partial<CoreDatabaseConfiguration>): boolean {
 | 
			
		||||
        const thisDebug = this.config.debug ?? false;
 | 
			
		||||
        const thisCachingStrategy = this.config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY;
 | 
			
		||||
        const otherDebug = config.debug ?? false;
 | 
			
		||||
        const otherCachingStrategy = config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY;
 | 
			
		||||
 | 
			
		||||
        return super.matchesConfig(config) && thisDebug === otherDebug && thisCachingStrategy === otherCachingStrategy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
@ -172,24 +179,12 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
        return this.target.deleteByPrimaryKey(primaryKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get default configuration values.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns Config defaults.
 | 
			
		||||
     */
 | 
			
		||||
    protected getConfigDefaults(): CoreDatabaseConfiguration {
 | 
			
		||||
        return {
 | 
			
		||||
            cachingStrategy: CoreDatabaseCachingStrategy.None,
 | 
			
		||||
            debug: false,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get database configuration to use at runtime.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns Database configuration.
 | 
			
		||||
     */
 | 
			
		||||
    protected async getRuntimeConfig(): Promise<CoreDatabaseConfiguration> {
 | 
			
		||||
    protected async getRuntimeConfig(): Promise<Partial<CoreDatabaseConfiguration>> {
 | 
			
		||||
        await CoreConfig.ready();
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
@ -228,7 +223,8 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
        const originalTarget = target instanceof CoreDebugDatabaseTable ? target.getTarget() : target;
 | 
			
		||||
 | 
			
		||||
        return (config.debug && target === originalTarget)
 | 
			
		||||
            || originalTarget?.constructor !== this.targetConstructors[config.cachingStrategy];
 | 
			
		||||
            || originalTarget?.constructor !== this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY]
 | 
			
		||||
            || !originalTarget.matchesConfig(config);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -238,7 +234,7 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
     */
 | 
			
		||||
    protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> {
 | 
			
		||||
        const config = await this.getRuntimeConfig();
 | 
			
		||||
        const table = this.createTable(config.cachingStrategy);
 | 
			
		||||
        const table = this.createTable(config);
 | 
			
		||||
 | 
			
		||||
        return config.debug ? new CoreDebugDatabaseTable(table) : table;
 | 
			
		||||
    }
 | 
			
		||||
@ -246,23 +242,29 @@ export class CoreDatabaseTableProxy<
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a database table using the given caching strategy.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cachingStrategy Caching strategy.
 | 
			
		||||
     * @param config Database configuration.
 | 
			
		||||
     * @returns Database table.
 | 
			
		||||
     */
 | 
			
		||||
    protected createTable(cachingStrategy: CoreDatabaseCachingStrategy): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> {
 | 
			
		||||
        const DatabaseTable = this.targetConstructors[cachingStrategy];
 | 
			
		||||
    protected createTable(config: Partial<CoreDatabaseConfiguration>): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> {
 | 
			
		||||
        const DatabaseTable = this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY];
 | 
			
		||||
 | 
			
		||||
        return new DatabaseTable(this.database, this.tableName, this.primaryKeyColumns);
 | 
			
		||||
        return new DatabaseTable(config, this.database, this.tableName, this.primaryKeyColumns);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Database proxy configuration.
 | 
			
		||||
 */
 | 
			
		||||
export interface CoreDatabaseConfiguration {
 | 
			
		||||
    cachingStrategy: CoreDatabaseCachingStrategy;
 | 
			
		||||
    debug: boolean;
 | 
			
		||||
declare module '@classes/database/database-table' {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Augment CoreDatabaseConfiguration interface with data specific to this class.
 | 
			
		||||
     *
 | 
			
		||||
     * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
 | 
			
		||||
     */
 | 
			
		||||
    export interface CoreDatabaseConfiguration {
 | 
			
		||||
        cachingStrategy: CoreDatabaseCachingStrategy;
 | 
			
		||||
        debug: boolean;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -24,16 +24,30 @@ export class CoreDatabaseTable<
 | 
			
		||||
    PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
 | 
			
		||||
> {
 | 
			
		||||
 | 
			
		||||
    protected config: Partial<CoreDatabaseConfiguration>;
 | 
			
		||||
    protected database: SQLiteDB;
 | 
			
		||||
    protected tableName: string;
 | 
			
		||||
    protected primaryKeyColumns: PrimaryKeyColumn[];
 | 
			
		||||
 | 
			
		||||
    constructor(database: SQLiteDB, tableName: string, primaryKeyColumns?: PrimaryKeyColumn[]) {
 | 
			
		||||
    constructor(
 | 
			
		||||
        config: Partial<CoreDatabaseConfiguration>,
 | 
			
		||||
        database: SQLiteDB,
 | 
			
		||||
        tableName: string,
 | 
			
		||||
        primaryKeyColumns?: PrimaryKeyColumn[],
 | 
			
		||||
    ) {
 | 
			
		||||
        this.config = config;
 | 
			
		||||
        this.database = database;
 | 
			
		||||
        this.tableName = tableName;
 | 
			
		||||
        this.primaryKeyColumns = primaryKeyColumns ?? ['id'] as PrimaryKeyColumn[];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get database configuration.
 | 
			
		||||
     */
 | 
			
		||||
    getConfig(): Partial<CoreDatabaseConfiguration> {
 | 
			
		||||
        return this.config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get database connection.
 | 
			
		||||
     *
 | 
			
		||||
@ -75,6 +89,17 @@ export class CoreDatabaseTable<
 | 
			
		||||
        // Nothing to destroy by default, override this method if necessary.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check whether the table matches the given configuration for the values that concern it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param config Database config.
 | 
			
		||||
     * @returns Whether the table matches the given configuration.
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    matchesConfig(config: Partial<CoreDatabaseConfiguration>): boolean {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get records matching the given conditions.
 | 
			
		||||
     *
 | 
			
		||||
@ -336,6 +361,13 @@ export class CoreDatabaseTable<
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Database configuration.
 | 
			
		||||
 */
 | 
			
		||||
export interface CoreDatabaseConfiguration {
 | 
			
		||||
    // This definition is augmented in subclasses.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CoreDatabaseTable constructor.
 | 
			
		||||
 */
 | 
			
		||||
@ -346,6 +378,7 @@ export type CoreDatabaseTableConstructor<
 | 
			
		||||
> = {
 | 
			
		||||
 | 
			
		||||
    new (
 | 
			
		||||
        config: Partial<CoreDatabaseConfiguration>,
 | 
			
		||||
        database: SQLiteDB,
 | 
			
		||||
        tableName: string,
 | 
			
		||||
        primaryKeyColumns?: PrimaryKeyColumn[]
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ export class CoreDebugDatabaseTable<
 | 
			
		||||
    protected logger: CoreLogger;
 | 
			
		||||
 | 
			
		||||
    constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>) {
 | 
			
		||||
        super(target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
 | 
			
		||||
        super(target.getConfig(), target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
 | 
			
		||||
 | 
			
		||||
        this.target = target;
 | 
			
		||||
        this.logger = CoreLogger.getInstance(`CoreDatabase[${this.tableName}]`);
 | 
			
		||||
@ -53,7 +53,9 @@ export class CoreDebugDatabaseTable<
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    initialize(): Promise<void> {
 | 
			
		||||
    async initialize(): Promise<void> {
 | 
			
		||||
        await super.initialize();
 | 
			
		||||
 | 
			
		||||
        this.logger.log('initialize', this.target);
 | 
			
		||||
 | 
			
		||||
        return this.target.initialize();
 | 
			
		||||
@ -62,7 +64,9 @@ export class CoreDebugDatabaseTable<
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    destroy(): Promise<void> {
 | 
			
		||||
    async destroy(): Promise<void> {
 | 
			
		||||
        await super.destroy();
 | 
			
		||||
 | 
			
		||||
        this.logger.log('destroy');
 | 
			
		||||
 | 
			
		||||
        return this.target.destroy();
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,8 @@ export class CoreEagerDatabaseTable<
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async initialize(): Promise<void> {
 | 
			
		||||
        await super.initialize();
 | 
			
		||||
 | 
			
		||||
        const records = await super.getMany();
 | 
			
		||||
 | 
			
		||||
        this.records = records.reduce((data, record) => {
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,13 @@
 | 
			
		||||
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { SQLiteDBRecordValues } from '@classes/sqlitedb';
 | 
			
		||||
import { CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey, CoreDatabaseQueryOptions } from './database-table';
 | 
			
		||||
import {
 | 
			
		||||
    CoreDatabaseConfiguration,
 | 
			
		||||
    CoreDatabaseTable,
 | 
			
		||||
    CoreDatabaseConditions,
 | 
			
		||||
    GetDBRecordPrimaryKey,
 | 
			
		||||
    CoreDatabaseQueryOptions,
 | 
			
		||||
} from './database-table';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Wrapper used to improve performance by caching records that are used often for faster read operations.
 | 
			
		||||
@ -28,7 +34,38 @@ export class CoreLazyDatabaseTable<
 | 
			
		||||
    PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
 | 
			
		||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
 | 
			
		||||
 | 
			
		||||
    protected readonly DEFAULT_CACHE_LIFETIME = 60000;
 | 
			
		||||
 | 
			
		||||
    protected records: Record<string, DBRecord | null> = {};
 | 
			
		||||
    protected interval?: number;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async initialize(): Promise<void> {
 | 
			
		||||
        await super.initialize();
 | 
			
		||||
 | 
			
		||||
        this.interval = window.setInterval(() => (this.records = {}), this.config.lazyCacheLifetime ?? this.DEFAULT_CACHE_LIFETIME);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async destroy(): Promise<void> {
 | 
			
		||||
        await super.destroy();
 | 
			
		||||
 | 
			
		||||
        this.interval && window.clearInterval(this.interval);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    matchesConfig(config: Partial<CoreDatabaseConfiguration>): boolean {
 | 
			
		||||
        const thisCacheLifetime = this.config.lazyCacheLifetime ?? this.DEFAULT_CACHE_LIFETIME;
 | 
			
		||||
        const otherCacheLifetime = config.lazyCacheLifetime ?? this.DEFAULT_CACHE_LIFETIME;
 | 
			
		||||
 | 
			
		||||
        return super.matchesConfig(config) && thisCacheLifetime === otherCacheLifetime;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
@ -152,3 +189,16 @@ export class CoreLazyDatabaseTable<
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module '@classes/database/database-table' {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Augment CoreDatabaseConfiguration interface with data specific to this table.
 | 
			
		||||
     *
 | 
			
		||||
     * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
 | 
			
		||||
     */
 | 
			
		||||
    export interface CoreDatabaseConfiguration {
 | 
			
		||||
        lazyCacheLifetime: number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,12 +13,8 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { mock, mockSingleton } from '@/testing/utils';
 | 
			
		||||
import { CoreDatabaseSorting, CoreDatabaseTable } from '@classes/database/database-table';
 | 
			
		||||
import {
 | 
			
		||||
    CoreDatabaseCachingStrategy,
 | 
			
		||||
    CoreDatabaseConfiguration,
 | 
			
		||||
    CoreDatabaseTableProxy,
 | 
			
		||||
} from '@classes/database/database-table-proxy';
 | 
			
		||||
import { CoreDatabaseConfiguration, CoreDatabaseSorting, CoreDatabaseTable } from '@classes/database/database-table';
 | 
			
		||||
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
 | 
			
		||||
import { SQLiteDB } from '@classes/sqlitedb';
 | 
			
		||||
import { CoreConfig } from '@services/config';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -56,12 +56,8 @@ import { CoreAjaxError } from '@classes/errors/ajaxerror';
 | 
			
		||||
import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
 | 
			
		||||
import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CorePromisedValue } from '@classes/promised-value';
 | 
			
		||||
import { CoreDatabaseTable } from '@classes/database/database-table';
 | 
			
		||||
import {
 | 
			
		||||
    CoreDatabaseCachingStrategy,
 | 
			
		||||
    CoreDatabaseConfiguration,
 | 
			
		||||
    CoreDatabaseTableProxy,
 | 
			
		||||
} from '@classes/database/database-table-proxy';
 | 
			
		||||
import { CoreDatabaseConfiguration, CoreDatabaseTable } from '@classes/database/database-table';
 | 
			
		||||
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
 | 
			
		||||
import { asyncInstance, AsyncInstance } from '../utils/async-instance';
 | 
			
		||||
import { CoreConfig } from './config';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								src/types/config.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/types/config.d.ts
									
									
									
									
										vendored
									
									
								
							@ -17,7 +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';
 | 
			
		||||
import { CoreDatabaseConfiguration } from '@classes/database/database-table';
 | 
			
		||||
 | 
			
		||||
/* eslint-disable @typescript-eslint/naming-convention */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user