From 84307d6f70cf07e3f661dc9257961ce070b0a9c2 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 10 Feb 2022 15:57:02 +0100 Subject: [PATCH] MOBILE-3981 pushnotifications: Optimize tables --- .../services/pushnotifications.ts | 95 +++++++++++-------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/src/core/features/pushnotifications/services/pushnotifications.ts b/src/core/features/pushnotifications/services/pushnotifications.ts index a4aadf0a7..be515b7c9 100644 --- a/src/core/features/pushnotifications/services/pushnotifications.ts +++ b/src/core/features/pushnotifications/services/pushnotifications.ts @@ -24,7 +24,6 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; import { CoreConfig } from '@services/config'; import { CoreConstants } from '@/core/constants'; -import { SQLiteDB } from '@classes/sqlitedb'; import { CoreSite, CoreSiteInfo } from '@classes/site'; import { makeSingleton, Badge, Push, Device, Translate, Platform, ApplicationInit, NgZone } from '@singletons'; import { CoreLogger } from '@singletons/logger'; @@ -42,6 +41,11 @@ import { CoreError } from '@classes/errors/error'; import { CoreWSExternalWarning } from '@services/ws'; import { CoreSitesFactory } from '@services/sites-factory'; import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu'; +import { AsyncInstance, asyncInstance } from '@/core/utils/async-instance'; +import { CoreDatabaseTable } from '@classes/database/database-table'; +import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy'; +import { CoreObject } from '@singletons/object'; +import { lazyMap, LazyMap } from '@/core/utils/lazy-map'; /** * Service to handle push notifications. @@ -53,14 +57,27 @@ export class CorePushNotificationsProvider { protected logger: CoreLogger; protected pushID?: string; + protected badgesTable = asyncInstance>(); + protected pendingUnregistersTable = + asyncInstance>(); - // Variables for DB. - protected appDB: Promise; - protected resolveAppDB!: (appDB: SQLiteDB) => void; + protected registeredDevicesTables: + LazyMap>>; constructor() { - this.appDB = new Promise(resolve => this.resolveAppDB = resolve); this.logger = CoreLogger.getInstance('CorePushNotificationsProvider'); + this.registeredDevicesTables = lazyMap( + siteId => asyncInstance( + () => CoreSites.getSiteTable( + REGISTERED_DEVICES_TABLE_NAME, + { + siteId, + config: { cachingStrategy: CoreDatabaseCachingStrategy.None }, + primaryKeyColumns: ['appid', 'uuid'], + }, + ), + ), + ); } /** @@ -157,7 +174,27 @@ export class CorePushNotificationsProvider { // Ignore errors. } - this.resolveAppDB(CoreApp.getDB()); + const database = CoreApp.getDB(); + const badgesTable = new CoreDatabaseTableProxy( + { cachingStrategy: CoreDatabaseCachingStrategy.Eager }, + database, + BADGE_TABLE_NAME, + ['siteid', 'addon'], + ); + const pendingUnregistersTable = new CoreDatabaseTableProxy( + { cachingStrategy: CoreDatabaseCachingStrategy.Eager }, + database, + PENDING_UNREGISTER_TABLE_NAME, + ['siteid'], + ); + + await Promise.all([ + badgesTable.initialize(), + pendingUnregistersTable.initialize(), + ]); + + this.badgesTable.setInstance(badgesTable); + this.pendingUnregistersTable.setInstance(pendingUnregistersTable); } /** @@ -177,8 +214,7 @@ export class CorePushNotificationsProvider { */ async cleanSiteCounters(siteId: string): Promise { try { - const db = await this.appDB; - await db.deleteRecords(BADGE_TABLE_NAME, { siteid: siteId } ); + await this.badgesTable.delete({ siteid: siteId }); } finally { this.updateAppCounter(); } @@ -514,7 +550,6 @@ export class CorePushNotificationsProvider { this.logger.debug(`Unregister device on Moodle: '${site.getId()}'`); - const db = await this.appDB; const data: CoreUserRemoveUserDeviceWSParams = { appid: CoreConstants.CONFIG.app_id, uuid: Device.uuid, @@ -526,7 +561,7 @@ export class CorePushNotificationsProvider { } catch (error) { if (CoreUtils.isWebServiceError(error) || CoreUtils.isExpiredTokenError(error)) { // Cannot unregister. Don't try again. - await CoreUtils.ignoreErrors(db.deleteRecords(PENDING_UNREGISTER_TABLE_NAME, { + await CoreUtils.ignoreErrors(this.pendingUnregistersTable.delete({ token: site.getToken(), siteid: site.getId(), })); @@ -535,13 +570,12 @@ export class CorePushNotificationsProvider { } // Store the pending unregister so it's retried again later. - const entry: CorePushNotificationsPendingUnregisterDBRecord = { + await this.pendingUnregistersTable.insert({ siteid: site.getId(), siteurl: site.getURL(), token: site.getToken(), info: JSON.stringify(site.getInfo()), - }; - await db.insertRecord(PENDING_UNREGISTER_TABLE_NAME, entry); + }); return; } @@ -552,9 +586,9 @@ export class CorePushNotificationsProvider { await CoreUtils.ignoreErrors(Promise.all([ // Remove the device from the local DB. - site.getDb().deleteRecords(REGISTERED_DEVICES_TABLE_NAME, this.getRegisterData()), + this.registeredDevicesTables[site.getId()].delete(this.getRegisterData()), // Remove pending unregisters for this site. - db.deleteRecords(PENDING_UNREGISTER_TABLE_NAME, { siteid: site.getId() }), + this.pendingUnregistersTable.deleteByPrimaryKey({ siteid: site.getId() }), ])); } @@ -714,15 +748,14 @@ export class CorePushNotificationsProvider { // Insert the device in the local DB. try { - await site.getDb().insertRecord(REGISTERED_DEVICES_TABLE_NAME, data); + await this.registeredDevicesTables[site.getId()].insert(data); } catch (err) { // Ignore errors. } } } finally { // Remove pending unregisters for this site. - const db = await this.appDB; - await CoreUtils.ignoreErrors(db.deleteRecords(PENDING_UNREGISTER_TABLE_NAME, { siteid: site.getId() })); + await CoreUtils.ignoreErrors(this.pendingUnregistersTable.deleteByPrimaryKey({ siteid: site.getId() })); } } @@ -735,8 +768,7 @@ export class CorePushNotificationsProvider { */ protected async getAddonBadge(siteId?: string, addon: string = 'site'): Promise { try { - const db = await this.appDB; - const entry = await db.getRecord(BADGE_TABLE_NAME, { siteid: siteId, addon }); + const entry = await this.badgesTable.getOne({ siteid: siteId, addon }); return entry?.number || 0; } catch (err) { @@ -751,19 +783,7 @@ export class CorePushNotificationsProvider { * @return Promise resolved when done. */ async retryUnregisters(siteId?: string): Promise { - - const db = await this.appDB; - let results: CorePushNotificationsPendingUnregisterDBRecord[]; - - if (siteId) { - // Check if the site has a pending unregister. - results = await db.getRecords(PENDING_UNREGISTER_TABLE_NAME, { - siteid: siteId, - }); - } else { - // Get all pending unregisters. - results = await db.getAllRecords(PENDING_UNREGISTER_TABLE_NAME); - } + const results = await this.pendingUnregistersTable.getMany(CoreObject.withoutEmpty({ siteid: siteId })); await Promise.all(results.map(async (result) => { // Create a temporary site to unregister. @@ -789,14 +809,11 @@ export class CorePushNotificationsProvider { protected async saveAddonBadge(value: number, siteId?: string, addon: string = 'site'): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); - const entry: CorePushNotificationsBadgeDBRecord = { + await this.badgesTable.insert({ siteid: siteId, addon, number: value, // eslint-disable-line id-blacklist - }; - - const db = await this.appDB; - await db.insertRecord(BADGE_TABLE_NAME, entry); + }); return value; } @@ -815,7 +832,7 @@ export class CorePushNotificationsProvider { // Check if the device is already registered. const records = await CoreUtils.ignoreErrors( - site.getDb().getRecords(REGISTERED_DEVICES_TABLE_NAME, { + this.registeredDevicesTables[site.getId()].getMany({ appid: data.appid, uuid: data.uuid, name: data.name,