-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Monad for allocation and cleanup of application resources
--   
--   This library allows you to allocate resources with clean up strategies
--   when initializing your application. It then provides a Monadic
--   interface to compose multiple resources without having to deal with
--   cleanup operations explicitely.
@package componentm
@version 0.0.0.2

module Control.Monad.Component.Internal.Types

-- | Exception thrown by the <tt>runComponentM</tt> family of functions
data ComponentError

-- | Failure raised when the Application Callback given to a
--   <tt>runComponentM</tt> function throws an exception
ComponentRuntimeFailed :: !SomeException -> !TeardownResult -> ComponentError

-- | Exception that was originally thrown by the Application Callback
[componentErrorOriginalException] :: ComponentError -> !SomeException

-- | Result from the execution allocated resources teardown
[componentErrorTeardownResult] :: ComponentError -> !TeardownResult

-- | Failure raised when execution of <a>ComponentM</a> throws an exception
ComponentBuildFailed :: ![ComponentBuildError] -> !TeardownResult -> ComponentError

-- | Exceptions thrown by <a>IO</a> sub-routines used when constructing
--   <a>ComponentM</a> values (e.g. <tt>buildComponent</tt>)
[componentErrorBuildErrors] :: ComponentError -> ![ComponentBuildError]

-- | Result from the execution allocated resources teardown
[componentErrorTeardownResult] :: ComponentError -> !TeardownResult

-- | Exception raised on the execution of <a>IO</a> sub-routines used when
--   constructing <a>ComponentM</a> values (e.g. <tt>buildComponent</tt>)
data ComponentBuildError

-- | Failure thrown when using the same component key on a Component
--   composition
DuplicatedComponentKeyDetected :: !Description -> ComponentBuildError

-- | Failure thrown when the allocation sub-routine of a Component fails
--   with an exception
ComponentAllocationFailed :: !Description -> !SomeException -> ComponentBuildError

-- | Failure thrown when calling the <a>throwM</a> when composing
--   <a>ComponentM</a> values
ComponentErrorThrown :: !SomeException -> ComponentBuildError

-- | Failure thrown when calling <a>liftIO</a> fails with an exception
ComponentIOLiftFailed :: !SomeException -> ComponentBuildError

-- | Represents the construction of a Component in your application,
--   components may be composed using a <a>Monad</a> or <a>Applicative</a>
--   interface.
newtype ComponentM a
ComponentM :: (IO (Either ([ComponentBuildError], BuildTable) (a, BuildTable))) -> ComponentM a

-- | Contains metadata about the build of a resource from a
--   <a>ComponentM</a> value
data Build
Build :: !Description -> !Teardown -> !NominalDiffTime -> !(Maybe SomeException) -> !(Set Description) -> Build

-- | Name of the component built
[componentDesc] :: Build -> !Description

-- | Cleanup sub-routine of the component built
[componentTeardown] :: Build -> !Teardown

-- | Elasped time in the allocation of a component resource
[buildElapsedTime] :: Build -> !NominalDiffTime

-- | Error thrown in the allocation of a component resource
[buildFailure] :: Build -> !(Maybe SomeException)

-- | What other components this build depends on
[buildDependencies] :: Build -> !(Set Description)

-- | Wraps a collection of <a>Build</a> records
newtype BuildResult
BuildResult :: [Build] -> BuildResult
[toBuildList] :: BuildResult -> [Build]

-- | Result from a <a>Teardown</a> sub-routine
data TeardownResult

