From d786b7d683f84e062241d3f3fbdfa2f0b42b21ac Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 19 Dec 2022 12:35:10 +0100 Subject: [PATCH] MOBILE-4081 core: Use inmemory database singletons --- .../classes/database/eager-database-table.ts | 4 +- .../database/inmemory-database-table.ts | 73 +++++++++++++++++++ .../classes/database/lazy-database-table.ts | 4 +- 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/core/classes/database/inmemory-database-table.ts diff --git a/src/core/classes/database/eager-database-table.ts b/src/core/classes/database/eager-database-table.ts index 1a03e0fda96..5db50316286 100644 --- a/src/core/classes/database/eager-database-table.ts +++ b/src/core/classes/database/eager-database-table.ts @@ -14,8 +14,8 @@ import { CoreError } from '@classes/errors/error'; import { SQLiteDBRecordValues } from '@classes/sqlitedb'; +import { CoreInMemoryDatabaseTable } from './inmemory-database-table'; import { - CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey, CoreDatabaseReducer, @@ -32,7 +32,7 @@ export class CoreEagerDatabaseTable< DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKey extends GetDBRecordPrimaryKey = GetDBRecordPrimaryKey -> extends CoreDatabaseTable { +> extends CoreInMemoryDatabaseTable { protected records: Record = {}; diff --git a/src/core/classes/database/inmemory-database-table.ts b/src/core/classes/database/inmemory-database-table.ts new file mode 100644 index 00000000000..6637f1f5416 --- /dev/null +++ b/src/core/classes/database/inmemory-database-table.ts @@ -0,0 +1,73 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CoreConstants } from '@/core/constants'; +import { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb'; +import { CoreLogger } from '@singletons/logger'; +import { CoreDatabaseTable, GetDBRecordPrimaryKey } from './database-table'; + +/** + * Database wrapper that caches database records in memory to speed up read operations. + * + * Extensions of this class should only be used as singletons, or the data integrity of the inmemory cache + * could be compromised. + */ +export abstract class CoreInMemoryDatabaseTable< + DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, + PrimaryKeyColumn extends keyof DBRecord = 'id', + PrimaryKey extends GetDBRecordPrimaryKey = GetDBRecordPrimaryKey +> extends CoreDatabaseTable { + + private static readonly ACTIVE_TABLES: WeakMap> = new WeakMap(); + private static readonly LOGGER: CoreLogger = CoreLogger.getInstance('CoreInMemoryDatabaseTable'); + + /** + * @inheritdoc + */ + async initialize(): Promise { + await super.initialize(); + + const activeTables = CoreInMemoryDatabaseTable.ACTIVE_TABLES.get(this.database) ?? new Set(); + + if (activeTables.has(this.tableName)) { + const message = `Trying to create multiple instances of an in-memory table for '${this.tableName}', ` + + 'use singletons instead.'; + + if (!CoreConstants.BUILD.isProduction) { + throw new Error(message); + } + + CoreInMemoryDatabaseTable.LOGGER.warn(message); + } + + activeTables.add(this.tableName); + CoreInMemoryDatabaseTable.ACTIVE_TABLES.set(this.database, activeTables); + } + + /** + * @inheritdoc + */ + async destroy(): Promise { + await super.destroy(); + + const activeTables = CoreInMemoryDatabaseTable.ACTIVE_TABLES.get(this.database); + + activeTables?.delete(this.tableName); + + if (activeTables?.size === 0) { + CoreInMemoryDatabaseTable.ACTIVE_TABLES.delete(this.database); + } + } + +} diff --git a/src/core/classes/database/lazy-database-table.ts b/src/core/classes/database/lazy-database-table.ts index 2e1aabcc5ff..faee315d0c5 100644 --- a/src/core/classes/database/lazy-database-table.ts +++ b/src/core/classes/database/lazy-database-table.ts @@ -14,9 +14,9 @@ import { CoreError } from '@classes/errors/error'; import { SQLiteDBRecordValues } from '@classes/sqlitedb'; +import { CoreInMemoryDatabaseTable } from './inmemory-database-table'; import { CoreDatabaseConfiguration, - CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey, CoreDatabaseQueryOptions, @@ -32,7 +32,7 @@ export class CoreLazyDatabaseTable< DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKey extends GetDBRecordPrimaryKey = GetDBRecordPrimaryKey -> extends CoreDatabaseTable { +> extends CoreInMemoryDatabaseTable { protected readonly DEFAULT_CACHE_LIFETIME = 60000;