forked from EVOgeek/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