From 0f067fc503e7e3c73a12a95e71acdb128edd6b85 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Feb 2025 12:52:10 -0500 Subject: [PATCH] feature/IO-3096-GlobalNotifications - Checkpoint, Ratify notifications tb table. --- hasura/metadata/tables.yaml | 84 +++++++++++++------ .../down.sql | 3 + .../up.sql | 1 + .../down.sql | 4 + .../up.sql | 1 + .../down.sql | 3 + .../up.sql | 1 + .../down.sql | 3 + .../up.sql | 1 + .../down.sql | 1 + .../up.sql | 1 + .../down.sql | 1 + .../up.sql | 1 + .../down.sql | 1 + .../up.sql | 1 + server/notifications/queues/appQueue.js | 76 +++++------------ 16 files changed, 101 insertions(+), 82 deletions(-) create mode 100644 hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql create mode 100644 hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql create mode 100644 hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql create mode 100644 hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql create mode 100644 hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql create mode 100644 hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql create mode 100644 hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql create mode 100644 hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql create mode 100644 hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql create mode 100644 hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql create mode 100644 hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql create mode 100644 hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql create mode 100644 hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql create mode 100644 hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index e713d16f0..0fb3007c5 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -4893,46 +4893,78 @@ - name: job using: foreign_key_constraint_on: jobid + insert_permissions: + - role: user + permission: + check: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - scenario_meta + - scenario_text + - fcm_text + - created_at + - read + - updated_at + - associationid + - id + - jobid + comment: "" select_permissions: - role: user permission: columns: - - associationid + - scenario_meta + - scenario_text + - fcm_text - created_at - - fcm_data - - fcm_message - - fcm_title + - read + - updated_at + - associationid - id - jobid - - meta - - read - - ui_translation_meta - - ui_translation_string - - updated_at filter: - association: - _and: - - active: - _eq: true - - user: - authid: - _eq: X-Hasura-User-Id + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true comment: "" update_permissions: - role: user permission: columns: - - meta + - scenario_meta + - scenario_text + - fcm_text + - created_at - read - filter: - association: - _and: - - active: - _eq: true - - user: - authid: - _eq: X-Hasura-User-Id - check: null + - updated_at + - associationid + - id + - jobid + filter: {} + check: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true comment: "" - table: name: owners diff --git a/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql new file mode 100644 index 000000000..3986cbda4 --- /dev/null +++ b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql @@ -0,0 +1,3 @@ +comment on column "public"."notifications"."html_body" is E'Real Time Notifications System'; +alter table "public"."notifications" alter column "html_body" drop not null; +alter table "public"."notifications" add column "html_body" text; diff --git a/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql new file mode 100644 index 000000000..58ee2d95f --- /dev/null +++ b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" drop column "html_body" cascade; diff --git a/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql new file mode 100644 index 000000000..70e4fc311 --- /dev/null +++ b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql @@ -0,0 +1,4 @@ +comment on column "public"."notifications"."fcm_data" is E'Real Time Notifications System'; +alter table "public"."notifications" alter column "fcm_data" set default jsonb_build_object(); +alter table "public"."notifications" alter column "fcm_data" drop not null; +alter table "public"."notifications" add column "fcm_data" jsonb; diff --git a/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql new file mode 100644 index 000000000..3f6441573 --- /dev/null +++ b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" drop column "fcm_data" cascade; diff --git a/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql new file mode 100644 index 000000000..4651b79a3 --- /dev/null +++ b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql @@ -0,0 +1,3 @@ +comment on column "public"."notifications"."fcm_message" is E'Real Time Notifications System'; +alter table "public"."notifications" alter column "fcm_message" drop not null; +alter table "public"."notifications" add column "fcm_message" text; diff --git a/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql new file mode 100644 index 000000000..6a51ad6f5 --- /dev/null +++ b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" drop column "fcm_message" cascade; diff --git a/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql new file mode 100644 index 000000000..234537d07 --- /dev/null +++ b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql @@ -0,0 +1,3 @@ +comment on column "public"."notifications"."ui_translation_string" is E'Real Time Notifications System'; +alter table "public"."notifications" alter column "ui_translation_string" drop not null; +alter table "public"."notifications" add column "ui_translation_string" text; diff --git a/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql new file mode 100644 index 000000000..702af0747 --- /dev/null +++ b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" drop column "ui_translation_string" cascade; diff --git a/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql new file mode 100644 index 000000000..f76615392 --- /dev/null +++ b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql @@ -0,0 +1 @@ +alter table "public"."notifications" rename column "fcm_text" to "fcm_title"; diff --git a/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql new file mode 100644 index 000000000..4e39cf157 --- /dev/null +++ b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" rename column "fcm_title" to "fcm_text"; diff --git a/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql new file mode 100644 index 000000000..4b7add7b9 --- /dev/null +++ b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql @@ -0,0 +1 @@ +alter table "public"."notifications" rename column "scenario_text" to "ui_translation_meta"; diff --git a/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql new file mode 100644 index 000000000..b2c933ed9 --- /dev/null +++ b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" rename column "ui_translation_meta" to "scenario_text"; diff --git a/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql new file mode 100644 index 000000000..f0ef6d736 --- /dev/null +++ b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql @@ -0,0 +1 @@ +alter table "public"."notifications" rename column "scenario_meta" to "meta"; diff --git a/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql new file mode 100644 index 000000000..4561da723 --- /dev/null +++ b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" rename column "meta" to "scenario_meta"; diff --git a/server/notifications/queues/appQueue.js b/server/notifications/queues/appQueue.js index e5ffb9617..a600fb525 100644 --- a/server/notifications/queues/appQueue.js +++ b/server/notifications/queues/appQueue.js @@ -20,7 +20,7 @@ const RATE_LIMITER_DURATION = APP_CONSOLIDATION_DELAY * 0.1; // 6 seconds (tenth let addQueue; let consolidateQueue; -// GraphQL mutation to insert notifications +// Updated GraphQL mutation to insert notifications with the new schema const INSERT_NOTIFICATIONS_MUTATION = ` mutation INSERT_NOTIFICATIONS($objects: [notifications_insert_input!]!) { insert_notifications(objects: $objects) { @@ -29,61 +29,34 @@ const INSERT_NOTIFICATIONS_MUTATION = ` id jobid associationid - ui_translation_string - ui_translation_meta - html_body + scenario_text + fcm_text + scenario_meta } } } `; /** - * Builds an HTML unordered list from an array of notification bodies. + * Builds the scenario_text, fcm_text, and scenario_meta for a batch of notifications. * - * @param {Array} notifications - Array of notification objects with a 'body' field. - * @returns {string} HTML string representing an unordered list of bodies. + * @param {Array} notifications - Array of notification objects with 'body' and 'variables'. + * @returns {Object} An object with 'scenario_text', 'fcm_text', and 'scenario_meta'. */ -const buildHtmlBody = (notifications) => { - const listItems = notifications.map((n) => `
  • ${n.body}
  • `).join(""); - return `
      ${listItems}
    `; -}; +const buildNotificationContent = (notifications) => { + const scenarioText = notifications.map((n) => n.body); // Array of text entries + const fcmText = scenarioText.join(". "); // Concatenated text with period separator + const scenarioMeta = notifications.map((n) => n.variables || {}); // Array of metadata objects -/** - * Determines the key and variables for a batch of notifications. - * - * @param {Array} notifications - Array of notification objects with 'key' and 'variables'. - * @returns {Object} An object with 'key' and 'variables' properties. - */ -const determineKeyAndVariables = (notifications) => { - if (notifications.length === 1) { - // Single notification: use the original key and variables - return { - key: notifications[0].key, - variables: notifications[0].variables - }; - } else { - // Multiple notifications: use a generic key and consolidate variables with their original keys - return { - key: "notifications.job.multipleChanges", - variables: { - variables: notifications.map((n) => ({ - key: n.key, // Include the original key in each variables object - ...n.variables - })) - } - }; - } + return { + scenario_text: scenarioText, + fcm_text: fcmText ? `${fcmText}.` : null, // Add trailing period if non-empty, otherwise null + scenario_meta: scenarioMeta + }; }; /** * Initializes the notification queues and workers for adding and consolidating notifications. - * - * @param {Object} options - Configuration options for queue initialization. - * @param {Object} options.pubClient - Redis client instance for queue communication. - * @param {Object} options.logger - Logger instance for logging events and debugging. - * @param {Object} options.redisHelpers - Utility functions for Redis operations. - * @param {Object} options.ioRedis - Socket.io Redis adapter for real-time event emission. - * @returns {Queue} The initialized `addQueue` instance for dispatching notifications. */ const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => { if (!addQueue || !consolidateQueue) { @@ -195,14 +168,13 @@ const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => { const employeeId = userRecipients[0]?.employeeId; for (const [bodyShopId, notifications] of Object.entries(bodyShopData)) { - const { key, variables } = determineKeyAndVariables(notifications); - const htmlBody = buildHtmlBody(notifications); + const { scenario_text, fcm_text, scenario_meta } = buildNotificationContent(notifications); notificationInserts.push({ jobid: jobId, associationid: employeeId || null, - ui_translation_string: key, - ui_translation_meta: JSON.stringify(variables), - html_body: htmlBody + scenario_text: JSON.stringify(scenario_text), // JSONB requires stringified input + fcm_text: fcm_text, + scenario_meta: JSON.stringify(scenario_meta) // JSONB requires stringified input }); notificationIdMap.set(`${user}:${bodyShopId}`, null); } @@ -301,9 +273,6 @@ const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => { /** * Retrieves the initialized `addQueue` instance. - * - * @returns {Queue} The `addQueue` instance for adding notifications. - * @throws {Error} If `addQueue` is not initialized (i.e., `loadAppQueue` wasn’t called). */ const getQueue = () => { if (!addQueue) throw new Error("Add queue not initialized. Ensure loadAppQueue is called during bootstrap."); @@ -312,11 +281,6 @@ const getQueue = () => { /** * Dispatches notifications to the `addQueue` for processing. - * - * @param {Object} options - Options for dispatching notifications. - * @param {Array} options.appsToDispatch - Array of notification objects to dispatch. - * @param {Object} options.logger - Logger instance for logging dispatch events. - * @returns {Promise} Resolves when all notifications are added to the queue. */ const dispatchAppsToQueue = async ({ appsToDispatch, logger }) => { const appQueue = getQueue();