diff --git a/keyserver/src/fetchers/message-fetchers.js b/keyserver/src/fetchers/message-fetchers.js --- a/keyserver/src/fetchers/message-fetchers.js +++ b/keyserver/src/fetchers/message-fetchers.js @@ -708,6 +708,16 @@ return rawMessageInfoFromRows(result, viewer, derivedMessages); } +async function fetchThreadMessagesCount(threadID: string): Promise { + const query = SQL` + SELECT COUNT(*) AS count + FROM messages + WHERE thread = ${threadID} + `; + const [result] = await dbQuery(query); + return result[0].count; +} + export { fetchCollapsableNotifs, fetchMessageInfos, @@ -716,4 +726,5 @@ fetchMessageInfoForLocalID, fetchMessageInfoForEntryAction, fetchMessageInfoByID, + fetchThreadMessagesCount, }; diff --git a/keyserver/src/responders/message-responders.js b/keyserver/src/responders/message-responders.js --- a/keyserver/src/responders/message-responders.js +++ b/keyserver/src/responders/message-responders.js @@ -36,6 +36,7 @@ fetchMessageInfos, fetchMessageInfoForLocalID, fetchMessageInfoByID, + fetchThreadMessagesCount, } from '../fetchers/message-fetchers.js'; import { fetchServerThreadInfos } from '../fetchers/thread-fetchers.js'; import { checkThreadPermission } from '../fetchers/thread-permission-fetchers.js'; @@ -90,7 +91,16 @@ messageData = { ...messageData, localID }; } if (sidebarCreation) { - messageData = { ...messageData, sidebarCreation }; + const numMessages = await fetchThreadMessagesCount(threadID); + if (numMessages === 2) { + // sidebarCreation is set below to prevent double notifs from a sidebar + // creation. We expect precisely two messages to appear before a + // sidebarCreation: a SIDEBAR_SOURCE and a CREATE_SIDEBAR. If two users + // attempt to create a sidebar at the same time, then both clients will + // attempt to set sidebarCreation here, but we only want to suppress + // notifs for the client that won the race. + messageData = { ...messageData, sidebarCreation }; + } } const rawMessageInfos = await createMessages(viewer, [messageData]);