Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32162163
D15160.1765044706.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D15160.1765044706.diff
View Options
diff --git a/lib/ops/dm-operations-store-ops.js b/lib/ops/dm-operations-store-ops.js
--- a/lib/ops/dm-operations-store-ops.js
+++ b/lib/ops/dm-operations-store-ops.js
@@ -322,6 +322,16 @@
item => !op.payload.ids.includes(item.id),
),
};
+ } else if (op.type === 'replace_dm_operation') {
+ if (op.payload.type === dmOperationUnshimmedType) {
+ processedStore = {
+ ...processedStore,
+ shimmedOperations: [
+ ...processedStore.shimmedOperations,
+ { operation: op.payload.operation, id: op.payload.id },
+ ],
+ };
+ }
}
}
@@ -435,6 +445,103 @@
},
};
+export function convertQueuedDMOperationsStoreToAddOps(
+ store: QueuedDMOperations,
+): $ReadOnlyArray<DMOperationStoreOperation> {
+ const operations: Array<DMOperationStoreOperation> = [];
+
+ // Convert thread queue operations
+ for (const [threadID, operationsQueue] of Object.entries(store.threadQueue)) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.THREAD,
+ threadID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+
+ // Convert message queue operations
+ for (const [messageID, operationsQueue] of Object.entries(
+ store.messageQueue,
+ )) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.MESSAGE,
+ messageID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+
+ // Convert entry queue operations
+ for (const [entryID, operationsQueue] of Object.entries(store.entryQueue)) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.ENTRY,
+ entryID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+
+ // Convert membership queue operations
+ for (const [threadID, threadMembershipQueue] of Object.entries(
+ store.membershipQueue,
+ )) {
+ for (const [userID, operationsQueue] of Object.entries(
+ threadMembershipQueue,
+ )) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.MEMBERSHIP,
+ threadID,
+ userID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+ }
+
+ // Convert shimmed operations
+ for (const shimmedOp of store.shimmedOperations) {
+ operations.push({
+ type: 'replace_dm_operation',
+ payload: {
+ id: shimmedOp.id,
+ type: dmOperationUnshimmedType,
+ operation: shimmedOp.operation,
+ },
+ });
+ }
+
+ return operations;
+}
+
export const dmOperationUnshimmedType = 'unshimmed_operation';
export {
diff --git a/lib/ops/dm-operations-store-ops.test.js b/lib/ops/dm-operations-store-ops.test.js
new file mode 100644
--- /dev/null
+++ b/lib/ops/dm-operations-store-ops.test.js
@@ -0,0 +1,170 @@
+// @flow
+
+import {
+ convertQueuedDMOperationsStoreToAddOps,
+ dmOperationsStoreOpsHandlers,
+} from './dm-operations-store-ops.js';
+import type { QueuedDMOperations } from '../types/dm-ops.js';
+
+describe('convertQueuedDMOperationsStoreToAddOps', () => {
+ // Shared mock operation for reuse
+ const mockOperation = {
+ type: 'send_text_message',
+ threadID: 'thread1',
+ creatorID: 'user123',
+ time: 1642500000000,
+ messageID: 'msg1',
+ text: 'Mock operation',
+ };
+
+ it('should convert complete store to operations and back', () => {
+ // Create mock store with data for all queue types
+ const originalStore: QueuedDMOperations = {
+ threadQueue: {
+ thread1: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500000000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'msg1b' },
+ timestamp: 1642500001000,
+ },
+ ],
+ thread2: [
+ {
+ operation: {
+ ...mockOperation,
+ threadID: 'thread2',
+ messageID: 'msg2a',
+ },
+ timestamp: 1642500002000,
+ },
+ ],
+ },
+ messageQueue: {
+ msg3: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500003000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'msg3b' },
+ timestamp: 1642500004000,
+ },
+ ],
+ msg4: [
+ {
+ operation: { ...mockOperation, messageID: 'msg4a' },
+ timestamp: 1642500005000,
+ },
+ ],
+ },
+ entryQueue: {
+ entry1: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500006000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'entry1b' },
+ timestamp: 1642500007000,
+ },
+ ],
+ entry2: [
+ {
+ operation: { ...mockOperation, messageID: 'entry2a' },
+ timestamp: 1642500008000,
+ },
+ ],
+ },
+ membershipQueue: {
+ thread1: {
+ user123: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500009000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'member1b' },
+ timestamp: 1642500010000,
+ },
+ ],
+ user456: [
+ {
+ operation: { ...mockOperation, messageID: 'member2a' },
+ timestamp: 1642500011000,
+ },
+ ],
+ },
+ thread2: {
+ user789: [
+ {
+ operation: {
+ ...mockOperation,
+ threadID: 'thread2',
+ messageID: 'member3a',
+ },
+ timestamp: 1642500012000,
+ },
+ ],
+ },
+ },
+ shimmedOperations: [
+ {
+ id: 'shimmed1',
+ operation: mockOperation,
+ },
+ {
+ id: 'shimmed2',
+ operation: mockOperation,
+ },
+ ],
+ };
+
+ // Convert store to operations
+ const operations = convertQueuedDMOperationsStoreToAddOps(originalStore);
+
+ // Verify we have the correct number of operations
+ // 3 thread + 3 message + 3 entry + 4 membership + 2 shimmed = 15 total
+ expect(operations).toHaveLength(15);
+
+ // Process operations back to store
+ const emptyStore = {
+ threadQueue: {},
+ messageQueue: {},
+ entryQueue: {},
+ membershipQueue: {},
+ shimmedOperations: [],
+ };
+
+ const reconstructedStore =
+ dmOperationsStoreOpsHandlers.processStoreOperations(
+ emptyStore,
+ operations,
+ );
+
+ // Verify reconstructed store matches original
+ expect(reconstructedStore).toEqual(originalStore);
+ });
+
+ it('should handle empty store', () => {
+ const emptyStore = {
+ threadQueue: {},
+ messageQueue: {},
+ entryQueue: {},
+ membershipQueue: {},
+ shimmedOperations: [],
+ };
+
+ const operations = convertQueuedDMOperationsStoreToAddOps(emptyStore);
+ expect(operations).toHaveLength(0);
+
+ const reconstructedStore =
+ dmOperationsStoreOpsHandlers.processStoreOperations(
+ emptyStore,
+ operations,
+ );
+ expect(reconstructedStore).toEqual(emptyStore);
+ });
+});
diff --git a/native/redux/handle-redux-migration-failure.js b/native/redux/handle-redux-migration-failure.js
--- a/native/redux/handle-redux-migration-failure.js
+++ b/native/redux/handle-redux-migration-failure.js
@@ -30,6 +30,7 @@
'globalThemeInfo',
'holderStore',
'threadActivityStore',
+ 'queuedDMOperations',
];
function handleReduxMigrationFailure(oldState: AppState): AppState {
diff --git a/native/redux/persist-constants.js b/native/redux/persist-constants.js
--- a/native/redux/persist-constants.js
+++ b/native/redux/persist-constants.js
@@ -5,6 +5,6 @@
// NOTE: renaming this constant requires updating
// `native/native_rust_library/build.rs` to correctly
// scrap Redux state version from this file.
-const storeVersion = 94;
+const storeVersion = 95;
export { rootKey, storeVersion };
diff --git a/native/redux/persist.js b/native/redux/persist.js
--- a/native/redux/persist.js
+++ b/native/redux/persist.js
@@ -17,6 +17,7 @@
convertConnectionInfoToNewIDSchema,
} from 'lib/_generated/migration-utils.js';
import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js';
+import { convertQueuedDMOperationsStoreToAddOps } from 'lib/ops/dm-operations-store-ops.js';
import type {
ClientDBEntryStoreOperation,
ReplaceEntryOperation,
@@ -1690,6 +1691,17 @@
},
};
}: MigrationFunction<NavInfo, AppState>),
+ [95]: (async (state: AppState) => {
+ const queuedDMOperations = state.queuedDMOperations;
+
+ return {
+ state,
+ ops: {
+ dmOperationStoreOperations:
+ convertQueuedDMOperationsStoreToAddOps(queuedDMOperations),
+ },
+ };
+ }: MigrationFunction<NavInfo, AppState>),
});
const persistConfig = {
diff --git a/web/redux/handle-redux-migration-failure.js b/web/redux/handle-redux-migration-failure.js
--- a/web/redux/handle-redux-migration-failure.js
+++ b/web/redux/handle-redux-migration-failure.js
@@ -11,7 +11,6 @@
'customServer',
'messageStore',
'tunnelbrokerDeviceToken',
- 'queuedDMOperations',
'restoreBackupState',
];
diff --git a/web/redux/persist-constants.js b/web/redux/persist-constants.js
--- a/web/redux/persist-constants.js
+++ b/web/redux/persist-constants.js
@@ -3,6 +3,6 @@
const rootKey = 'root';
const rootKeyPrefix = 'persist:';
const completeRootKey = `${rootKeyPrefix}${rootKey}`;
-const storeVersion = 94;
+const storeVersion = 95;
export { rootKey, rootKeyPrefix, completeRootKey, storeVersion };
diff --git a/web/redux/persist.js b/web/redux/persist.js
--- a/web/redux/persist.js
+++ b/web/redux/persist.js
@@ -7,6 +7,7 @@
import type { PersistConfig } from 'redux-persist/src/types.js';
import { createReplaceThreadOperation } from 'lib/ops/create-replace-thread-operation.js';
+import { convertQueuedDMOperationsStoreToAddOps } from 'lib/ops/dm-operations-store-ops.js';
import {
type HolderStoreOperation,
createReplaceHoldersOperation,
@@ -904,6 +905,17 @@
},
};
}: MigrationFunction<WebNavInfo, AppState>),
+ [95]: (async (state: AppState) => {
+ const queuedDMOperations = state.queuedDMOperations;
+
+ return {
+ state,
+ ops: {
+ dmOperationStoreOperations:
+ convertQueuedDMOperationsStoreToAddOps(queuedDMOperations),
+ },
+ };
+ }: MigrationFunction<WebNavInfo, AppState>),
};
const persistConfig: PersistConfig = {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 6, 6:11 PM (18 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5839999
Default Alt Text
D15160.1765044706.diff (11 KB)
Attached To
Mode
D15160: [web][native] migrate QueuedDMOperations to SQLite
Attached
Detach File
Event Timeline
Log In to Comment