-- | An event record used to trace the execution of an application
--   initialization and teardown
data ComponentEvent
ComponentBuilt :: !BuildResult -> ComponentEvent
ComponentReleased :: !TeardownResult -> ComponentEvent
ComponentErrorDetected :: !ComponentError -> ComponentEvent
buildTableToOrderedList :: BuildTable -> [Build]
buildTableToTeardown :: Text -> BuildTable -> IO Teardown
instance GHC.Generics.Generic Control.Monad.Component.Internal.Types.Build
instance GHC.Show.Show Control.Monad.Component.Internal.Types.ComponentError
instance GHC.Generics.Generic Control.Monad.Component.Internal.Types.ComponentError
instance GHC.Show.Show Control.Monad.Component.Internal.Types.ComponentBuildError
instance GHC.Generics.Generic Control.Monad.Component.Internal.Types.ComponentBuildError
instance GHC.Base.Functor Control.Monad.Component.Internal.Types.ComponentM
instance GHC.Base.Applicative Control.Monad.Component.Internal.Types.ComponentM
instance GHC.Base.Monad Control.Monad.Component.Internal.Types.ComponentM
instance Control.Monad.Catch.MonadThrow Control.Monad.Component.Internal.Types.ComponentM
instance Control.Monad.IO.Class.MonadIO Control.Monad.Component.Internal.Types.ComponentM
instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Monad.Component.Internal.Types.ComponentEvent
instance RIO.Prelude.Display.Display Control.Monad.Component.Internal.Types.ComponentEvent
instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Monad.Component.Internal.Types.BuildResult
instance RIO.Prelude.Display.Display Control.Monad.Component.Internal.Types.BuildResult
instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Monad.Component.Internal.Types.Build
instance RIO.Prelude.Display.Display Control.Monad.Component.Internal.Types.Build
instance GHC.Exception.Exception Control.Monad.Component.Internal.Types.ComponentError
instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Monad.Component.Internal.Types.ComponentError
instance GHC.Exception.Exception Control.Monad.Component.Internal.Types.ComponentBuildError
instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Monad.Component.Internal.Types.ComponentBuildError

module Control.Monad.Component.Internal.Core

-- | Use this function when you want to allocate a new resource (e.g.
--   Database, Socket, etc). It registers the constructed resource in your
--   application component tree and guarantees that its cleanup sub-routine
--   is executed at the end of your program.
--   
--   This function is similar to the <a>bracket</a> function with the
--   caveat that it expects a <a>Text</a> argument which identifies the
--   component being allocated.
--   
--   NOTE: The name of your component must be unique; otherwise a
--   <a>DuplicatedComponentKeyDetected</a> will be thrown
buildComponent :: Text -> IO a -> (a -> IO ()) -> ComponentM a

-- | Transforms an <a>IO</a> sub-routine into a <a>ComponentM</a>
--   sub-routine; the given <a>IO</a> sub-routine returns a resource that
--   does not allocate any other resources that would need to be cleaned up
--   on a system shutdown.
--   
--   This is similar to using <a>liftIO</a>, with the caveat that the
--   library will register the given <a>IO</a> sub-routine as a Component,
--   and it will keep track and report its initialization timespan
buildComponent_ :: Text -> IO a -> ComponentM a

-- | Constructs the <i>environment</i> of your application by executing the
--   <a>IO</a> sub-routines provided in the <a>buildComponent</a> and
--   <a>buildComponent_</a> functions; it then executes a callback where
--   your main application will run.
--   
--   This function:
--   
--   <ul>
--   <li>Keeps track of initialization elapsed time for each component of
--   your application</li>
--   <li>Initializes components concurrently as long as they are composed
--   using <a>Applicative</a> functions</li>
--   <li>Builds a graph of your dependencies automatically when composing
--   your <a>ComponentM</a> values via <a>Applicative</a> or <a>Monad</a>
--   interfaces; it then guarantees the execution of cleanup operations in
--   a topological sorted order</li>
--   <li>Guarantees the proper cleanup of previously allocated resources if
--   the creation of a resource throws an exception on initialization</li>
--   <li>Guarantees best-effort cleanup of resources on application
--   teardown in the scenario where a cleanup sub-routine throws an
--   exception</li>
--   <li>Keeps track of teardown elasped time for each component of your
--   application; and reports what exceptions was thrown in case of
--   failures</li>
--   </ul>
--   
--   If you want to trace the behavior of your application on
--   initialization and teardown, use <a>runComponentM1</a> instead
runComponentM :: Text -> ComponentM a -> (a -> IO b) -> IO b

-- | Enhances <a>runComponentM</a> with a callback function that emits
--   <a>ComponentEvent</a> records. These events are a great way of tracing
--   the lifecycle and structure of your application.
runComponentM1 :: (ComponentEvent -> IO ()) -> Text -> ComponentM a -> (a -> IO b) -> IO b


-- | <h1>Why use <a>ComponentM</a>?</h1>
--   
--   <a>ComponentM</a> values wraps vanilla <tt>IO</tt> sub-routines whose
--   responsibility is to allocate resources that your application may need
--   (e.g. database connections, tcp sockets, etc). Your program will
--   execute these <a>ComponentM</a> sub-routines at the beginning of it's
--   lifecyle, building an environment that your main application needs in
--   order to work as intended.
--   
--   By using <a>ComponentM</a> sub-routines your program will
--   automatically:
--   
--   <ul>
--   <li>Compose the cleanup sub-routines of all your allocated
--   resources</li>
--   <li>Keep track of initialization time for each resource needed in your
--   application</li>
--   <li>Keep track of teardown time for each resources needed in your
--   application.</li>
--   <li>Isolate the teardown of each resource in your application,
--   ensuring no thrown exception will affect the cleanup of
--   resources.</li>
--   <li>Initialize resources concurrently when using <tt>Applicative</tt>
--   notation</li>
--   <li>Build a dependency graph of your application resources when using
--   <tt>Applicative</tt> or <tt>Monad</tt> notation; and then guarantees
--   the execution of cleanup operations in a topological sorted order</li>
--   <li>Make sure that previously allocated resources are cleaned up when
--   a resource throws an exception on initialization</li>
--   <li>Report all exceptions thrown on each resource teardown</li>
--   <li>Document (through types) what is the purpose of some of the
--   <tt>IO</tt> sub-routines in your program</li>
--   </ul>
--   
--   These properties are crucial when applications need to run for long
--   periods of time and they are reloaded (without a process restart). It
--   also ensures that resources are cleaned tightly when doing REPL driven
--   development through GHCi.
module Control.Monad.Component

-- | Use this function when you want to allocate a new resource (e.g.
--   Database, Socket, etc). It registers the constructed resource in your
--   application component tree and guarantees that its cleanup sub-routine
--   is executed at the end of your program.
--   
--   This function is similar to the <a>bracket</a> function with the
--   caveat that it expects a <a>Text</a> argument which identifies the
--   component being allocated.
--   
--   NOTE: The name of your component must be unique; otherwise a
--   <a>DuplicatedComponentKeyDetected</a> will be thrown
buildComponent :: Text -> IO a -> (a -> IO ()) -> ComponentM a

-- | Transforms an <a>IO</a> sub-routine into a <a>ComponentM</a>
--   sub-routine; the given <a>IO</a> sub-routine returns a resource that
--   does not allocate any other resources that would need to be cleaned up
--   on a system shutdown.
--   
--   This is similar to using <a>liftIO</a>, with the caveat that the
--   library will register the given <a>IO</a> sub-routine as a Component,
--   and it will keep track and report its initialization timespan
buildComponent_ :: Text -> IO a -> ComponentM a

-- | Represents the construction of a Component in your application,
--   components may be composed using a <a>Monad</a> or <a>Applicative</a>
--   interface.
data ComponentM a

-- | Constructs the <i>environment</i> of your application by executing the
--   <a>IO</a> sub-routines provided in the <a>buildComponent</a> and
--   <a>buildComponent_</a> functions; it then executes a callback where
--   your main application will run.
--   
--   This function:
--   
--   <ul>
--   <li>Keeps track of initialization elapsed time for each component of
--   your application</li>
--   <li>Initializes components concurrently as long as they are composed
--   using <a>Applicative</a> functions</li>
--   <li>Builds a graph of your dependencies automatically when composing
--   your <a>ComponentM</a> values via <a>Applicative</a> or <a>Monad</a>
--   interfaces; it then guarantees the execution of cleanup operations in
--   a topological sorted order</li>
--   <li>Guarantees the proper cleanup of previously allocated resources if
--   the creation of a resource throws an exception on initialization</li>
--   <li>Guarantees best-effort cleanup of resources on application
--   teardown in the scenario where a cleanup sub-routine throws an
--   exception</li>
--   <li>Keeps track of teardown elasped time for each component of your
--   application; and reports what exceptions was thrown in case of
--   failures</li>
--   </ul>
--   
--   If you want to trace the behavior of your application on
--   initialization and teardown, use <a>runComponentM1</a> instead
runComponentM :: Text -> ComponentM a -> (a -> IO b) -> IO b

-- | Enhances <a>runComponentM</a> with a callback function that emits
--   <a>ComponentEvent</a> records. These events are a great way of tracing
--   the lifecycle and structure of your application.
runComponentM1 :: (ComponentEvent -> IO ()) -> Text -> ComponentM a -> (a -> IO b) -> IO b

