content: -- | Some useful functions to work with Data.Acid.
  
  module Serokell.AcidState.Util
         (
           -- | Simple helpers
           exceptStateToUpdate
         , exceptStateToUpdateGeneric
         , readerToQuery
         , stateToUpdate
  
           -- | Utilities
         , createAndDiscardArchive
         , tidyLocalState
         ) where
  
  import           Control.Exception (Exception, throw)
  import           Control.Monad.Except (ExceptT, runExceptT)
  import           Control.Monad.Reader (Reader, asks, runReader)
  import           Control.Monad.State (State, runState, state)
  import           Control.Monad.Trans (MonadIO (liftIO))
  import           Data.Acid (AcidState, Query, Update, createArchive,
                       createCheckpoint)
  import           System.Directory (removeDirectoryRecursive)
  import           System.FilePath ((</>))
  
  readerToQuery :: Reader s a -> Query s a
  readerToQuery = asks . runReader
  
  stateToUpdate :: State s a -> Update s a
  stateToUpdate = state . runState
  
  exceptStateToUpdate
      :: (Exception e)
      => ExceptT e (State s) a -> Update s a
  exceptStateToUpdate = exceptStateToUpdateGeneric id
  
  exceptStateToUpdateGeneric
    :: (Exception exc)
    => (e -> exc) -> ExceptT e (State s) a -> Update s a
  exceptStateToUpdateGeneric toException u =
      state $
      runState $
      do res <- runExceptT u
         either (throw . toException) return res
  
  -- | Archive unnecessary data (see createArchive docs for details) and
  -- discard it. Works for local state.
  createAndDiscardArchive :: MonadIO m => AcidState st -> FilePath -> m ()
  createAndDiscardArchive st path =
      liftIO $ createArchive st >> removeDirectoryRecursive (path </> "Archive")
  
  -- | Apply all updates and remove all data from local state which is
  -- unnecessary for state restoration.
  tidyLocalState :: MonadIO m => AcidState st -> FilePath -> m ()
  tidyLocalState st path =
      liftIO (createCheckpoint st) >> createAndDiscardArchive st path
  