From 4dcfb382a9586afc21ec3d99167a1b92ed15af9e Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 10 Jul 2025 17:27:32 -0400 Subject: [PATCH] feature/IO-3291-Tasks-Notifications: Checkpoint --- .../src/contexts/SocketIO/socketProvider.jsx | 157 +++++------------- 1 file changed, 45 insertions(+), 112 deletions(-) diff --git a/client/src/contexts/SocketIO/socketProvider.jsx b/client/src/contexts/SocketIO/socketProvider.jsx index 33ac756a3..60e2e5c02 100644 --- a/client/src/contexts/SocketIO/socketProvider.jsx +++ b/client/src/contexts/SocketIO/socketProvider.jsx @@ -16,11 +16,6 @@ import { useMutation } from "@apollo/client"; import { useTranslation } from "react-i18next"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { INITIAL_NOTIFICATIONS, SocketContext } from "./useSocket.js"; -import { - QUERY_MY_TASKS_COUNT, - QUERY_TASKS_NO_DUE_DATE_PAGINATED, - QUERY_TASKS_WITH_DUE_DATES -} from "../../graphql/tasks.queries"; const LIMIT = INITIAL_NOTIFICATIONS; @@ -193,123 +188,61 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => { limit: LIMIT, offset: 0 }; - const countVars = { - assigned_to: assignedToId, - bodyshopid: bodyshop?.id - }; - // Helper to update a list in cache locally - const updateListCache = (query, vars, action) => { - // action: 'add' or 'remove' + const whereBase = { + bodyshopid: { _eq: bodyshop?.id }, + assigned_to: { _eq: assignedToId }, + deleted: { _eq: false }, + completed: { _eq: false } + }; + const whereDue = { ...whereBase, due_date: { _is_null: false } }; + const whereNoDue = { ...whereBase, due_date: { _is_null: true } }; + + // Helper to invalidate a cache entry + const invalidateCache = (fieldName, args) => { try { - const current = client.readQuery({ query, variables: vars }); - if (!current) return; // List not loaded yet, skip - - let updatedTasks = [...current.tasks]; - let delta = 0; - - if (action === "remove") { - const prevLength = updatedTasks.length; - updatedTasks = updatedTasks.filter((task) => task.id !== payload.id); - if (updatedTasks.length < prevLength) delta -= 1; - } - - if (action === "add") { - const exists = updatedTasks.some((task) => task.id === payload.id); - if (!exists) { - const newTask = { ...payload, __typename: "tasks" }; - updatedTasks.push(newTask); - delta += 1; - } - } - - // Sort the array based on the query type if delta !== 0 - if (delta !== 0) { - if (query === QUERY_TASKS_WITH_DUE_DATES) { - updatedTasks.sort((a, b) => { - const da = new Date(a.due_date); - const db = new Date(b.due_date); - if (da < db) return -1; - if (da > db) return 1; - const ca = new Date(a.created_at); - const cb = new Date(b.created_at); - return cb - ca; // desc - }); - } else if (query === QUERY_TASKS_NO_DUE_DATE_PAGINATED) { - updatedTasks.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); - } - } - - let data = { ...current, tasks: updatedTasks }; - - // Adjust aggregate count for no due date query - if (query === QUERY_TASKS_NO_DUE_DATE_PAGINATED && delta !== 0 && current.tasks_aggregate) { - const newCount = Math.max(0, current.tasks_aggregate.aggregate.count + delta); - data = { - ...data, - tasks_aggregate: { - ...current.tasks_aggregate, - aggregate: { - ...current.tasks_aggregate.aggregate, - count: newCount - } - } - }; - } - - client.writeQuery({ query, variables: vars, data }); + client.cache.evict({ + id: "ROOT_QUERY", + fieldName, + args + }); } catch (error) { - console.error("Error updating task list cache:", error); + console.error("Error invalidating cache:", error); } }; - // Update lists based on event type - if (message.type === "task-deleted") { - updateListCache(QUERY_TASKS_WITH_DUE_DATES, dueVars, "remove"); - updateListCache(QUERY_TASKS_NO_DUE_DATE_PAGINATED, noDueVars, "remove"); - } else { - const targetQuery = payload.due_date ? QUERY_TASKS_WITH_DUE_DATES : QUERY_TASKS_NO_DUE_DATE_PAGINATED; - const targetVars = payload.due_date ? dueVars : noDueVars; - - if (message.type === "task-updated") { - // Remove from both in case of due_date change - updateListCache(QUERY_TASKS_WITH_DUE_DATES, dueVars, "remove"); - updateListCache(QUERY_TASKS_NO_DUE_DATE_PAGINATED, noDueVars, "remove"); + // Invalidate lists and aggregates based on event type + if (message.type === "task-deleted" || message.type === "task-updated") { + // Invalidate both lists and no due aggregate for deletes and updates + invalidateCache("tasks", { where: whereDue, order_by: dueVars.order }); + invalidateCache("tasks", { + where: whereNoDue, + order_by: noDueVars.order, + limit: noDueVars.limit, + offset: noDueVars.offset + }); + invalidateCache("tasks_aggregate", { where: whereNoDue }); + } else if (message.type === "task-created") { + // For creates, invalidate the target list and no due aggregate if applicable + const hasDue = !!payload.due_date; + if (hasDue) { + invalidateCache("tasks", { where: whereDue, order_by: dueVars.order }); + } else { + invalidateCache("tasks", { + where: whereNoDue, + order_by: noDueVars.order, + limit: noDueVars.limit, + offset: noDueVars.offset + }); + invalidateCache("tasks_aggregate", { where: whereNoDue }); } - - // Add to the target list - updateListCache(targetQuery, targetVars, "add"); } - // Locally update the total count (no network call) - try { - const currentCountQuery = client.readQuery({ query: QUERY_MY_TASKS_COUNT, variables: countVars }); - if (currentCountQuery) { - let countDelta = 0; - if (message.type === "task-created") countDelta = 1; - else if (message.type === "task-deleted") countDelta = -1; - // For "task-updated", assume no change to count unless specific logic (e.g., completion) + // Always invalidate the total count for all events (handles creates, deletes, updates including completions) + invalidateCache("tasks_aggregate", { where: whereBase }); - if (countDelta !== 0) { - const newCount = Math.max(0, currentCountQuery.tasks_aggregate.aggregate.count + countDelta); - client.writeQuery({ - query: QUERY_MY_TASKS_COUNT, - variables: countVars, - data: { - tasks_aggregate: { - __typename: "tasks_aggregate", - aggregate: { - __typename: "tasks_aggregate_fields", - count: newCount - } - } - } - }); - } - } - } catch (error) { - console.error("Error updating task count cache:", error); - } + // Garbage collect after evictions + client.cache.gc(); break; default: