Repository: hasura/graphql-engine
File: server/src-lib/Hasura/Server/Init.hs (Haskell)

Code before:
                                withEnv (rsoAdminInternalErrors rso) (fst adminInternalErrorsEnv)
  let internalErrorsConfig =
        if | devMode             -> InternalErrorsAllRequests
           | adminInternalErrors -> InternalErrorsAdminOnly
           | otherwise           -> InternalErrorsDisabled

  eventsHttpPoolSize <- withEnv (rsoEventsHttpPoolSize rso) (fst eventsHttpPoolSizeEnv)
  eventsFetchInterval <- withEnv (rsoEventsFetchInterval rso) (fst eventsFetchIntervalEnv)
  logHeadersFromEnv <- withEnvBool (rsoLogHeadersFromEnv rso) (fst logHeadersFromEnvEnv)

  webSocketCompressionFromEnv <- withEnvBool (rsoWebSocketCompression rso) $
                                 fst webSocketCompressionEnv

  let connectionOptions = WS.defaultConnectionOptions {
                            WS.connectionCompressionOptions =
                              if webSocketCompressionFromEnv
                                then WS.PermessageDeflateCompression WS.defaultPermessageDeflate
                                else WS.NoCompression
                          }
  webSocketKeepAlive <- KeepAliveDelay . Seconds . secondsToDiffTime . fromIntegral . fromMaybe 5
      <$> withEnv (rsoWebSocketKeepAlive rso) (fst webSocketKeepAliveEnv)

    -- maybe
    --   (Just . KeepAliveDelay $ Seconds (secondsToDiffTime 5)) -- default keep-alive interval is 5 seconds
    --   (Just . KeepAliveDelay . Seconds . secondsToDiffTime)
    --   <$> (withEnv (rsoWebSocketKeepAlive rso) (fst webSocketKeepAliveEnv))

  return $ ServeOptions port host connParams txIso adminScrt authHook jwtSecret
                        unAuthRole corsCfg enableConsole consoleAssetsDir
                        enableTelemetry strfyNum enabledAPIs lqOpts enableAL
                        enabledLogs serverLogLevel planCacheOptions
                        internalErrorsConfig eventsHttpPoolSize eventsFetchInterval
                        logHeadersFromEnv connectionOptions webSocketKeepAlive
  where
#ifdef DeveloperAPIs
    defaultAPIs = [METADATA,GRAPHQL,PGDUMP,CONFIG,DEVELOPER]
#else
    defaultAPIs = [METADATA,GRAPHQL,PGDUMP,CONFIG]
#endif
    mkConnParams (RawConnParams s c i cl p) = do
      stripes <- fromMaybe 1 <$> withEnv s (fst pgStripesEnv)
      -- Note: by Little's Law we can expect e.g. (with 50 max connections) a
      -- hard throughput cap at 1000RPS when db queries take 50ms on average:
      conns <- fromMaybe 50 <$> withEnv c (fst pgConnsEnv)
      iTime <- fromMaybe 180 <$> withEnv i (fst pgTimeoutEnv)
      connLifetime <- withEnv cl (fst pgConnLifetimeEnv)
      allowPrepare <- fromMaybe True <$> withEnv p (fst pgUsePrepareEnv)
      return $ Q.ConnParams stripes conns iTime allowPrepare connLifetime

    mkAuthHook (AuthHookG mUrl mType) = do
      mUrlEnv <- withEnv mUrl $ fst authHookEnv

Review comment (suggestion):
Yeah, after a second inspection, I do think the canonical way to get a `Seconds` object is to use the `Num` instance.

```suggestion
  webSocketKeepAlive <- KeepAliveDelay . fromIntegral . fromMaybe 5
      <$> withEnv (rsoWebSocketKeepAlive rso) (fst webSocketKeepAliveEnv)
```

Code after:
                                withEnv (rsoAdminInternalErrors rso) (fst adminInternalErrorsEnv)
  let internalErrorsConfig =
        if | devMode             -> InternalErrorsAllRequests
           | adminInternalErrors -> InternalErrorsAdminOnly
           | otherwise           -> InternalErrorsDisabled

  eventsHttpPoolSize <- withEnv (rsoEventsHttpPoolSize rso) (fst eventsHttpPoolSizeEnv)
  eventsFetchInterval <- withEnv (rsoEventsFetchInterval rso) (fst eventsFetchIntervalEnv)
  logHeadersFromEnv <- withEnvBool (rsoLogHeadersFromEnv rso) (fst logHeadersFromEnvEnv)

  webSocketCompressionFromEnv <- withEnvBool (rsoWebSocketCompression rso) $
                                 fst webSocketCompressionEnv

  let connectionOptions = WS.defaultConnectionOptions {
                            WS.connectionCompressionOptions =
                              if webSocketCompressionFromEnv
                                then WS.PermessageDeflateCompression WS.defaultPermessageDeflate
                                else WS.NoCompression
                          }
  webSocketKeepAlive <- KeepAliveDelay . fromIntegral . fromMaybe 5
      <$> withEnv (rsoWebSocketKeepAlive rso) (fst webSocketKeepAliveEnv)

  return $ ServeOptions port host connParams txIso adminScrt authHook jwtSecret
                        unAuthRole corsCfg enableConsole consoleAssetsDir
                        enableTelemetry strfyNum enabledAPIs lqOpts enableAL
                        enabledLogs serverLogLevel planCacheOptions
                        internalErrorsConfig eventsHttpPoolSize eventsFetchInterval
                        logHeadersFromEnv connectionOptions webSocketKeepAlive
  where
#ifdef DeveloperAPIs
    defaultAPIs = [METADATA,GRAPHQL,PGDUMP,CONFIG,DEVELOPER]
#else
    defaultAPIs = [METADATA,GRAPHQL,PGDUMP,CONFIG]
#endif
    mkConnParams (RawConnParams s c i cl p) = do
      stripes <- fromMaybe 1 <$> withEnv s (fst pgStripesEnv)
      -- Note: by Little's Law we can expect e.g. (with 50 max connections) a
      -- hard throughput cap at 1000RPS when db queries take 50ms on average:
      conns <- fromMaybe 50 <$> withEnv c (fst pgConnsEnv)
      iTime <- fromMaybe 180 <$> withEnv i (fst pgTimeoutEnv)
      connLifetime <- withEnv cl (fst pgConnLifetimeEnv)
      allowPrepare <- fromMaybe True <$> withEnv p (fst pgUsePrepareEnv)
      return $ Q.ConnParams stripes conns iTime allowPrepare connLifetime

    mkAuthHook (AuthHookG mUrl mType) = do
      mUrlEnv <- withEnv mUrl $ fst authHookEnv
      authModeM <- withEnv mType (fst authHookModeEnv)
      ty <- onNothing authModeM (authHookTyEnv mType)
      return (flip AuthHookG ty <$> mUrlEnv)

    -- Also support HASURA_GRAPHQL_AUTH_HOOK_TYPE