Manually manage full-text search table
This commit is contained in:
parent
245f8c665d
commit
2f90d6aca9
3 changed files with 223 additions and 84 deletions
|
@ -21,12 +21,15 @@ const ERASE_SQL_KEY = 'erase-sql-key';
|
||||||
let singleQueue = null;
|
let singleQueue = null;
|
||||||
let multipleQueue = null;
|
let multipleQueue = null;
|
||||||
|
|
||||||
|
// Note: we don't want queue timeouts, because delays here are due to in-progress sql
|
||||||
|
// operations. For example we might try to start a transaction when the prevous isn't
|
||||||
|
// done, causing that database operation to fail.
|
||||||
function makeNewSingleQueue() {
|
function makeNewSingleQueue() {
|
||||||
singleQueue = new Queue({ concurrency: 1, timeout: 1000 * 60 * 2 });
|
singleQueue = new Queue({ concurrency: 1 });
|
||||||
return singleQueue;
|
return singleQueue;
|
||||||
}
|
}
|
||||||
function makeNewMultipleQueue() {
|
function makeNewMultipleQueue() {
|
||||||
multipleQueue = new Queue({ concurrency: 10, timeout: 1000 * 60 * 2 });
|
multipleQueue = new Queue({ concurrency: 10 });
|
||||||
return multipleQueue;
|
return multipleQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,12 @@ export const ConfirmationDialog = React.memo(
|
||||||
|
|
||||||
const handleAction = React.useCallback(
|
const handleAction = React.useCallback(
|
||||||
(e: React.MouseEvent<HTMLButtonElement>) => {
|
(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
onClose();
|
|
||||||
if (e.currentTarget.dataset.action) {
|
if (e.currentTarget.dataset.action) {
|
||||||
const actionIndex = parseInt(e.currentTarget.dataset.action, 10);
|
const actionIndex = parseInt(e.currentTarget.dataset.action, 10);
|
||||||
const { action } = actions[actionIndex];
|
const { action } = actions[actionIndex];
|
||||||
action();
|
action();
|
||||||
}
|
}
|
||||||
|
onClose();
|
||||||
},
|
},
|
||||||
[onClose, actions]
|
[onClose, actions]
|
||||||
);
|
);
|
||||||
|
|
152
ts/sql/Server.ts
152
ts/sql/Server.ts
|
@ -1621,6 +1621,30 @@ async function updateToSchemaVersion22(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateToSchemaVersion23(
|
||||||
|
currentVersion: number,
|
||||||
|
instance: PromisifiedSQLDatabase
|
||||||
|
) {
|
||||||
|
if (currentVersion >= 23) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await instance.run('BEGIN TRANSACTION;');
|
||||||
|
|
||||||
|
// Remove triggers which keep full-text search up to date
|
||||||
|
await instance.run('DROP TRIGGER messages_on_insert;');
|
||||||
|
await instance.run('DROP TRIGGER messages_on_update;');
|
||||||
|
await instance.run('DROP TRIGGER messages_on_delete;');
|
||||||
|
|
||||||
|
await instance.run('PRAGMA user_version = 23;');
|
||||||
|
await instance.run('COMMIT TRANSACTION;');
|
||||||
|
console.log('updateToSchemaVersion23: success!');
|
||||||
|
} catch (error) {
|
||||||
|
await instance.run('ROLLBACK');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const SCHEMA_VERSIONS = [
|
const SCHEMA_VERSIONS = [
|
||||||
updateToSchemaVersion1,
|
updateToSchemaVersion1,
|
||||||
updateToSchemaVersion2,
|
updateToSchemaVersion2,
|
||||||
|
@ -1644,6 +1668,7 @@ const SCHEMA_VERSIONS = [
|
||||||
updateToSchemaVersion20,
|
updateToSchemaVersion20,
|
||||||
updateToSchemaVersion21,
|
updateToSchemaVersion21,
|
||||||
updateToSchemaVersion22,
|
updateToSchemaVersion22,
|
||||||
|
updateToSchemaVersion23,
|
||||||
];
|
];
|
||||||
|
|
||||||
async function updateSchema(instance: PromisifiedSQLDatabase) {
|
async function updateSchema(instance: PromisifiedSQLDatabase) {
|
||||||
|
@ -1849,6 +1874,7 @@ async function getIdentityKeyById(id: string) {
|
||||||
async function bulkAddIdentityKeys(array: Array<IdentityKeyType>) {
|
async function bulkAddIdentityKeys(array: Array<IdentityKeyType>) {
|
||||||
return bulkAdd(IDENTITY_KEYS_TABLE, array);
|
return bulkAdd(IDENTITY_KEYS_TABLE, array);
|
||||||
}
|
}
|
||||||
|
bulkAddIdentityKeys.needsSerial = true;
|
||||||
async function removeIdentityKeyById(id: string) {
|
async function removeIdentityKeyById(id: string) {
|
||||||
return removeById(IDENTITY_KEYS_TABLE, id);
|
return removeById(IDENTITY_KEYS_TABLE, id);
|
||||||
}
|
}
|
||||||
|
@ -1869,6 +1895,7 @@ async function getPreKeyById(id: number) {
|
||||||
async function bulkAddPreKeys(array: Array<PreKeyType>) {
|
async function bulkAddPreKeys(array: Array<PreKeyType>) {
|
||||||
return bulkAdd(PRE_KEYS_TABLE, array);
|
return bulkAdd(PRE_KEYS_TABLE, array);
|
||||||
}
|
}
|
||||||
|
bulkAddPreKeys.needsSerial = true;
|
||||||
async function removePreKeyById(id: number) {
|
async function removePreKeyById(id: number) {
|
||||||
return removeById(PRE_KEYS_TABLE, id);
|
return removeById(PRE_KEYS_TABLE, id);
|
||||||
}
|
}
|
||||||
|
@ -1889,6 +1916,7 @@ async function getSignedPreKeyById(id: number) {
|
||||||
async function bulkAddSignedPreKeys(array: Array<SignedPreKeyType>) {
|
async function bulkAddSignedPreKeys(array: Array<SignedPreKeyType>) {
|
||||||
return bulkAdd(SIGNED_PRE_KEYS_TABLE, array);
|
return bulkAdd(SIGNED_PRE_KEYS_TABLE, array);
|
||||||
}
|
}
|
||||||
|
bulkAddSignedPreKeys.needsSerial = true;
|
||||||
async function removeSignedPreKeyById(id: number) {
|
async function removeSignedPreKeyById(id: number) {
|
||||||
return removeById(SIGNED_PRE_KEYS_TABLE, id);
|
return removeById(SIGNED_PRE_KEYS_TABLE, id);
|
||||||
}
|
}
|
||||||
|
@ -1918,6 +1946,7 @@ async function getAllItems() {
|
||||||
async function bulkAddItems(array: Array<ItemType>) {
|
async function bulkAddItems(array: Array<ItemType>) {
|
||||||
return bulkAdd(ITEMS_TABLE, array);
|
return bulkAdd(ITEMS_TABLE, array);
|
||||||
}
|
}
|
||||||
|
bulkAddItems.needsSerial = true;
|
||||||
async function removeItemById(id: string) {
|
async function removeItemById(id: string) {
|
||||||
return removeById(ITEMS_TABLE, id);
|
return removeById(ITEMS_TABLE, id);
|
||||||
}
|
}
|
||||||
|
@ -1990,6 +2019,7 @@ async function getSessionsById(conversationId: string) {
|
||||||
async function bulkAddSessions(array: Array<SessionType>) {
|
async function bulkAddSessions(array: Array<SessionType>) {
|
||||||
return bulkAdd(SESSIONS_TABLE, array);
|
return bulkAdd(SESSIONS_TABLE, array);
|
||||||
}
|
}
|
||||||
|
bulkAddSessions.needsSerial = true;
|
||||||
async function removeSessionById(id: string) {
|
async function removeSessionById(id: string) {
|
||||||
return removeById(SESSIONS_TABLE, id);
|
return removeById(SESSIONS_TABLE, id);
|
||||||
}
|
}
|
||||||
|
@ -2043,6 +2073,7 @@ async function bulkAdd(table: string, array: Array<any>) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bulkAdd.needsSerial = true;
|
||||||
|
|
||||||
async function getById(table: string, id: string | number) {
|
async function getById(table: string, id: string | number) {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
|
@ -2452,7 +2483,10 @@ async function getMessageCount(conversationId?: string) {
|
||||||
|
|
||||||
async function saveMessage(
|
async function saveMessage(
|
||||||
data: MessageType,
|
data: MessageType,
|
||||||
{ forceSave }: { forceSave?: boolean } = {}
|
{
|
||||||
|
forceSave,
|
||||||
|
alreadyInTransaction,
|
||||||
|
}: { forceSave?: boolean; alreadyInTransaction?: boolean } = {}
|
||||||
) {
|
) {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
const {
|
const {
|
||||||
|
@ -2502,7 +2536,13 @@ async function saveMessage(
|
||||||
};
|
};
|
||||||
|
|
||||||
if (id && !forceSave) {
|
if (id && !forceSave) {
|
||||||
await db.run(
|
if (!alreadyInTransaction) {
|
||||||
|
await db.run('BEGIN TRANSACTION;');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
db.run(
|
||||||
`UPDATE messages SET
|
`UPDATE messages SET
|
||||||
id = $id,
|
id = $id,
|
||||||
json = $json,
|
json = $json,
|
||||||
|
@ -2527,7 +2567,38 @@ async function saveMessage(
|
||||||
unread = $unread
|
unread = $unread
|
||||||
WHERE id = $id;`,
|
WHERE id = $id;`,
|
||||||
payload
|
payload
|
||||||
|
),
|
||||||
|
db.run('DELETE FROM messages_fts WHERE id = $id;', {
|
||||||
|
$id: id,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (body) {
|
||||||
|
await db.run(
|
||||||
|
`INSERT INTO messages_fts(
|
||||||
|
id,
|
||||||
|
body
|
||||||
|
) VALUES (
|
||||||
|
$id,
|
||||||
|
$body
|
||||||
);
|
);
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
$id: id,
|
||||||
|
$body: body,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alreadyInTransaction) {
|
||||||
|
await db.run('COMMIT TRANSACTION;');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (!alreadyInTransaction) {
|
||||||
|
await db.run('ROLLBACK;');
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -2537,7 +2608,13 @@ async function saveMessage(
|
||||||
id: id || generateUUID(),
|
id: id || generateUUID(),
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.run(
|
if (!alreadyInTransaction) {
|
||||||
|
await db.run('BEGIN TRANSACTION;');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
db.run(
|
||||||
`INSERT INTO messages (
|
`INSERT INTO messages (
|
||||||
id,
|
id,
|
||||||
json,
|
json,
|
||||||
|
@ -2588,10 +2665,36 @@ async function saveMessage(
|
||||||
$id: toCreate.id,
|
$id: toCreate.id,
|
||||||
$json: objectToJSON(toCreate),
|
$json: objectToJSON(toCreate),
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
db.run(
|
||||||
|
`INSERT INTO messages_fts(
|
||||||
|
id,
|
||||||
|
body
|
||||||
|
) VALUES (
|
||||||
|
$id,
|
||||||
|
$body
|
||||||
);
|
);
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
$id: id,
|
||||||
|
$body: body,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!alreadyInTransaction) {
|
||||||
|
await db.run('COMMIT TRANSACTION;');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (!alreadyInTransaction) {
|
||||||
|
await db.run('ROLLBACK;');
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
return toCreate.id;
|
return toCreate.id;
|
||||||
}
|
}
|
||||||
|
saveMessage.needsSerial = true;
|
||||||
|
|
||||||
async function saveMessages(
|
async function saveMessages(
|
||||||
arrayOfMessages: Array<MessageType>,
|
arrayOfMessages: Array<MessageType>,
|
||||||
|
@ -2603,7 +2706,7 @@ async function saveMessages(
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
...map(arrayOfMessages, async message =>
|
...map(arrayOfMessages, async message =>
|
||||||
saveMessage(message, { forceSave })
|
saveMessage(message, { forceSave, alreadyInTransaction: true })
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2617,16 +2720,49 @@ saveMessages.needsSerial = true;
|
||||||
|
|
||||||
async function removeMessage(id: string) {
|
async function removeMessage(id: string) {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
await db.run('DELETE FROM messages WHERE id = $id;', { $id: id });
|
await db.run('BEGIN TRANSACTION;');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
db.run('DELETE FROM messages WHERE id = $id;', { $id: id }),
|
||||||
|
db.run('DELETE FROM messages_fts WHERE id = $id;', { $id: id }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await db.run('COMMIT TRANSACTION;');
|
||||||
|
} catch (error) {
|
||||||
|
await db.run('ROLLBACK;');
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
removeMessage.needsSerial = true;
|
||||||
|
|
||||||
async function removeMessages(ids: Array<string>) {
|
async function removeMessages(ids: Array<string>) {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
await db.run(
|
await db.run('BEGIN TRANSACTION;');
|
||||||
`DELETE FROM messages WHERE id IN ( ${ids.map(() => '?').join(', ')} );`,
|
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
db.run(
|
||||||
|
`DELETE FROM messages WHERE id IN ( ${ids
|
||||||
|
.map(() => '?')
|
||||||
|
.join(', ')} );`,
|
||||||
ids
|
ids
|
||||||
);
|
),
|
||||||
|
db.run(
|
||||||
|
`DELETE FROM messages_fts WHERE id IN ( ${ids
|
||||||
|
.map(() => '?')
|
||||||
|
.join(', ')} );`,
|
||||||
|
ids
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await db.run('COMMIT TRANSACTION;');
|
||||||
|
} catch (error) {
|
||||||
|
await db.run('ROLLBACK;');
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
removeMessages.needsSerial = true;
|
||||||
|
|
||||||
async function getMessageById(id: string) {
|
async function getMessageById(id: string) {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue