Use minimal replacement class for MessageModel
This commit is contained in:
parent
6b00cf756e
commit
f846678b90
95 changed files with 3919 additions and 4457 deletions
139
ts/sql/Client.ts
139
ts/sql/Client.ts
|
@ -2,30 +2,34 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ipcRenderer as ipc } from 'electron';
|
||||
|
||||
import { groupBy, isTypedArray, last, map, omit } from 'lodash';
|
||||
|
||||
import type { ReadonlyDeep } from 'type-fest';
|
||||
|
||||
import { deleteExternalFiles } from '../types/Conversation';
|
||||
import { update as updateExpiringMessagesService } from '../services/expiringMessagesDeletion';
|
||||
import { tapToViewMessagesDeletionService } from '../services/tapToViewMessagesDeletionService';
|
||||
// Note: nothing imported here can come back and require Client.ts, and that includes
|
||||
// their imports too. That circularity causes problems. Anything that would do that needs
|
||||
// to be passed in, like cleanupMessages below.
|
||||
import * as Bytes from '../Bytes';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
import { deleteExternalFiles } from '../types/Conversation';
|
||||
import { createBatcher } from '../util/batcher';
|
||||
import { assertDev, softAssert } from '../util/assert';
|
||||
import { mapObjectWithSpec } from '../util/mapObjectWithSpec';
|
||||
import type { ObjectMappingSpecType } from '../util/mapObjectWithSpec';
|
||||
import { cleanDataForIpc } from './cleanDataForIpc';
|
||||
import type { AciString, ServiceIdString } from '../types/ServiceId';
|
||||
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
||||
import * as log from '../logging/log';
|
||||
import { isValidUuid, isValidUuidV7 } from '../util/isValidUuid';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
import type { StoredJob } from '../jobs/types';
|
||||
import { formatJobForInsert } from '../jobs/formatJobForInsert';
|
||||
import { cleanupMessages } from '../util/cleanup';
|
||||
import { AccessType, ipcInvoke, doShutdown, removeDB } from './channels';
|
||||
import { getMessageIdForLogging } from '../util/idForLogging';
|
||||
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
||||
import { generateSnippetAroundMention } from '../util/search';
|
||||
import { drop } from '../util/drop';
|
||||
|
||||
import type { ObjectMappingSpecType } from '../util/mapObjectWithSpec';
|
||||
import type { AciString, ServiceIdString } from '../types/ServiceId';
|
||||
import type { StoredJob } from '../jobs/types';
|
||||
import type {
|
||||
ClientInterfaceWrap,
|
||||
AdjacentMessagesByConversationOptionsType,
|
||||
|
@ -58,12 +62,8 @@ import type {
|
|||
ClientOnlyReadableInterface,
|
||||
ClientOnlyWritableInterface,
|
||||
} from './Interface';
|
||||
import { getMessageIdForLogging } from '../util/idForLogging';
|
||||
import type { MessageAttributesType } from '../model-types';
|
||||
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
||||
import { generateSnippetAroundMention } from '../util/search';
|
||||
import type { AttachmentDownloadJobType } from '../types/AttachmentDownload';
|
||||
import type { SingleProtoJobQueue } from '../jobs/singleProtoJobQueue';
|
||||
|
||||
const ERASE_SQL_KEY = 'erase-sql-key';
|
||||
const ERASE_ATTACHMENTS_KEY = 'erase-attachments';
|
||||
|
@ -121,6 +121,10 @@ const clientOnlyWritable: ClientOnlyWritableInterface = {
|
|||
removeMessage,
|
||||
removeMessages,
|
||||
|
||||
saveMessage,
|
||||
saveMessages,
|
||||
saveMessagesIndividually,
|
||||
|
||||
// Client-side only
|
||||
|
||||
flushUpdateConversationBatcher,
|
||||
|
@ -137,17 +141,12 @@ const clientOnlyWritable: ClientOnlyWritableInterface = {
|
|||
type ClientOverridesType = ClientOnlyWritableInterface &
|
||||
Pick<
|
||||
ClientInterfaceWrap<ServerWritableDirectInterface>,
|
||||
| 'saveAttachmentDownloadJob'
|
||||
| 'saveMessage'
|
||||
| 'saveMessages'
|
||||
| 'updateConversations'
|
||||
'saveAttachmentDownloadJob' | 'updateConversations'
|
||||
>;
|
||||
|
||||
const clientOnlyWritableOverrides: ClientOverridesType = {
|
||||
...clientOnlyWritable,
|
||||
saveAttachmentDownloadJob,
|
||||
saveMessage,
|
||||
saveMessages,
|
||||
updateConversations,
|
||||
};
|
||||
|
||||
|
@ -595,41 +594,76 @@ async function searchMessages({
|
|||
|
||||
async function saveMessage(
|
||||
data: ReadonlyDeep<MessageType>,
|
||||
options: {
|
||||
jobToInsert?: Readonly<StoredJob>;
|
||||
{
|
||||
forceSave,
|
||||
jobToInsert,
|
||||
ourAci,
|
||||
postSaveUpdates,
|
||||
}: {
|
||||
forceSave?: boolean;
|
||||
jobToInsert?: Readonly<StoredJob>;
|
||||
ourAci: AciString;
|
||||
postSaveUpdates: () => Promise<void>;
|
||||
}
|
||||
): Promise<string> {
|
||||
const id = await writableChannel.saveMessage(_cleanMessageData(data), {
|
||||
...options,
|
||||
jobToInsert: options.jobToInsert && formatJobForInsert(options.jobToInsert),
|
||||
forceSave,
|
||||
jobToInsert: jobToInsert && formatJobForInsert(jobToInsert),
|
||||
ourAci,
|
||||
});
|
||||
|
||||
softAssert(
|
||||
// Older messages still have `UUIDv4` so don't log errors when encountering
|
||||
// it.
|
||||
(!options.forceSave && isValidUuid(id)) || isValidUuidV7(id),
|
||||
(!forceSave && isValidUuid(id)) || isValidUuidV7(id),
|
||||
'saveMessage: messageId is not a UUID'
|
||||
);
|
||||
|
||||
void updateExpiringMessagesService();
|
||||
void tapToViewMessagesDeletionService.update();
|
||||
drop(postSaveUpdates?.());
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
async function saveMessages(
|
||||
arrayOfMessages: ReadonlyArray<ReadonlyDeep<MessageType>>,
|
||||
options: { forceSave?: boolean; ourAci: AciString }
|
||||
{
|
||||
forceSave,
|
||||
ourAci,
|
||||
postSaveUpdates,
|
||||
}: {
|
||||
forceSave?: boolean;
|
||||
ourAci: AciString;
|
||||
postSaveUpdates: () => Promise<void>;
|
||||
}
|
||||
): Promise<Array<string>> {
|
||||
const result = await writableChannel.saveMessages(
|
||||
arrayOfMessages.map(message => _cleanMessageData(message)),
|
||||
options
|
||||
{ forceSave, ourAci }
|
||||
);
|
||||
|
||||
void updateExpiringMessagesService();
|
||||
void tapToViewMessagesDeletionService.update();
|
||||
drop(postSaveUpdates?.());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function saveMessagesIndividually(
|
||||
arrayOfMessages: ReadonlyArray<ReadonlyDeep<MessageType>>,
|
||||
{
|
||||
forceSave,
|
||||
ourAci,
|
||||
postSaveUpdates,
|
||||
}: {
|
||||
forceSave?: boolean;
|
||||
ourAci: AciString;
|
||||
postSaveUpdates: () => Promise<void>;
|
||||
}
|
||||
): Promise<{ failedIndices: Array<number> }> {
|
||||
const result = await writableChannel.saveMessagesIndividually(
|
||||
arrayOfMessages,
|
||||
{ forceSave, ourAci }
|
||||
);
|
||||
|
||||
drop(postSaveUpdates?.());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -637,7 +671,10 @@ async function saveMessages(
|
|||
async function removeMessage(
|
||||
id: string,
|
||||
options: {
|
||||
singleProtoJobQueue: SingleProtoJobQueue;
|
||||
cleanupMessages: (
|
||||
messages: ReadonlyArray<MessageAttributesType>,
|
||||
options: { fromSync?: boolean }
|
||||
) => Promise<void>;
|
||||
fromSync?: boolean;
|
||||
}
|
||||
): Promise<void> {
|
||||
|
@ -647,9 +684,8 @@ async function removeMessage(
|
|||
// it needs to delete all associated on-disk files along with the database delete.
|
||||
if (message) {
|
||||
await writableChannel.removeMessage(id);
|
||||
await cleanupMessages([message], {
|
||||
...options,
|
||||
markCallHistoryDeleted: DataWriter.markCallHistoryDeleted,
|
||||
await options.cleanupMessages([message], {
|
||||
fromSync: options.fromSync,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -659,7 +695,10 @@ export async function deleteAndCleanup(
|
|||
logId: string,
|
||||
options: {
|
||||
fromSync?: boolean;
|
||||
singleProtoJobQueue: SingleProtoJobQueue;
|
||||
cleanupMessages: (
|
||||
messages: ReadonlyArray<MessageAttributesType>,
|
||||
options: { fromSync?: boolean }
|
||||
) => Promise<void>;
|
||||
}
|
||||
): Promise<void> {
|
||||
const ids = messages.map(message => message.id);
|
||||
|
@ -668,9 +707,8 @@ export async function deleteAndCleanup(
|
|||
await writableChannel.removeMessages(ids);
|
||||
|
||||
log.info(`deleteAndCleanup/${logId}: Cleanup for ${ids.length} messages...`);
|
||||
await cleanupMessages(messages, {
|
||||
...options,
|
||||
markCallHistoryDeleted: DataWriter.markCallHistoryDeleted,
|
||||
await options.cleanupMessages(messages, {
|
||||
fromSync: Boolean(options.fromSync),
|
||||
});
|
||||
|
||||
log.info(`deleteAndCleanup/${logId}: Complete`);
|
||||
|
@ -680,13 +718,15 @@ async function removeMessages(
|
|||
messageIds: ReadonlyArray<string>,
|
||||
options: {
|
||||
fromSync?: boolean;
|
||||
singleProtoJobQueue: SingleProtoJobQueue;
|
||||
cleanupMessages: (
|
||||
messages: ReadonlyArray<MessageAttributesType>,
|
||||
options: { fromSync?: boolean }
|
||||
) => Promise<void>;
|
||||
}
|
||||
): Promise<void> {
|
||||
const messages = await readableChannel.getMessagesById(messageIds);
|
||||
await cleanupMessages(messages, {
|
||||
...options,
|
||||
markCallHistoryDeleted: DataWriter.markCallHistoryDeleted,
|
||||
await options.cleanupMessages(messages, {
|
||||
fromSync: Boolean(options.fromSync),
|
||||
});
|
||||
await writableChannel.removeMessages(messageIds);
|
||||
}
|
||||
|
@ -743,15 +783,18 @@ async function getConversationRangeCenteredOnMessage(
|
|||
async function removeMessagesInConversation(
|
||||
conversationId: string,
|
||||
{
|
||||
cleanupMessages,
|
||||
fromSync,
|
||||
logId,
|
||||
receivedAt,
|
||||
singleProtoJobQueue,
|
||||
fromSync,
|
||||
}: {
|
||||
cleanupMessages: (
|
||||
messages: ReadonlyArray<MessageAttributesType>,
|
||||
options: { fromSync?: boolean | undefined }
|
||||
) => Promise<void>;
|
||||
fromSync?: boolean;
|
||||
logId: string;
|
||||
receivedAt?: number;
|
||||
singleProtoJobQueue: SingleProtoJobQueue;
|
||||
}
|
||||
): Promise<void> {
|
||||
let messages;
|
||||
|
@ -776,7 +819,7 @@ async function removeMessagesInConversation(
|
|||
}
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await deleteAndCleanup(messages, logId, { fromSync, singleProtoJobQueue });
|
||||
await deleteAndCleanup(messages, logId, { fromSync, cleanupMessages });
|
||||
} while (messages.length > 0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue