From b9afde051e9423c001e293eda551ae58df209e8a Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Tue, 28 May 2024 03:12:33 +0200 Subject: [PATCH] Improved notification efficiency. --- src/alerts.js | 88 +++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/src/alerts.js b/src/alerts.js index 67ea0dc..9ca844d 100755 --- a/src/alerts.js +++ b/src/alerts.js @@ -150,51 +150,57 @@ export async function fetchNotifications(reqUser, options = {}) { return []; } - const notifications = await knex('notifications') - .select( - 'notifications.*', - 'alerts.id as alert_id', - knex.raw('coalesce(array_agg(alerts_actors.actor_id) filter (where alerts_actors.id is not null), \'{}\') as alert_actors'), - knex.raw('coalesce(array_agg(alerts_tags.tag_id) filter (where alerts_tags.id is not null), \'{}\') as alert_tags'), - knex.raw('coalesce(array_agg(alerts_entities.entity_id) filter (where alerts_entities.id is not null), \'{}\') as alert_entities'), - knex.raw('coalesce(json_agg(alerts_matches) filter (where alerts_matches.id is not null), \'[]\') as alert_matches'), - ) - .leftJoin('alerts', 'alerts.id', 'notifications.alert_id') - .leftJoin('alerts_actors', 'alerts_actors.alert_id', 'alerts.id') - .leftJoin('alerts_tags', 'alerts_tags.alert_id', 'alerts.id') - .leftJoin('alerts_entities', 'alerts_entities.alert_id', 'alerts.id') - .leftJoin('alerts_matches', 'alerts_matches.alert_id', 'alerts.id') - .where('notifications.user_id', reqUser.id) - .groupBy('notifications.id', 'alerts.id') - .orderBy('created_at', 'desc'); + const [notifications, rawUnseen] = await Promise.all([ + knex('notifications') + .select( + 'notifications.*', + 'alerts.id as alert_id', + knex.raw('coalesce(array_agg(alerts_actors.actor_id) filter (where alerts_actors.id is not null), \'{}\') as alert_actors'), + knex.raw('coalesce(array_agg(alerts_tags.tag_id) filter (where alerts_tags.id is not null), \'{}\') as alert_tags'), + knex.raw('coalesce(array_agg(alerts_entities.entity_id) filter (where alerts_entities.id is not null), \'{}\') as alert_entities'), + knex.raw('coalesce(json_agg(alerts_matches) filter (where alerts_matches.id is not null), \'[]\') as alert_matches'), + ) + .leftJoin('alerts', 'alerts.id', 'notifications.alert_id') + .leftJoin('alerts_actors', 'alerts_actors.alert_id', 'alerts.id') + .leftJoin('alerts_tags', 'alerts_tags.alert_id', 'alerts.id') + .leftJoin('alerts_entities', 'alerts_entities.alert_id', 'alerts.id') + .leftJoin('alerts_matches', 'alerts_matches.alert_id', 'alerts.id') + .where('notifications.user_id', reqUser.id) + .limit(options.limit) + .groupBy('notifications.id', 'alerts.id') + .orderBy('created_at', 'desc'), + knex('notifications') + .select(knex.raw('count(id)')) + .where('user_id', reqUser.id) + .where('seen', false) + .first(), + ]); const scenes = await fetchScenesById(notifications.map((notification) => notification.scene_id)); - const unseen = notifications.filter((notification) => !notification.seen).length; + const unseen = Number(rawUnseen.count); - const curatedNotifications = notifications - .slice(0, options.limit || 10) - .map((notification) => { - const scene = scenes.find((sceneX) => sceneX.id === notification.scene_id); + const curatedNotifications = notifications.map((notification) => { + const scene = scenes.find((sceneX) => sceneX.id === notification.scene_id); - return { - id: notification.id, - sceneId: notification.scene_id, - scene, - alertId: notification.alert_id, - matchedActors: scene.actors.filter((actor) => notification.alert_actors.includes(actor.id)), - matchedTags: scene.tags.filter((tag) => notification.alert_tags.includes(tag.id)), - matchedEntity: [scene.channel, scene.network].find((entity) => notification.alert_entities.includes(entity?.id)) || null, - matchedExpressions: notification.alert_matches - .filter((match) => new RegExp(match.expression, 'ui').test(scene[match.property])) - .map((match) => ({ - id: match.id, - property: match.property, - expression: match.expression, - })), - isSeen: notification.seen, - createdAt: notification.created_at, - }; - }); + return { + id: notification.id, + sceneId: notification.scene_id, + scene, + alertId: notification.alert_id, + matchedActors: scene.actors.filter((actor) => notification.alert_actors.includes(actor.id)), + matchedTags: scene.tags.filter((tag) => notification.alert_tags.includes(tag.id)), + matchedEntity: [scene.channel, scene.network].find((entity) => notification.alert_entities.includes(entity?.id)) || null, + matchedExpressions: notification.alert_matches + .filter((match) => new RegExp(match.expression, 'ui').test(scene[match.property])) + .map((match) => ({ + id: match.id, + property: match.property, + expression: match.expression, + })), + isSeen: notification.seen, + createdAt: notification.created_at, + }; + }); return { notifications: curatedNotifications,