diff --git a/lib/shared/dm-ops/add-members-spec.js b/lib/shared/dm-ops/add-members-spec.js --- a/lib/shared/dm-ops/add-members-spec.js +++ b/lib/shared/dm-ops/add-members-spec.js @@ -170,6 +170,25 @@ ); return { rawMessageInfos, updateInfos }; }, + canBeProcessed( + dmOperation: DMAddMembersOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if ( + utilities.threadInfos[dmOperation.existingThreadDetails.threadID] || + dmOperation.addedUserIDs.includes(viewerID) + ) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.existingThreadDetails.threadID, + }, + }; + }, }); export { addMembersSpec, createAddNewMembersResults }; diff --git a/lib/shared/dm-ops/change-thread-settings-spec.js b/lib/shared/dm-ops/change-thread-settings-spec.js --- a/lib/shared/dm-ops/change-thread-settings-spec.js +++ b/lib/shared/dm-ops/change-thread-settings-spec.js @@ -1,8 +1,12 @@ // @flow +import invariant from 'invariant'; import uuid from 'uuid'; -import { createAddNewMembersResults } from './add-members-spec.js'; +import { + addMembersSpec, + createAddNewMembersResults, +} from './add-members-spec.js'; import type { DMOperationSpec, ProcessDMOperationUtilities, @@ -17,6 +21,25 @@ import type { ClientUpdateInfo } from '../../types/update-types.js'; import { values } from '../../utils/objects.js'; +function createAddMembersOperation( + dmOperation: DMChangeThreadSettingsOperation, +) { + const { editorID, time, messageIDsPrefix, changes, existingThreadDetails } = + dmOperation; + const newMemberIDs = + changes.newMemberIDs && changes.newMemberIDs.length > 0 + ? [...new Set(changes.newMemberIDs)] + : []; + return { + type: 'add_members', + editorID, + time, + messageID: `${messageIDsPrefix}/add_members`, + addedUserIDs: newMemberIDs, + existingThreadDetails, + }; +} + const changeThreadSettingsSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( @@ -34,34 +57,15 @@ const { name, description, color, avatar } = changes; const threadID = existingThreadDetails.threadID; - const newMemberIDs = - changes.newMemberIDs && changes.newMemberIDs.length > 0 - ? [...new Set(changes.newMemberIDs)] - : null; - let threadInfoToUpdate: ?(RawThreadInfo | LegacyRawThreadInfo) = utilities.threadInfos[threadID]; - if (!threadInfoToUpdate && !newMemberIDs?.includes(viewerID)) { - // We can't perform this operation now. It should be queued for later. - return { - rawMessageInfos: [], - updateInfos: [], - }; - } - const updateInfos: Array = []; const rawMessageInfos: Array = []; - if (newMemberIDs) { + if (changes.newMemberIDs && changes.newMemberIDs.length > 0) { + const addMembersOperation = createAddMembersOperation(dmOperation); const addMembersResult = createAddNewMembersResults( - { - type: 'add_members', - editorID, - time, - messageID: `${messageIDsPrefix}/add_members`, - addedUserIDs: newMemberIDs, - existingThreadDetails, - }, + addMembersOperation, viewerID, utilities, ); @@ -72,13 +76,7 @@ rawMessageInfos.push(...addMembersResult.rawMessageInfos); } - if (!threadInfoToUpdate || !threadInfoToUpdate.thick) { - // We can't perform this operation now. It should be queued for later. - return { - rawMessageInfos: [], - updateInfos: [], - }; - } + invariant(threadInfoToUpdate?.thick, 'Thread should be thick'); const changedFields: { [string]: string | number } = {}; @@ -157,6 +155,17 @@ updateInfos, }; }, + canBeProcessed( + dmOperation: DMChangeThreadSettingsOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + return addMembersSpec.canBeProcessed( + createAddMembersOperation(dmOperation), + viewerID, + utilities, + ); + }, }); export { changeThreadSettingsSpec }; diff --git a/lib/shared/dm-ops/create-sidebar-spec.js b/lib/shared/dm-ops/create-sidebar-spec.js --- a/lib/shared/dm-ops/create-sidebar-spec.js +++ b/lib/shared/dm-ops/create-sidebar-spec.js @@ -105,6 +105,9 @@ updateInfos: [threadJoinUpdateInfo], }; }, + canBeProcessed() { + return { isProcessingPossible: true }; + }, }); export { createSidebarSpec }; diff --git a/lib/shared/dm-ops/create-thread-spec.js b/lib/shared/dm-ops/create-thread-spec.js --- a/lib/shared/dm-ops/create-thread-spec.js +++ b/lib/shared/dm-ops/create-thread-spec.js @@ -187,6 +187,9 @@ updateInfos: [threadJoinUpdateInfo], }; }, + canBeProcessed() { + return { isProcessingPossible: true }; + }, }); export { diff --git a/lib/shared/dm-ops/dm-op-spec.js b/lib/shared/dm-ops/dm-op-spec.js --- a/lib/shared/dm-ops/dm-op-spec.js +++ b/lib/shared/dm-ops/dm-op-spec.js @@ -16,4 +16,14 @@ viewerID: string, utilities: ProcessDMOperationUtilities, ) => Promise, + +canBeProcessed: ( + dmOp: DMOp, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) => + | { +isProcessingPossible: true } + | { + +isProcessingPossible: false, + +reason: { +type: 'missing_thread', +threadID: string }, + }, }; diff --git a/lib/shared/dm-ops/join-thread-spec.js b/lib/shared/dm-ops/join-thread-spec.js --- a/lib/shared/dm-ops/join-thread-spec.js +++ b/lib/shared/dm-ops/join-thread-spec.js @@ -18,10 +18,7 @@ messageTruncationStatus, type RawMessageInfo, } from '../../types/message-types.js'; -import { - minimallyEncodeMemberInfo, - type ThickRawThreadInfo, -} from '../../types/minimally-encoded-thread-permissions-types.js'; +import { minimallyEncodeMemberInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import { joinThreadSubscription } from '../../types/subscription-types.js'; import type { ThickMemberInfo } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; @@ -37,6 +34,9 @@ ) => { const { editorID, time, messageID, existingThreadDetails } = dmOperation; + const currentThreadInfo = + utilities.threadInfos[existingThreadDetails.threadID]; + const joinThreadMessage = { type: messageTypes.JOIN_THREAD, id: messageID, @@ -45,9 +45,7 @@ time, }; - const currentThreadInfoOptional = - utilities.threadInfos[existingThreadDetails.threadID]; - if (userIsMember(currentThreadInfoOptional, editorID)) { + if (userIsMember(currentThreadInfo, editorID)) { return { rawMessageInfos: [joinThreadMessage], updateInfos: [ @@ -97,14 +95,7 @@ updateInfos.push(repliesCountUpdate); } } else { - if (!currentThreadInfoOptional || !currentThreadInfoOptional.thick) { - // We can't perform this operation now. It should be queued for later. - return { - rawMessageInfos: [], - updateInfos: [], - }; - } - const currentThreadInfo: ThickRawThreadInfo = currentThreadInfoOptional; + invariant(currentThreadInfo.thick, 'Thread should be thick'); rawMessageInfos.push(joinThreadMessage); const defaultRoleID = values(currentThreadInfo.roles).find(role => @@ -153,6 +144,22 @@ updateInfos, }; }, + canBeProcessed( + dmOperation: DMJoinThreadOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if (utilities.threadInfos[dmOperation.existingThreadDetails.threadID]) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.existingThreadDetails.threadID, + }, + }; + }, }); export { joinThreadSpec }; diff --git a/lib/shared/dm-ops/leave-thread-spec.js b/lib/shared/dm-ops/leave-thread-spec.js --- a/lib/shared/dm-ops/leave-thread-spec.js +++ b/lib/shared/dm-ops/leave-thread-spec.js @@ -1,5 +1,6 @@ // @flow +import invariant from 'invariant'; import uuid from 'uuid'; import type { @@ -9,7 +10,6 @@ import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; import type { DMLeaveThreadOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; -import type { ThickRawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import { threadTypes } from '../../types/thread-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; @@ -23,15 +23,8 @@ ) => { const { editorID, time, messageID, threadID } = dmOperation; - const threadInfoOptional = utilities.threadInfos[threadID]; - if (!threadInfoOptional || !threadInfoOptional.thick) { - // We can't perform this operation now. It should be queued for later. - return { - rawMessageInfos: [], - updateInfos: [], - }; - } - const threadInfo: ThickRawThreadInfo = threadInfoOptional; + const threadInfo = utilities.threadInfos[threadID]; + invariant(threadInfo.thick, 'Thread should be thick'); const leaveThreadMessage = { type: messageTypes.LEAVE_THREAD, @@ -86,6 +79,22 @@ updateInfos, }; }, + canBeProcessed( + dmOperation: DMLeaveThreadOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if (utilities.threadInfos[dmOperation.threadID]) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.threadID, + }, + }; + }, }); export { leaveThreadSpec }; diff --git a/lib/shared/dm-ops/process-dm-ops.js b/lib/shared/dm-ops/process-dm-ops.js --- a/lib/shared/dm-ops/process-dm-ops.js +++ b/lib/shared/dm-ops/process-dm-ops.js @@ -32,6 +32,15 @@ console.log('ignored DMOperation because logged out'); return; } + const processingCheckResult = dmOpSpecs[dmOp.type].canBeProcessed( + dmOp, + viewerID, + utilities, + ); + if (!processingCheckResult.isProcessingPossible) { + // TODO queue for later + return; + } const { rawMessageInfos, updateInfos } = await dmOpSpecs[ dmOp.type ].processDMOperation(dmOp, viewerID, utilities); diff --git a/lib/shared/dm-ops/remove-members-spec.js b/lib/shared/dm-ops/remove-members-spec.js --- a/lib/shared/dm-ops/remove-members-spec.js +++ b/lib/shared/dm-ops/remove-members-spec.js @@ -1,5 +1,6 @@ // @flow +import invariant from 'invariant'; import uuid from 'uuid'; import type { @@ -9,7 +10,6 @@ import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; import type { DMRemoveMembersOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; -import type { ThickRawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import { threadTypes } from '../../types/thread-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; @@ -24,15 +24,8 @@ const { editorID, time, messageID, threadID, removedUserIDs } = dmOperation; - const threadInfoOptional = utilities.threadInfos[threadID]; - if (!threadInfoOptional || !threadInfoOptional.thick) { - // We can't perform this operation now. It should be queued for later. - return { - rawMessageInfos: [], - updateInfos: [], - }; - } - const threadInfo: ThickRawThreadInfo = threadInfoOptional; + const threadInfo = utilities.threadInfos[threadID]; + invariant(threadInfo.thick, 'Thread should be thick'); const removeMembersMessage = { type: messageTypes.REMOVE_MEMBERS, @@ -90,6 +83,22 @@ updateInfos, }; }, + canBeProcessed( + dmOperation: DMRemoveMembersOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if (utilities.threadInfos[dmOperation.threadID]) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.threadID, + }, + }; + }, }); export { removeMembersSpec }; diff --git a/lib/shared/dm-ops/send-edit-message-spec.js b/lib/shared/dm-ops/send-edit-message-spec.js --- a/lib/shared/dm-ops/send-edit-message-spec.js +++ b/lib/shared/dm-ops/send-edit-message-spec.js @@ -42,19 +42,33 @@ }); } const threadInfo = utilities.threadInfos[threadID]; - if (threadInfo) { - const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ - editMessage, - ]); - if (repliesCountUpdate) { - updateInfos.push(repliesCountUpdate); - } + const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ + editMessage, + ]); + if (repliesCountUpdate) { + updateInfos.push(repliesCountUpdate); } return { rawMessageInfos: [editMessage], updateInfos, }; }, + canBeProcessed( + dmOperation: DMSendEditMessageOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if (utilities.threadInfos[dmOperation.threadID]) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.threadID, + }, + }; + }, }); export { sendEditMessageSpec }; diff --git a/lib/shared/dm-ops/send-reaction-message-spec.js b/lib/shared/dm-ops/send-reaction-message-spec.js --- a/lib/shared/dm-ops/send-reaction-message-spec.js +++ b/lib/shared/dm-ops/send-reaction-message-spec.js @@ -50,19 +50,33 @@ }); } const threadInfo = utilities.threadInfos[threadID]; - if (threadInfo) { - const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ - reactionMessage, - ]); - if (repliesCountUpdate) { - updateInfos.push(repliesCountUpdate); - } + const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ + reactionMessage, + ]); + if (repliesCountUpdate) { + updateInfos.push(repliesCountUpdate); } return { rawMessageInfos: [reactionMessage], updateInfos, }; }, + canBeProcessed( + dmOperation: DMSendReactionMessageOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if (utilities.threadInfos[dmOperation.threadID]) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.threadID, + }, + }; + }, }); export { sendReactionMessageSpec }; diff --git a/lib/shared/dm-ops/send-text-message-spec.js b/lib/shared/dm-ops/send-text-message-spec.js --- a/lib/shared/dm-ops/send-text-message-spec.js +++ b/lib/shared/dm-ops/send-text-message-spec.js @@ -39,19 +39,33 @@ }); } const threadInfo = utilities.threadInfos[threadID]; - if (threadInfo) { - const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ - textMessage, - ]); - if (repliesCountUpdate) { - updateInfos.push(repliesCountUpdate); - } + const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ + textMessage, + ]); + if (repliesCountUpdate) { + updateInfos.push(repliesCountUpdate); } return { rawMessageInfos: [textMessage], updateInfos, }; }, + canBeProcessed( + dmOperation: DMSendTextMessageOperation, + viewerID: string, + utilities: ProcessDMOperationUtilities, + ) { + if (utilities.threadInfos[dmOperation.threadID]) { + return { isProcessingPossible: true }; + } + return { + isProcessingPossible: false, + reason: { + type: 'missing_thread', + threadID: dmOperation.threadID, + }, + }; + }, }); export { sendTextMessageSpec };