-- | Exception thrown by the <tt>runComponentM</tt> family of functions
data ComponentError

-- | Failure raised when the Application Callback given to a
--   <tt>runComponentM</tt> function throws an exception
ComponentRuntimeFailed :: !SomeException -> !TeardownResult -> ComponentError

-- | Exception that was originally thrown by the Application Callback
[componentErrorOriginalException] :: ComponentError -> !SomeException

-- | Result from the execution allocated resources teardown
[componentErrorTeardownResult] :: ComponentError -> !TeardownResult

-- | Failure raised when execution of <a>ComponentM</a> throws an exception
ComponentBuildFailed :: ![ComponentBuildError] -> !TeardownResult -> ComponentError

-- | Exceptions thrown by <a>IO</a> sub-routines used when constructing
--   <a>ComponentM</a> values (e.g. <tt>buildComponent</tt>)
[componentErrorBuildErrors] :: ComponentError -> ![ComponentBuildError]

-- | Result from the execution allocated resources teardown
[componentErrorTeardownResult] :: ComponentError -> !TeardownResult

-- | Exception raised on the execution of <a>IO</a> sub-routines used when
--   constructing <a>ComponentM</a> values (e.g. <tt>buildComponent</tt>)
data ComponentBuildError

-- | Failure thrown when using the same component key on a Component
--   composition
DuplicatedComponentKeyDetected :: !Description -> ComponentBuildError

-- | Failure thrown when the allocation sub-routine of a Component fails
--   with an exception
ComponentAllocationFailed :: !Description -> !SomeException -> ComponentBuildError

-- | Failure thrown when calling the <a>throwM</a> when composing
--   <a>ComponentM</a> values
ComponentErrorThrown :: !SomeException -> ComponentBuildError

-- | Failure thrown when calling <a>liftIO</a> fails with an exception
ComponentIOLiftFailed :: !SomeException -> ComponentBuildError

-- | An event record used to trace the execution of an application
--   initialization and teardown
data ComponentEvent
ComponentBuilt :: !BuildResult -> ComponentEvent
ComponentReleased :: !TeardownResult -> ComponentEvent
ComponentErrorDetected :: !ComponentError -> ComponentEvent

-- | Contains metadata about the build of a resource from a
--   <a>ComponentM</a> value
data Build

-- | Elasped time in the allocation of a component resource
buildElapsedTime :: Build -> NominalDiffTime

-- | Error thrown in the allocation of a component resource
buildFailure :: Build -> (Maybe SomeException)

-- | Wraps a collection of <a>Build</a> records
data BuildResult
toBuildList :: BuildResult -> [Build]

-- | Result from a <a>Teardown</a> sub-routine
data TeardownResult

-- | Result is composed by multiple teardown sub-routines
BranchResult :: !Description -> !NominalDiffTime -> !Bool -> ![TeardownResult] -> TeardownResult

-- | Text description of parent teardown spec
[resultDescription] :: TeardownResult -> !Description

-- | Sum of elapsed time on sub-routines execution
[resultElapsedTime] :: TeardownResult -> !NominalDiffTime

-- | Tells if any sub-routines failed
[resultDidFail] :: TeardownResult -> !Bool

-- | Results of inner sub-routines
[resultListing] :: TeardownResult -> ![TeardownResult]

-- | Result represents a single teardown sub-routine
LeafResult :: !Description -> !NominalDiffTime -> !Maybe SomeException -> TeardownResult

-- | Text description of parent teardown spec
[resultDescription] :: TeardownResult -> !Description

-- | Sum of elapsed time on sub-routines execution
[resultElapsedTime] :: TeardownResult -> !NominalDiffTime

-- | Exception from sub-routine
[resultError] :: TeardownResult -> !Maybe SomeException

-- | Represents a stub cleanup operation (for lifting pure values)
EmptyResult :: !Description -> TeardownResult

-- | Text description of parent teardown spec
[resultDescription] :: TeardownResult -> !Description

-- | Throw an exception. Note that this throws when this action is run in
--   the monad <tt>m</tt>, not when it is applied. It is a generalization
--   of <a>Control.Exception</a>'s <a>throwIO</a>.
--   
--   Should satisfy the law:
--   
--   <pre>
--   throwM e &gt;&gt; f = throwM e
--   </pre>
throwM :: (MonadThrow m, Exception e) => e -> m a
