Browse Source

Maintenance: Desktop view - Add possibility to activate connection over websocket per query.

Dominik Klein 1 month ago
parent
commit
799079495e

+ 3 - 0
app/frontend/shared/components/Form/Form.vue

@@ -1337,6 +1337,9 @@ const initializeFormSchema = () => {
               batch: {
                 active: false,
               },
+              websocket: {
+                active: true,
+              },
             },
             fetchPolicy: 'no-cache',
           },

+ 6 - 14
app/frontend/shared/server/apollo/link.ts

@@ -15,6 +15,7 @@ import errorLink from './link/error.ts'
 import setAuthorizationLink from './link/setAuthorization.ts'
 import testFlagsLink from './link/testFlags.ts'
 import getBatchContext from './utils/getBatchContext.ts'
+import getWebsocketContext from './utils/getWebsocketContext.ts'
 
 import type { Operation } from '@apollo/client/core'
 import type { FragmentDefinitionNode, OperationDefinitionNode } from 'graphql'
@@ -49,19 +50,6 @@ const operationIsLoginLogout = (
   )
 }
 
-// TODO: Maybe we can also add a generic solution with the query context to exclude operation for batching or
-// run operations over websocket.
-const operationIsFormUpdater = (
-  definition: OperationDefinitionNode | FragmentDefinitionNode,
-) => {
-  return !!(
-    definition.kind === 'OperationDefinition' &&
-    definition.operation === 'query' &&
-    definition.name?.value &&
-    definition.name?.value === 'formUpdater'
-  )
-}
-
 const requiresBatchLink = (op: Operation) => {
   if (!enableBatchLink) return false
 
@@ -74,15 +62,19 @@ const httpLink = ApolloLink.split(requiresBatchLink, batchLink, noBatchLink)
 
 const requiresHttpLink = (op: Operation) => {
   const definition = getMainDefinition(op.query)
+
+  const websocketContext = getWebsocketContext(op)
+
   if (!enableQueriesOverWebsocket) {
     // Only subscriptions over websocket.
     return (
       !(
         definition.kind === 'OperationDefinition' &&
         definition.operation === 'subscription'
-      ) && !operationIsFormUpdater(definition)
+      ) && !websocketContext.active
     )
   }
+
   // Everything over websocket except login/logout as that changes cookies.
   return operationIsLoginLogout(definition)
 }

+ 17 - 0
app/frontend/shared/server/apollo/utils/getWebsocketContext.ts

@@ -0,0 +1,17 @@
+// Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
+
+import type { ClientWebsocketContext } from '#shared/types/server/apollo/client.ts'
+
+import type { Operation } from '@apollo/client/core'
+
+export default function getBatchContext(
+  operation: Operation,
+): ClientWebsocketContext {
+  const defaultWebsocketContext: ClientWebsocketContext = {
+    active: false,
+  }
+  const context = operation.getContext()
+  const websocket: Partial<ClientWebsocketContext> = context.websocket || {}
+
+  return Object.assign(defaultWebsocketContext, websocket)
+}

+ 4 - 0
app/frontend/shared/types/server/apollo/client.ts

@@ -20,6 +20,10 @@ export interface ClientBatchContext {
   active: boolean
 }
 
+export interface ClientWebsocketContext {
+  active: boolean
+}
+
 export interface DebugLinkRequestOutput {
   requestHeaders?: Record<string, string>
   printedDocument: string