MOBILE-4304 core: Update database usage
parent
bb82cd8ff1
commit
807860f0d5
|
@ -74,7 +74,22 @@ export const APP_SCHEMA: CoreAppSchema = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CodeRequestsQueueItem = {
|
export type CodeRequestsQueueItem = {
|
||||||
table: string;
|
table: typeof SITES_TABLE_NAME | typeof COMPONENTS_TABLE_NAME;
|
||||||
id: string;
|
id: string;
|
||||||
deferreds: CorePromisedValue<number>[];
|
deferreds: CorePromisedValue<number>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CoreLocalNotificationsSitesDBRecord = {
|
||||||
|
id: string;
|
||||||
|
code: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CoreLocalNotificationsComponentsDBRecord = {
|
||||||
|
id: string;
|
||||||
|
code: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CoreLocalNotificationsTriggeredDBRecord = {
|
||||||
|
id: number;
|
||||||
|
at: number;
|
||||||
|
};
|
||||||
|
|
|
@ -20,7 +20,6 @@ import { CoreApp } from '@services/app';
|
||||||
import { CoreConfig } from '@services/config';
|
import { CoreConfig } from '@services/config';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreTextUtils } from '@services/utils/text';
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
import { SQLiteDB } from '@classes/sqlitedb';
|
|
||||||
import { CoreQueueRunner } from '@classes/queue-runner';
|
import { CoreQueueRunner } from '@classes/queue-runner';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
|
@ -32,10 +31,16 @@ import {
|
||||||
COMPONENTS_TABLE_NAME,
|
COMPONENTS_TABLE_NAME,
|
||||||
SITES_TABLE_NAME,
|
SITES_TABLE_NAME,
|
||||||
CodeRequestsQueueItem,
|
CodeRequestsQueueItem,
|
||||||
|
CoreLocalNotificationsTriggeredDBRecord,
|
||||||
|
CoreLocalNotificationsComponentsDBRecord,
|
||||||
|
CoreLocalNotificationsSitesDBRecord,
|
||||||
} from '@services/database/local-notifications';
|
} from '@services/database/local-notifications';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { Push } from '@features/native/plugins';
|
import { Push } from '@features/native/plugins';
|
||||||
|
import { AsyncInstance, asyncInstance } from '@/core/utils/async-instance';
|
||||||
|
import { CoreDatabaseTable } from '@classes/database/database-table';
|
||||||
|
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to handle local notifications.
|
* Service to handle local notifications.
|
||||||
|
@ -56,12 +61,11 @@ export class CoreLocalNotificationsProvider {
|
||||||
protected updateSubscription?: Subscription;
|
protected updateSubscription?: Subscription;
|
||||||
protected queueRunner: CoreQueueRunner; // Queue to decrease the number of concurrent calls to the plugin (see MOBILE-3477).
|
protected queueRunner: CoreQueueRunner; // Queue to decrease the number of concurrent calls to the plugin (see MOBILE-3477).
|
||||||
|
|
||||||
// Variables for DB.
|
protected sitesTable = asyncInstance<CoreDatabaseTable<CoreLocalNotificationsSitesDBRecord, 'id', never>>();
|
||||||
protected appDB: Promise<SQLiteDB>;
|
protected componentsTable = asyncInstance<CoreDatabaseTable<CoreLocalNotificationsComponentsDBRecord, 'id', never>>();
|
||||||
protected resolveAppDB!: (appDB: SQLiteDB) => void;
|
protected triggeredTable = asyncInstance<CoreDatabaseTable<CoreLocalNotificationsTriggeredDBRecord>>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.appDB = new Promise(resolve => this.resolveAppDB = resolve);
|
|
||||||
this.logger = CoreLogger.getInstance('CoreLocalNotificationsProvider');
|
this.logger = CoreLogger.getInstance('CoreLocalNotificationsProvider');
|
||||||
this.queueRunner = new CoreQueueRunner(10);
|
this.queueRunner = new CoreQueueRunner(10);
|
||||||
}
|
}
|
||||||
|
@ -127,7 +131,36 @@ export class CoreLocalNotificationsProvider {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resolveAppDB(CoreApp.getDB());
|
const database = CoreApp.getDB();
|
||||||
|
const sitesTable = new CoreDatabaseTableProxy<CoreLocalNotificationsSitesDBRecord, 'id', never>(
|
||||||
|
{ cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
|
database,
|
||||||
|
SITES_TABLE_NAME,
|
||||||
|
['id'],
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const componentsTable = new CoreDatabaseTableProxy<CoreLocalNotificationsComponentsDBRecord, 'id', never>(
|
||||||
|
{ cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
|
database,
|
||||||
|
COMPONENTS_TABLE_NAME,
|
||||||
|
['id'],
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const triggeredTable = new CoreDatabaseTableProxy<CoreLocalNotificationsTriggeredDBRecord>(
|
||||||
|
{ cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
|
database,
|
||||||
|
TRIGGERED_TABLE_NAME,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
sitesTable.initialize(),
|
||||||
|
componentsTable.initialize(),
|
||||||
|
triggeredTable.initialize(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.sitesTable.setInstance(sitesTable);
|
||||||
|
this.componentsTable.setInstance(componentsTable);
|
||||||
|
this.triggeredTable.setInstance(triggeredTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -222,7 +255,10 @@ export class CoreLocalNotificationsProvider {
|
||||||
* @param id ID of the element to get its code.
|
* @param id ID of the element to get its code.
|
||||||
* @returns Promise resolved when the code is retrieved.
|
* @returns Promise resolved when the code is retrieved.
|
||||||
*/
|
*/
|
||||||
protected async getCode(table: string, id: string): Promise<number> {
|
protected async getCode(
|
||||||
|
table: AsyncInstance<CoreDatabaseTable<{ id: string; code: number }>>,
|
||||||
|
id: string,
|
||||||
|
): Promise<number> {
|
||||||
const key = table + '#' + id;
|
const key = table + '#' + id;
|
||||||
|
|
||||||
// Check if the code is already in memory.
|
// Check if the code is already in memory.
|
||||||
|
@ -230,25 +266,27 @@ export class CoreLocalNotificationsProvider {
|
||||||
return this.codes[key];
|
return this.codes[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = await this.appDB;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if we already have a code stored for that ID.
|
// Check if we already have a code stored for that ID.
|
||||||
const entry = await db.getRecord<{id: string; code: number}>(table, { id: id });
|
const entry = await table.getOneByPrimaryKey({ id: id });
|
||||||
|
|
||||||
this.codes[key] = entry.code;
|
this.codes[key] = entry.code;
|
||||||
|
|
||||||
return entry.code;
|
return entry.code;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// No code stored for that ID. Create a new code for it.
|
// No code stored for that ID. Create a new code for it.
|
||||||
const entries = await db.getRecords<{id: string; code: number}>(table, undefined, 'code DESC');
|
const entries = await table.getMany(undefined, {
|
||||||
|
sorting: [
|
||||||
|
{ code: 'desc' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
let newCode = 0;
|
let newCode = 0;
|
||||||
if (entries.length > 0) {
|
if (entries.length > 0) {
|
||||||
newCode = entries[0].code + 1;
|
newCode = entries[0].code + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.insertRecord(table, { id: id, code: newCode });
|
await table.insert({ id: id, code: newCode });
|
||||||
this.codes[key] = newCode;
|
this.codes[key] = newCode;
|
||||||
|
|
||||||
return newCode;
|
return newCode;
|
||||||
|
@ -347,13 +385,12 @@ export class CoreLocalNotificationsProvider {
|
||||||
* @returns Promise resolved with a boolean indicating if promise is triggered (true) or not.
|
* @returns Promise resolved with a boolean indicating if promise is triggered (true) or not.
|
||||||
*/
|
*/
|
||||||
async isTriggered(notification: ILocalNotification, useQueue: boolean = true): Promise<boolean> {
|
async isTriggered(notification: ILocalNotification, useQueue: boolean = true): Promise<boolean> {
|
||||||
const db = await this.appDB;
|
if (notification.id === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stored = await db.getRecord<{ id: number; at: number }>(
|
const stored = await this.triggeredTable.getOneByPrimaryKey({ id: notification.id });
|
||||||
TRIGGERED_TABLE_NAME,
|
|
||||||
{ id: notification.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
let triggered = (notification.trigger && notification.trigger.at) || 0;
|
let triggered = (notification.trigger && notification.trigger.at) || 0;
|
||||||
|
|
||||||
|
@ -439,7 +476,18 @@ export class CoreLocalNotificationsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the code and resolve/reject all the promises of this request.
|
// Get the code and resolve/reject all the promises of this request.
|
||||||
const code = await this.getCode(request.table, request.id);
|
const getCodeFromTable = async () => {
|
||||||
|
switch (request.table) {
|
||||||
|
case SITES_TABLE_NAME:
|
||||||
|
return this.getCode(this.sitesTable, request.id);
|
||||||
|
case COMPONENTS_TABLE_NAME:
|
||||||
|
return this.getCode(this.componentsTable, request.id);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown local-notifications table: ${request.table}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const code = await getCodeFromTable();
|
||||||
|
|
||||||
request.deferreds.forEach((p) => {
|
request.deferreds.forEach((p) => {
|
||||||
p.resolve(code);
|
p.resolve(code);
|
||||||
|
@ -506,9 +554,7 @@ export class CoreLocalNotificationsProvider {
|
||||||
* @returns Promise resolved when it is removed.
|
* @returns Promise resolved when it is removed.
|
||||||
*/
|
*/
|
||||||
async removeTriggered(id: number): Promise<void> {
|
async removeTriggered(id: number): Promise<void> {
|
||||||
const db = await this.appDB;
|
await this.triggeredTable.deleteByPrimaryKey({ id });
|
||||||
|
|
||||||
await db.deleteRecords(TRIGGERED_TABLE_NAME, { id: id });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -518,7 +564,7 @@ export class CoreLocalNotificationsProvider {
|
||||||
* @param id ID of the element to get its code.
|
* @param id ID of the element to get its code.
|
||||||
* @returns Promise resolved when the code is retrieved.
|
* @returns Promise resolved when the code is retrieved.
|
||||||
*/
|
*/
|
||||||
protected requestCode(table: string, id: string): Promise<number> {
|
protected requestCode(table: typeof SITES_TABLE_NAME | typeof COMPONENTS_TABLE_NAME, id: string): Promise<number> {
|
||||||
const deferred = new CorePromisedValue<number>();
|
const deferred = new CorePromisedValue<number>();
|
||||||
const key = table + '#' + id;
|
const key = table + '#' + id;
|
||||||
const isQueueEmpty = Object.keys(this.codeRequestsQueue).length == 0;
|
const isQueueEmpty = Object.keys(this.codeRequestsQueue).length == 0;
|
||||||
|
@ -529,8 +575,8 @@ export class CoreLocalNotificationsProvider {
|
||||||
} else {
|
} else {
|
||||||
// Add a pending request to the queue.
|
// Add a pending request to the queue.
|
||||||
this.codeRequestsQueue[key] = {
|
this.codeRequestsQueue[key] = {
|
||||||
table: table,
|
table,
|
||||||
id: id,
|
id,
|
||||||
deferreds: [deferred],
|
deferreds: [deferred],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -664,7 +710,6 @@ export class CoreLocalNotificationsProvider {
|
||||||
* @returns Promise resolved when stored, rejected otherwise.
|
* @returns Promise resolved when stored, rejected otherwise.
|
||||||
*/
|
*/
|
||||||
async trigger(notification: ILocalNotification): Promise<number> {
|
async trigger(notification: ILocalNotification): Promise<number> {
|
||||||
const db = await this.appDB;
|
|
||||||
let time = Date.now();
|
let time = Date.now();
|
||||||
if (notification.trigger?.at) {
|
if (notification.trigger?.at) {
|
||||||
// The type says "at" is a Date, but in Android we can receive timestamps instead.
|
// The type says "at" is a Date, but in Android we can receive timestamps instead.
|
||||||
|
@ -675,12 +720,10 @@ export class CoreLocalNotificationsProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = {
|
return this.triggeredTable.insert({
|
||||||
id: notification.id,
|
id: notification.id,
|
||||||
at: time,
|
at: time,
|
||||||
};
|
});
|
||||||
|
|
||||||
return db.insertRecord(TRIGGERED_TABLE_NAME, entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -691,12 +734,10 @@ export class CoreLocalNotificationsProvider {
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async updateComponentName(oldName: string, newName: string): Promise<void> {
|
async updateComponentName(oldName: string, newName: string): Promise<void> {
|
||||||
const db = await this.appDB;
|
|
||||||
|
|
||||||
const oldId = COMPONENTS_TABLE_NAME + '#' + oldName;
|
const oldId = COMPONENTS_TABLE_NAME + '#' + oldName;
|
||||||
const newId = COMPONENTS_TABLE_NAME + '#' + newName;
|
const newId = COMPONENTS_TABLE_NAME + '#' + newName;
|
||||||
|
|
||||||
await db.updateRecords(COMPONENTS_TABLE_NAME, { id: newId }, { id: oldId });
|
await this.componentsTable.update({ id: newId }, { id: oldId });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue