teardown-0.3.0.0: src/Control/Monad/Component/Internal/Core.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Control.Monad.Component.Internal.Core where
import Protolude
import Control.Monad.Component.Internal.Types
import Control.Teardown (Teardown, newTeardown, teardown)
--------------------------------------------------------------------------------
-- | Given the name and a `ComponentM` sub-routine, this function builds an `IO`
-- sub-routine that returns a `Component` record.
--
-- The name argument is used for trace-ability purposes when executing the
-- `teardown` of a resulting `Component`.
--
-- * A note on error scenarios:
--
-- Sometimes the given `ComponentM` sub-routine may fail on execution, in such
-- cases, this function will teardown all component resources allocated so far
-- and throw a `ComponentStartupFailure` exception.
--
runComponentM :: Text -> ComponentM a -> IO (Component a)
runComponentM !appName (ComponentM ma) = do
eResult <- ma
case eResult of
Left (errList, cleanupActions) -> do
appTeardown <- newTeardown appName cleanupActions
-- Cleanup resources allocated so far and throw error
-- list
void $ teardown appTeardown
throwIO (ComponentStartupFailure errList)
Right (a, cleanupActions) -> do
appTeardown <- newTeardown appName cleanupActions
return $! Component a appTeardown
-- | Transforms an `IO` sub-routine into a `ComponentM` sub-routine; the given
-- `IO` sub-routine must return a tuple where:
--
-- * First position represents the resource being returned from
-- the component
--
-- * Second position represents a named cleanup action that tears down
-- allocated resources to create the first element of the tuple
--
buildComponentWithCleanup :: IO (a, (Text, IO ())) -> ComponentM a
buildComponentWithCleanup !ma =
ComponentM $ do
(a, (desc, cleanupAction)) <- ma
teardownAction <- newTeardown desc cleanupAction
return $ Right (a, [teardownAction])
-- | Transforms an `IO` sub-routine into a `ComponentM` sub-routine; the given
-- `IO` sub-routine must return a tuple where:
--
-- * First position represents the resource being returned from
-- the component
--
-- * Second position represents a `Teardown` record that cleans up allocated
-- resources to create the first element of the tuple
--
buildComponentWithTeardown :: IO (a, Teardown) -> ComponentM a
buildComponentWithTeardown !ma =
ComponentM $ (\(a, resourceTeardown) ->
Right (a, [resourceTeardown])) <$> ma
-- | Transforms an `IO` sub-routine into a `ComponentM` sub-routine; the given
-- `IO` sub-routine returns a resource that does not allocate any other
-- resources that would need to be cleaned up on a system shutdown.
--
buildComponent :: IO a -> ComponentM a
buildComponent !ma =
ComponentM $ (\a -> Right (a, [])) <$> ma