packages feed

ngx-export-tools-1.0: NgxExport/Tools/System.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  NgxExport.Tools.System
-- Copyright   :  (c) Alexey Radkov 2018-2022
-- License     :  BSD-style
--
-- Maintainer  :  alexey.radkov@gmail.com
-- Stability   :  stable
-- Portability :  non-portable (requires POSIX)
--
-----------------------------------------------------------------------------


module NgxExport.Tools.System (
    -- * Various functions to access low-level Nginx API
    -- $description

    -- * Exported functions
                               terminateWorkerProcess
                              ,restartWorkerProcess
                              ,finalizeHTTPRequest
                              ,workerProcessIsExiting
                              ,ngxRequestPtr
                              ,ngxNow
                              ,ngxPid
                              ) where

import           NgxExport

import           Foreign.Ptr
import           Foreign.Storable
import           Foreign.C.Types
import           Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as L
import           Data.Binary.Get
import           Data.Maybe
import           Control.Exception
import           System.Posix.Types

-- $description
--
-- Various functions to access low-level Nginx API, mostly wrappers around
-- corresponding functions and data from module "NgxExport".

-- | Terminates the Nginx worker process from a Haskell service.
--
-- Nginx master process shall /not/ spawn a new worker process thereafter. This
-- function throws exception 'TerminateWorkerProcess', and therefore terminates
-- the worker process effectively only from a Haskell service.
terminateWorkerProcess :: String -> IO ()
terminateWorkerProcess = throwIO . TerminateWorkerProcess

-- | Restarts the Nginx worker process from a Haskell service.
--
-- Nginx master process shall spawn a new worker process after termination of
-- the current one. This function throws exception 'RestartWorkerProcess', and
-- therefore terminates the worker process effectively only from a Haskell
-- service.
restartWorkerProcess :: String -> IO ()
restartWorkerProcess = throwIO . RestartWorkerProcess

-- | Finalizes the current HTTP request from a Haskell asynchronous variable
--   handler.
--
-- This function throws exception 'FinalizeHTTPRequest', and therefore
-- terminates the HTTP request effectively only from a Haskell asynchronous
-- variable handler.
finalizeHTTPRequest :: Int -> Maybe String -> IO ()
finalizeHTTPRequest = (throwIO .) . FinalizeHTTPRequest

-- | Checks that a generic exception is of type 'WorkerProcessIsExiting'.
--
-- This can be useful to check quickly in an exception handler whether a
-- Haskell service has been interrupted because the worker process is exiting.
workerProcessIsExiting :: SomeException -> Bool
workerProcessIsExiting e =
    isJust (fromException e :: Maybe WorkerProcessIsExiting)

-- | Unmarshals the value of Nginx variable __/$_r_ptr/__ into a pointer to
--   the Nginx request object.
--
-- This is safe to use in request-based Haskell handlers such as synchronous
-- and asynchronous tasks and content handlers, but not in services and their
-- derivatives. In /asynchronous/ tasks and content handlers the value must be
-- used as read-only. The value can be passed into a /C plugin/, however, as
-- opposed to usual functions in Nginx C code, it must be tested against the
-- /NULL/ value.
ngxRequestPtr :: ByteString -> Ptr ()
ngxRequestPtr = wordPtrToPtr . fromIntegral . runGet getWordhost . L.fromStrict

-- | Returns the current time as the number of seconds elapsed since the UNIX
--   epoch.
--
-- The value is taken from Nginx core, so no additional system calls get
-- involved. On the other hand, it means that this is only safe to use from
-- an Nginx worker's main thread, i.e. in /synchronous/ Haskell handlers and
-- /service hooks/. Be also aware that this is a small type casting hack:
-- the value is interpreted as being of type @time_t@ while having been
-- actually wrapped in a bigger C struct as its first element.
ngxNow :: IO CTime
ngxNow = ngxCachedTimePtr >>= peek >>= peek . castPtr

-- | Returns the /PID/ of the current worker process cached in Nginx core.
ngxPid :: IO CPid
ngxPid = ngxCachedPid