From 48be006eba8fd1a016e3c6212a65fc3b1bf2f05b Mon Sep 17 00:00:00 2001 From: Louis Laureys Date: Sun, 12 Sep 2021 17:24:46 +0200 Subject: [PATCH 1/2] Add optional thread message counters to listing --- docs/api/openapi.yml | 13 +++++++++++++ lib/api/messages.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/docs/api/openapi.yml b/docs/api/openapi.yml index 1b9bbbc3..26307b07 100644 --- a/docs/api/openapi.yml +++ b/docs/api/openapi.yml @@ -1503,6 +1503,11 @@ paths: description: 'If true, then includes metaData in the response' schema: type: boolean + - name: threadCounters + in: query + description: 'If true, then includes threadMessageCount in the response. Counters come with some overhead' + schema: + type: boolean - name: limit in: query description: How many records to return @@ -1828,6 +1833,11 @@ paths: description: Maximal message size in bytes schema: type: number + - name: threadCounters + in: query + description: 'If true, then includes threadMessageCount in the response. Counters come with some overhead' + schema: + type: boolean - name: limit in: query description: How many records to return @@ -6379,6 +6389,9 @@ components: thread: type: string description: ID of the Thread + threadMessageCount: + type: number + description: Amount of messages in the Thread. Included if threadCounters query argument was true from: $ref: '#/components/schemas/Address' to: diff --git a/lib/api/messages.js b/lib/api/messages.js index 0de6fc82..13e107a1 100644 --- a/lib/api/messages.js +++ b/lib/api/messages.js @@ -267,6 +267,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti mailbox: Joi.string().hex().lowercase().length(24).required(), unseen: booleanSchema, metaData: booleanSchema.default(false), + threadCounters: booleanSchema.default(false), limit: Joi.number().empty('').default(20).min(1).max(250), order: Joi.any().empty('').allow('asc', 'desc').default('desc'), next: nextPageCursorSchema, @@ -302,6 +303,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti let user = new ObjectId(result.value.user); let mailbox = new ObjectId(result.value.mailbox); let limit = result.value.limit; + let threadCounters = result.value.threadCounters; let page = result.value.page; let pageNext = result.value.next; let pagePrevious = result.value.previous; @@ -410,6 +412,19 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti page = 1; } + if (threadCounters) { + const threadIdsToFetch = listing.results.map(message => message.thread); + const threads = await db.database + .collection('threads') + .find({ _id: { $in: threadIdsToFetch } }) + .toArray(); + + listing.results = listing.results.map(message => ({ + ...message, + threadEntity: threads.find(thread => thread._id.toString() === message.thread.toString()) + })); + } + let response = { success: true, total, @@ -454,6 +469,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti flagged: booleanSchema, unseen: booleanSchema, searchable: booleanSchema, + threadCounters: booleanSchema.default(false), limit: Joi.number().default(20).min(1).max(250), next: nextPageCursorSchema, previous: previousPageCursorSchema, @@ -505,6 +521,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti let filterMinSize = result.value.minSize; let filterMaxSize = result.value.maxSize; + let threadCounters = result.value.threadCounters; let limit = result.value.limit; let page = result.value.page; let pageNext = result.value.next; @@ -819,6 +836,19 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti page = 1; } + if (threadCounters) { + const threadIdsToFetch = listing.results.map(message => message.thread); + const threads = await db.database + .collection('threads') + .find({ _id: { $in: threadIdsToFetch } }) + .toArray(); + + listing.results = listing.results.map(message => ({ + ...message, + threadEntity: threads.find(thread => thread._id.toString() === message.thread.toString()) + })); + } + let response = { success: true, query, @@ -3139,6 +3169,7 @@ function formatMessageListing(messageData) { id: messageData.uid, mailbox: messageData.mailbox, thread: messageData.thread, + threadMessageCount: messageData.threadEntity?.ids?.length, from: from && from[0], to, cc, From d7d73179eedf8110d51c9a8a163a341b930fdb63 Mon Sep 17 00:00:00 2001 From: Louis Laureys Date: Sun, 12 Sep 2021 22:15:39 +0200 Subject: [PATCH 2/2] Make thread counters work correctly --- lib/api/messages.js | 53 +++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/lib/api/messages.js b/lib/api/messages.js index 13e107a1..2869e4a6 100644 --- a/lib/api/messages.js +++ b/lib/api/messages.js @@ -61,6 +61,35 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti }); }); + const addThreadCountersToMessageList = async (user, list) => { + const threadIdsToCount = list.map(message => message.thread); + const threadCounts = await db.database + .collection('messages') + .aggregate([ + { + $match: { + user: new ObjectId(user), + thread: { $in: threadIdsToCount } + } + }, + { + $group: { + _id: '$thread', + count: { + $sum: 1 + } + } + } + ]) + .toArray(); + + return list.map(message => { + const matchingThreadCount = threadCounts.find(thread => thread._id.toString() === message.thread.toString()); + message.threadMessageCount = matchingThreadCount ? matchingThreadCount.count : undefined + return message + }); + }; + const putMessageHandler = async (req, res, next) => { res.charSet('utf-8'); @@ -413,16 +442,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti } if (threadCounters) { - const threadIdsToFetch = listing.results.map(message => message.thread); - const threads = await db.database - .collection('threads') - .find({ _id: { $in: threadIdsToFetch } }) - .toArray(); - - listing.results = listing.results.map(message => ({ - ...message, - threadEntity: threads.find(thread => thread._id.toString() === message.thread.toString()) - })); + listing.results = await addThreadCountersToMessageList(user, listing.results); } let response = { @@ -837,16 +857,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti } if (threadCounters) { - const threadIdsToFetch = listing.results.map(message => message.thread); - const threads = await db.database - .collection('threads') - .find({ _id: { $in: threadIdsToFetch } }) - .toArray(); - - listing.results = listing.results.map(message => ({ - ...message, - threadEntity: threads.find(thread => thread._id.toString() === message.thread.toString()) - })); + listing.results = await addThreadCountersToMessageList(user, listing.results); } let response = { @@ -3169,7 +3180,7 @@ function formatMessageListing(messageData) { id: messageData.uid, mailbox: messageData.mailbox, thread: messageData.thread, - threadMessageCount: messageData.threadEntity?.ids?.length, + threadMessageCount: messageData.threadMessageCount, from: from && from[0], to, cc,