Repository: hasura/graphql-engine
File: server/src-lib/Hasura/GraphQL/Transport/WebSocket.hs (Haskell)

Code before:
    E.GExPRemote rsi opDef  ->
      runRemoteGQ execCtx requestId userInfo reqHdrs opDef rsi
  where
    runHasuraGQ :: RequestId -> GQLReqUnparsed -> UserInfo -> E.ExecOp
                -> ExceptT () IO ()
    runHasuraGQ reqId query userInfo = \case
      E.ExOpQuery opTx genSql ->
        execQueryOrMut reqId query genSql $ runLazyTx' pgExecCtx opTx
      E.ExOpMutation opTx ->
        execQueryOrMut reqId query Nothing $
          runLazyTx pgExecCtx Q.ReadWrite $ withUserInfo userInfo opTx
      E.ExOpSubs lqOp -> do
        -- log the graphql query
        L.unLogger logger $ QueryLog query Nothing reqId
        lqId <- liftIO $ LQ.addLiveQuery lqMap lqOp liveQOnChange
        liftIO $ STM.atomically $
          STMMap.insert (lqId, _grOperationName q) opId opMap
        logOpEv ODStarted (Just reqId)

    execQueryOrMut reqId query genSql action = do
      logOpEv ODStarted (Just reqId)
      -- log the generated SQL and the graphql query
      L.unLogger logger $ QueryLog query genSql reqId
      t1 <- liftIO TC.getCurrentTime -- for measuring response time purposes
      resp <- liftIO $ runExceptT action
      t2 <- liftIO TC.getCurrentTime -- for measuring response time purposes
      let ocMeta = LQ.LiveQueryMetadata $ Just $ realToFrac $ TC.diffUTCTime t2 t1
      either (postExecErr reqId) (`sendSuccResp` ocMeta) resp
      sendCompleted (Just reqId)

    runRemoteGQ :: E.ExecutionCtx -> RequestId -> UserInfo -> [H.Header]
                -> G.TypedOperationDefinition -> RemoteSchemaInfo
                -> ExceptT () IO ()
    runRemoteGQ execCtx reqId userInfo reqHdrs opDef rsi = do
      when (G._todType opDef == G.OperationTypeSubscription) $
        withComplete $ preExecErr reqId $
        err400 NotSupported "subscription to remote server is not supported"

      -- if it's not a subscription, use HTTP to execute the query on the remote
      t1 <- liftIO TC.getCurrentTime -- for measuring response time purposes
      resp <- runExceptT $ flip runReaderT execCtx $
              E.execRemoteGQ reqId userInfo reqHdrs q rsi opDef
      t2 <- liftIO TC.getCurrentTime -- for measuring response time purposes
      let ocMeta = LQ.LiveQueryMetadata $ Just $ realToFrac $ TC.diffUTCTime t2 t1
      either (postExecErr reqId) (\val -> sendRemoteResp reqId (_hrBody val) ocMeta) resp
      sendCompleted (Just reqId)

    sendRemoteResp reqId resp meta =
      case J.eitherDecodeStrict (encJToBS resp) of
        Left e    -> postExecErr reqId $ invalidGqlErr $ T.pack e
        Right res -> sendMsgWithMetadata wsConn (SMData $ DataMsg opId $ GRRemote res) meta

Review comment (refactor):
It might be worth extracting this pattern into a helper function with a type like this:

```haskell
withElapsedTime :: MonadIO m => m a -> m (DiffTime, a)
```

Code after:
    E.GExPRemote rsi opDef  ->
      runRemoteGQ execCtx requestId userInfo reqHdrs opDef rsi
  where
    runHasuraGQ :: RequestId -> GQLReqUnparsed -> UserInfo -> E.ExecOp
                -> ExceptT () IO ()
    runHasuraGQ reqId query userInfo = \case
      E.ExOpQuery opTx genSql ->
        execQueryOrMut reqId query genSql $ runLazyTx' pgExecCtx opTx
      E.ExOpMutation opTx ->
        execQueryOrMut reqId query Nothing $
          runLazyTx pgExecCtx Q.ReadWrite $ withUserInfo userInfo opTx
      E.ExOpSubs lqOp -> do
        -- log the graphql query
        L.unLogger logger $ QueryLog query Nothing reqId
        lqId <- liftIO $ LQ.addLiveQuery lqMap lqOp liveQOnChange
        liftIO $ STM.atomically $
          STMMap.insert (lqId, _grOperationName q) opId opMap
        logOpEv ODStarted (Just reqId)

    execQueryOrMut reqId query genSql action = do
      logOpEv ODStarted (Just reqId)
      -- log the generated SQL and the graphql query
      L.unLogger logger $ QueryLog query genSql reqId
      (dt, resp) <- withElapsedTime $ liftIO $ runExceptT action
      let lqMeta = LQ.LiveQueryMetadata dt
      either (postExecErr reqId) (`sendSuccResp` lqMeta) resp
      sendCompleted (Just reqId)

    runRemoteGQ :: E.ExecutionCtx -> RequestId -> UserInfo -> [H.Header]
                -> G.TypedOperationDefinition -> RemoteSchemaInfo
                -> ExceptT () IO ()
    runRemoteGQ execCtx reqId userInfo reqHdrs opDef rsi = do
      when (G._todType opDef == G.OperationTypeSubscription) $
        withComplete $ preExecErr reqId $
        err400 NotSupported "subscription to remote server is not supported"

      -- if it's not a subscription, use HTTP to execute the query on the remote
      (dt, resp) <- withElapsedTime $ runExceptT $ flip runReaderT execCtx $
              E.execRemoteGQ reqId userInfo reqHdrs q rsi opDef
      let ocMeta = LQ.LiveQueryMetadata dt
      either (postExecErr reqId) (\val -> sendRemoteResp reqId (_hrBody val) ocMeta) resp
      sendCompleted (Just reqId)

    sendRemoteResp reqId resp meta =
      case J.eitherDecodeStrict (encJToBS resp) of
        Left e    -> postExecErr reqId $ invalidGqlErr $ T.pack e
        Right res -> sendMsgWithMetadata wsConn (SMData $ DataMsg opId $ GRRemote res) meta

    invalidGqlErr err = err500 Unexpected $
      "Failed parsing GraphQL response from remote: " <> err