Page MenuHomePhabricator

D11539.id38852.diff
No OneTemporary

D11539.id38852.diff

diff --git a/keyserver/src/responders/redux-state-responders.js b/keyserver/src/responders/redux-state-responders.js
--- a/keyserver/src/responders/redux-state-responders.js
+++ b/keyserver/src/responders/redux-state-responders.js
@@ -69,6 +69,7 @@
const excludedDataValidator: TInterface<ExcludedData> = tShape<ExcludedData>({
userStore: t.maybe(t.Bool),
+ messageStore: t.maybe(t.Bool),
threadStore: t.maybe(t.Bool),
});
@@ -220,6 +221,17 @@
);
return freshStore;
})();
+ const finalMessageStorePromise: Promise<MessageStore> = (async () => {
+ if (excludedData.messageStore && useDatabase) {
+ return {
+ messages: {},
+ threads: {},
+ local: {},
+ currentAsOf: {},
+ };
+ }
+ return await messageStorePromise;
+ })();
const entryStorePromise = (async () => {
const [{ rawEntryInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
entryInfoPromise,
@@ -376,7 +388,7 @@
entryStore: entryStorePromise,
threadStore: threadStorePromise,
userInfos: finalUserInfosPromise,
- messageStore: messageStorePromise,
+ messageStore: finalMessageStorePromise,
pushApiPublicKey: pushApiPublicKeyPromise,
inviteLinksStore: inviteLinksStorePromise,
keyserverInfo: keyserverInfoPromise,
diff --git a/web/redux/initial-state-gate.js b/web/redux/initial-state-gate.js
--- a/web/redux/initial-state-gate.js
+++ b/web/redux/initial-state-gate.js
@@ -5,6 +5,7 @@
import type { Persistor } from 'redux-persist/es/types';
import { setClientDBStoreActionType } from 'lib/actions/client-db-store-actions.js';
+import type { MessageStoreOperation } from 'lib/ops/message-store-ops.js';
import type { ThreadStoreOperation } from 'lib/ops/thread-store-ops.js';
import type { UserStoreOperation } from 'lib/ops/user-store-ops.js';
import { allUpdatesCurrentAsOfSelector } from 'lib/selectors/keyserver-selectors.js';
@@ -77,6 +78,7 @@
urlInfo,
excludedData: {
threadStore: !!clientDBStore.threadStore,
+ messageStore: !!clientDBStore.messages,
userStore: !!clientDBStore.users,
},
allUpdatesCurrentAsOf,
@@ -126,15 +128,35 @@
}));
}
+ let messageStoreOperations: MessageStoreOperation[] = [];
+ if (clientDBStore.messages) {
+ const { messageStore, ...rest } = initialReduxState;
+ initialReduxState = rest;
+ } else {
+ const { messages, threads } = payload.messageStore;
+
+ messageStoreOperations = [
+ ...entries(messages).map(([id, messageInfo]) => ({
+ type: 'replace',
+ payload: { id, messageInfo },
+ })),
+ {
+ type: 'replace_threads',
+ payload: { threads },
+ },
+ ];
+ }
+
if (
threadStoreOperations.length > 0 ||
- userStoreOperations.length > 0
+ userStoreOperations.length > 0 ||
+ messageStoreOperations.length > 0
) {
await processDBStoreOperations(
{
threadStoreOperations,
draftStoreOperations: [],
- messageStoreOperations: [],
+ messageStoreOperations,
reportStoreOperations: [],
userStoreOperations,
keyserverStoreOperations: [],
diff --git a/web/redux/persist.js b/web/redux/persist.js
--- a/web/redux/persist.js
+++ b/web/redux/persist.js
@@ -15,6 +15,7 @@
type StorageMigrationFunction,
} from 'lib/shared/create-async-migrate.js';
import { keyserverStoreTransform } from 'lib/shared/transforms/keyserver-store-transform.js';
+import { messageStoreMessagesBlocklistTransform } from 'lib/shared/transforms/message-store-transform.js';
import { defaultCalendarQuery } from 'lib/types/entry-types.js';
import type { KeyserverInfo } from 'lib/types/keyserver-types.js';
import { cookieTypes } from 'lib/types/session-types.js';
@@ -51,6 +52,7 @@
'keyserverStore',
'globalThemeInfo',
'customServer',
+ 'messageStore',
];
function handleReduxMigrationFailure(oldState: AppState): AppState {
@@ -416,7 +418,7 @@
migrateStorageToSQLite,
): any),
version: 14,
- transforms: [keyserverStoreTransform],
+ transforms: [messageStoreMessagesBlocklistTransform, keyserverStoreTransform],
};
export { persistConfig };
diff --git a/web/shared-worker/types/entities.js b/web/shared-worker/types/entities.js
--- a/web/shared-worker/types/entities.js
+++ b/web/shared-worker/types/entities.js
@@ -1,7 +1,10 @@
// @flow
+import type { ClientDBMessageInfo } from 'lib/types/message-types.js';
import type { ClientDBThreadInfo } from 'lib/types/thread-types.js';
+import type { Media, WebMessage } from './sqlite-query-executor.js';
+
export type Nullable<T> = {
+value: T,
+isNull: boolean,
@@ -43,6 +46,19 @@
};
}
+function createNullableInt(value: ?string): NullableInt {
+ if (value === null || value === undefined) {
+ return {
+ value: 0,
+ isNull: true,
+ };
+ }
+ return {
+ value: Number(value),
+ isNull: false,
+ };
+}
+
function clientDBThreadInfoToWebThread(
info: ClientDBThreadInfo,
): WebClientDBThreadInfo {
@@ -99,4 +115,67 @@
return result;
}
-export { clientDBThreadInfoToWebThread, webThreadToClientDBThreadInfo };
+function clientDBMessageInfoToWebMessage(messageInfo: ClientDBMessageInfo): {
+ +message: WebMessage,
+ +medias: $ReadOnlyArray<Media>,
+} {
+ return {
+ message: {
+ id: messageInfo.id,
+ localID: createNullableString(messageInfo.local_id),
+ thread: messageInfo.thread,
+ user: messageInfo.user,
+ type: Number(messageInfo.type),
+ futureType: createNullableInt(messageInfo.future_type),
+ content: createNullableString(messageInfo.content),
+ time: messageInfo.time,
+ },
+ medias: (messageInfo.media_infos ?? []).map(
+ ({ id, uri, type, extras }) => ({
+ id,
+ uri,
+ type,
+ extras,
+ thread: messageInfo.thread,
+ container: messageInfo.id,
+ }),
+ ),
+ };
+}
+
+function webMessageToClientDBMessageInfo({
+ message,
+ medias,
+}: {
+ +message: WebMessage,
+ +medias: $ReadOnlyArray<Media>,
+}): ClientDBMessageInfo {
+ return {
+ id: message.id,
+ local_id: message.localID.isNull ? null : message.localID.value,
+ thread: message.thread,
+ user: message.user,
+ type: message.type.toString(),
+ future_type: message.futureType.isNull
+ ? null
+ : message.futureType.value.toString(),
+ content: message.content.isNull ? null : message.content.value,
+ time: message.time,
+ media_infos:
+ medias?.length === 0
+ ? null
+ : medias?.map(({ id, uri, type, extras }) => ({
+ id,
+ uri,
+ type,
+ extras,
+ })),
+ };
+}
+
+export {
+ clientDBThreadInfoToWebThread,
+ webThreadToClientDBThreadInfo,
+ clientDBMessageInfoToWebMessage,
+ webMessageToClientDBMessageInfo,
+};
diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js
--- a/web/shared-worker/types/sqlite-query-executor.js
+++ b/web/shared-worker/types/sqlite-query-executor.js
@@ -15,7 +15,7 @@
type NullableInt,
} from './entities.js';
-type WebMessage = {
+export type WebMessage = {
+id: string,
+localID: NullableString,
+thread: string,
@@ -26,7 +26,7 @@
+time: string,
};
-type Media = {
+export type Media = {
+id: string,
+container: string,
+thread: string,
diff --git a/web/shared-worker/utils/store.js b/web/shared-worker/utils/store.js
--- a/web/shared-worker/utils/store.js
+++ b/web/shared-worker/utils/store.js
@@ -4,6 +4,7 @@
import { communityStoreOpsHandlers } from 'lib/ops/community-store-ops.js';
import { integrityStoreOpsHandlers } from 'lib/ops/integrity-store-ops.js';
import { keyserverStoreOpsHandlers } from 'lib/ops/keyserver-store-ops.js';
+import { messageStoreOpsHandlers } from 'lib/ops/message-store-ops.js';
import { reportStoreOpsHandlers } from 'lib/ops/report-store-ops.js';
import { syncedMetadataStoreOpsHandlers } from 'lib/ops/synced-metadata-store-ops.js';
import { threadStoreOpsHandlers } from 'lib/ops/thread-store-ops.js';
@@ -105,6 +106,21 @@
users: userStoreOpsHandlers.translateClientDBData(data.store.users),
};
}
+ if (data?.store?.messages && data.store.messages.length > 0) {
+ result = {
+ ...result,
+ messages: data.store.messages,
+ };
+ }
+ if (
+ data?.store?.messageStoreThreads &&
+ data.store.messageStoreThreads.length > 0
+ ) {
+ result = {
+ ...result,
+ messageStoreThreads: data.store.messageStoreThreads,
+ };
+ }
return result;
}
@@ -122,6 +138,7 @@
syncedMetadataStoreOperations,
auxUserStoreOperations,
userStoreOperations,
+ messageStoreOperations,
} = storeOperations;
const canUseDatabase = canUseDatabaseOnWeb(userID);
@@ -145,6 +162,8 @@
auxUserStoreOpsHandlers.convertOpsToClientDBOps(auxUserStoreOperations);
const convertedUserStoreOperations =
userStoreOpsHandlers.convertOpsToClientDBOps(userStoreOperations);
+ const convertedMessageStoreOperations =
+ messageStoreOpsHandlers.convertOpsToClientDBOps(messageStoreOperations);
if (
convertedThreadStoreOperations.length === 0 &&
@@ -155,7 +174,8 @@
convertedIntegrityStoreOperations.length === 0 &&
convertedSyncedMetadataStoreOperations.length === 0 &&
convertedAuxUserStoreOperations.length === 0 &&
- convertedUserStoreOperations.length === 0
+ convertedUserStoreOperations.length === 0 &&
+ convertedMessageStoreOperations.length === 0
) {
return;
}
@@ -178,6 +198,7 @@
syncedMetadataStoreOperations: convertedSyncedMetadataStoreOperations,
auxUserStoreOperations: convertedAuxUserStoreOperations,
userStoreOperations: convertedUserStoreOperations,
+ messageStoreOperations: convertedMessageStoreOperations,
},
});
} catch (e) {
diff --git a/web/shared-worker/worker/process-operations.js b/web/shared-worker/worker/process-operations.js
--- a/web/shared-worker/worker/process-operations.js
+++ b/web/shared-worker/worker/process-operations.js
@@ -4,6 +4,7 @@
import type { ClientDBCommunityStoreOperation } from 'lib/ops/community-store-ops.js';
import type { ClientDBIntegrityStoreOperation } from 'lib/ops/integrity-store-ops.js';
import type { ClientDBKeyserverStoreOperation } from 'lib/ops/keyserver-store-ops.js';
+import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js';
import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js';
import type { ClientDBSyncedMetadataStoreOperation } from 'lib/ops/synced-metadata-store-ops.js';
import type { ClientDBThreadStoreOperation } from 'lib/ops/thread-store-ops.js';
@@ -21,6 +22,8 @@
import {
clientDBThreadInfoToWebThread,
webThreadToClientDBThreadInfo,
+ webMessageToClientDBMessageInfo,
+ clientDBMessageInfoToWebMessage,
} from '../types/entities.js';
import type { EmscriptenModule } from '../types/module.js';
import type { SQLiteQueryExecutor } from '../types/sqlite-query-executor.js';
@@ -256,6 +259,63 @@
}
}
+function processMessageStoreOperations(
+ sqliteQueryExecutor: SQLiteQueryExecutor,
+ operations: $ReadOnlyArray<ClientDBMessageStoreOperation>,
+ module: EmscriptenModule,
+) {
+ for (const operation of operations) {
+ try {
+ if (operation.type === 'rekey') {
+ const { from, to } = operation.payload;
+ sqliteQueryExecutor.rekeyMessage(from, to);
+ } else if (operation.type === 'remove') {
+ const { ids } = operation.payload;
+ sqliteQueryExecutor.removeMessages(ids);
+ } else if (operation.type === 'replace') {
+ const { message, medias } = clientDBMessageInfoToWebMessage(
+ operation.payload,
+ );
+ sqliteQueryExecutor.replaceMessageWeb(message);
+ for (const media of medias) {
+ sqliteQueryExecutor.replaceMedia(media);
+ }
+ } else if (operation.type === 'remove_all') {
+ sqliteQueryExecutor.removeAllMessages();
+ sqliteQueryExecutor.removeAllMedia();
+ } else if (operation.type === 'remove_threads') {
+ const { ids } = operation.payload;
+ sqliteQueryExecutor.removeMessageStoreThreads(ids);
+ } else if (operation.type === 'replace_threads') {
+ const { threads } = operation.payload;
+
+ sqliteQueryExecutor.replaceMessageStoreThreads(
+ threads.map(({ id, start_reached }) => ({
+ id,
+ startReached: Number(start_reached),
+ })),
+ );
+ } else if (operation.type === 'remove_all_threads') {
+ sqliteQueryExecutor.removeAllMessageStoreThreads();
+ } else if (operation.type === 'remove_messages_for_threads') {
+ const { threadIDs } = operation.payload;
+ sqliteQueryExecutor.removeMessagesForThreads(threadIDs);
+ } else {
+ throw new Error('Unsupported message operation');
+ }
+ } catch (e) {
+ throw new Error(
+ `Error while processing ${
+ operation.type
+ } message operation: ${getProcessingStoreOpsExceptionMessage(
+ e,
+ module,
+ )}`,
+ );
+ }
+ }
+}
+
function processUserStoreOperations(
sqliteQueryExecutor: SQLiteQueryExecutor,
operations: $ReadOnlyArray<ClientDBUserStoreOperation>,
@@ -299,6 +359,7 @@
syncedMetadataStoreOperations,
auxUserStoreOperations,
userStoreOperations,
+ messageStoreOperations,
} = storeOperations;
try {
@@ -369,6 +430,13 @@
module,
);
}
+ if (messageStoreOperations && messageStoreOperations.length > 0) {
+ processMessageStoreOperations(
+ sqliteQueryExecutor,
+ messageStoreOperations,
+ module,
+ );
+ }
sqliteQueryExecutor.commitTransaction();
} catch (e) {
sqliteQueryExecutor.rollbackTransaction();
@@ -413,11 +481,18 @@
): ClientDBStore {
return {
drafts: sqliteQueryExecutor.getAllDrafts(),
- messages: [],
+ messages: sqliteQueryExecutor
+ .getAllMessagesWeb()
+ .map(webMessageToClientDBMessageInfo),
threads: sqliteQueryExecutor
.getAllThreadsWeb()
- .map(t => webThreadToClientDBThreadInfo(t)),
- messageStoreThreads: [],
+ .map(webThreadToClientDBThreadInfo),
+ messageStoreThreads: sqliteQueryExecutor
+ .getAllMessageStoreThreads()
+ .map(({ id, startReached }) => ({
+ id,
+ start_reached: startReached.toString(),
+ })),
reports: sqliteQueryExecutor.getAllReports(),
users: sqliteQueryExecutor.getAllUsers(),
keyservers: sqliteQueryExecutor.getAllKeyservers(),
diff --git a/web/types/redux-types.js b/web/types/redux-types.js
--- a/web/types/redux-types.js
+++ b/web/types/redux-types.js
@@ -29,7 +29,7 @@
+entryStore: EntryStore,
+threadStore?: ThreadStore,
+userInfos?: UserInfos,
- +messageStore: MessageStore,
+ +messageStore?: MessageStore,
+pushApiPublicKey: ?string,
+inviteLinksStore: InviteLinksStore,
+dataLoaded: boolean,
@@ -39,6 +39,7 @@
export type ExcludedData = {
+userStore?: boolean,
+ +messageStore?: boolean,
+threadStore?: boolean,
};

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 4:29 AM (20 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2533830
Default Alt Text
D11539.id38852.diff (15 KB)

Event Timeline