-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Workflows with arrows -- -- An arrow with resumable computations and logging @package funflow @version 1.3.2 -- | Various varieties of free arrow constructions. -- -- For all of these constructions, there are only two important -- functions: - eval evaluates the free arrow in the context of -- another arrow. - effect lifts the underlying effect into the -- arrow. -- -- The class FreeArrowLike, which is not exported from this -- module, exists to allow these to be defined generally. -- -- This module also defines some arrow combinators which are not exposed -- by the standard arrow library. module Control.Arrow.Free -- | Freely generated arrows over an effect. data Free eff a b -- | Freely generated ArrowChoice over an effect. data Choice eff a b -- | Freely generated arrows with both choice and error handling. data ErrorChoice ex eff a b effect :: FreeArrowLike fal => eff a b -> fal eff a b eval :: forall eff arr a b. (FreeArrowLike fal, ((Ctx fal) arr)) => (eff ~> arr) -> fal eff a b -> arr a b -- | ArrowError represents those arrows which can catch exceptions within -- the processing of the flow. class ArrowError ex a catch :: ArrowError ex a => a e c -> a (e, ex) c -> a e c -- | Map an arrow over a list. mapA :: ArrowChoice a => a b c -> a [b] [c] -- | Map an arrow over a list, forcing sequencing between each element. mapSeqA :: ArrowChoice a => a b c -> a [b] [c] -- | Filter a list given an arrow filter filterA :: ArrowChoice a => a b Bool -> a [b] [b] -- | A natural transformation on type constructors of two arguments. type x ~> y = forall a b. x a b -> y a b instance Control.Category.Category (Control.Arrow.Free.ErrorChoice ex eff) instance Control.Arrow.Arrow (Control.Arrow.Free.ErrorChoice ex eff) instance Control.Arrow.ArrowChoice (Control.Arrow.Free.ErrorChoice ex eff) instance Control.Arrow.Free.ArrowError ex (Control.Arrow.Free.ErrorChoice ex eff) instance Control.Arrow.Free.FreeArrowLike (Control.Arrow.Free.ErrorChoice ex) instance (Control.Arrow.Arrow (Control.Arrow.Kleisli m), GHC.Exception.Exception ex, Control.Monad.Catch.MonadCatch m) => Control.Arrow.Free.ArrowError ex (Control.Arrow.Kleisli m) instance Control.Category.Category (Control.Arrow.Free.Choice eff) instance Control.Arrow.Arrow (Control.Arrow.Free.Choice eff) instance Control.Arrow.ArrowChoice (Control.Arrow.Free.Choice eff) instance Control.Arrow.Free.FreeArrowLike Control.Arrow.Free.Choice instance Control.Category.Category (Control.Arrow.Free.Free eff) instance Control.Arrow.Arrow (Control.Arrow.Free.Free eff) instance Control.Arrow.Free.FreeArrowLike Control.Arrow.Free.Free instance forall k (a :: k -> GHC.Types.Constraint) (x :: k) (b :: k -> GHC.Types.Constraint). (a x, b x) => Control.Arrow.Free.Join a b x -- | Asynchronous arrows over monads with MonadBaseControl IO, using -- lifted-async. module Control.Arrow.Async newtype AsyncA m a b AsyncA :: a -> m b -> AsyncA m a b [runAsyncA] :: AsyncA m a b -> a -> m b -- | Lift an AsyncA through a monad transformer of the underlying monad. liftAsyncA :: (MonadTrans t, Monad m) => AsyncA m i o -> AsyncA (t m) i o instance GHC.Base.Monad m => Control.Category.Category (Control.Arrow.Async.AsyncA m) instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Arrow.Arrow (Control.Arrow.Async.AsyncA m) instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Arrow.ArrowChoice (Control.Arrow.Async.AsyncA m) instance (GHC.Exception.Exception ex, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m, Control.Monad.Catch.MonadCatch m) => Control.Arrow.Free.ArrowError ex (Control.Arrow.Async.AsyncA m) -- | A Diagram is a representation of an arrow with labels. No computation -- is actually performed by a diagram, it just carries around a -- description. We explot the fact that in 7.10, everything is typeable -- to label the incoming and outgoing node types. module Control.Funflow.Diagram newtype NodeProperties NodeProperties :: [Text] -> NodeProperties [labels] :: NodeProperties -> [Text] emptyNodeProperties :: NodeProperties data Diagram ex a b [Node] :: NodeProperties -> Proxy a -> Proxy b -> Diagram ex a b [Seq] :: Diagram ex a b -> Diagram ex b c -> Diagram ex a c [Par] :: Diagram ex a b -> Diagram ex c d -> Diagram ex (a, c) (b, d) [Fanin] :: Diagram ex a c -> Diagram ex b c -> Diagram ex (Either a b) c [Catch] :: Diagram ex a b -> Diagram ex (a, ex) b -> Diagram ex a b -- | Construct a labelled node node :: forall arr a b ex. Arrow arr => arr a b -> [Text] -> (Diagram ex) a b instance Control.Category.Category (Control.Funflow.Diagram.Diagram ex) instance Control.Arrow.Arrow (Control.Funflow.Diagram.Diagram ex) instance Control.Arrow.ArrowChoice (Control.Funflow.Diagram.Diagram ex) instance Control.Arrow.Free.ArrowError ex (Control.Funflow.Diagram.Diagram ex) -- | Thread and process write lock. -- -- Allows synchronisation between threads and processes. Uses an -- MVar for synchronisation between threads and fcntl write locks -- for synchronisation between processes. -- -- Only ever have one Lock object per lock file per process! module Control.Funflow.Lock -- | Thread and process write lock. -- -- Only ever have one Lock object per lock file per process! data Lock -- | Open the lock file and create a lock object. -- -- This does not acquire the lock. -- -- Only ever have one Lock object per lock file per process! openLock :: Path Abs Dir -> IO Lock -- | Close the lock file. -- -- Does not release the lock. -- -- Blocks if the lock is taken. closeLock :: Lock -> IO () -- | Acquire the lock for the duration of the given action and release -- after. withLock :: Lock -> IO a -> IO a -- | Dedicated module for orphan instances. module Control.Funflow.Orphans instance Data.Store.Impl.Store (Path.Internal.Path Path.Abs Path.File) instance Data.Store.Impl.Store (Path.Internal.Path Path.Abs Path.Dir) instance Data.Store.Impl.Store (Path.Internal.Path Path.Rel Path.File) instance Data.Store.Impl.Store (Path.Internal.Path Path.Rel Path.Dir) -- | ContentHashable provides a hashing function suitable for use in -- the Funflow content store. -- -- This behaves as does a normal hashing function on Haskell types. -- However, on path types, this instead calculates a hash based on the -- contents of the file or directory referenced. -- -- We also export the ExternallyAssuredFile and -- ExternallyAssuredDirectory types. These instead use the path, -- file size and modification time to control the hash. module Control.Funflow.ContentHashable data ContentHash toBytes :: ContentHash -> ByteString fromBytes :: ByteString -> Maybe ContentHash class Monad m => ContentHashable m a -- | Update a hash context based on the given value. -- -- See hashUpdate. -- -- XXX: Consider swapping the arguments. contentHashUpdate :: ContentHashable m a => Context SHA256 -> a -> m (Context SHA256) -- | Update a hash context based on the given value. -- -- See hashUpdate. -- -- XXX: Consider swapping the arguments. contentHashUpdate :: (ContentHashable m a, Generic a, GContentHashable m (Rep a)) => Context SHA256 -> a -> m (Context SHA256) -- | Generate hash of the given value. -- -- See hash. contentHash :: ContentHashable m a => a -> m ContentHash -- | Update hash context based on binary contents of the given file. contentHashUpdate_binaryFile :: Context SHA256 -> FilePath -> IO (Context SHA256) -- | Update hash context based on ByteArray# by copying into a newly -- allocated Bytes and updating the hash context from there. -- -- XXX: byteArrayContents# :: ByteArray# -> -- Addr# could be used together with MemView instead. -- However, byteArrayContents# explicitly says, that it is only -- safe to use on a pinned ByteArray#. contentHashUpdate_byteArray# :: ByteArray# -> Int -> Int -> Context SHA256 -> Context SHA256 -- | Update hash context based on a type's Fingerprint. -- -- The fingerprint is constructed from the library-name, module-name, and -- name of the type itself. contentHashUpdate_fingerprint :: (Monad m, Typeable a) => Context SHA256 -> a -> m (Context SHA256) -- | Update hash context by combining contentHashUpdate_fingerprint -- and contentHashUpdate_storable. Intended for primitive types -- like Int. contentHashUpdate_primitive :: (Monad m, Typeable a, Storable a) => Context SHA256 -> a -> m (Context SHA256) -- | Update hash context based on binary in memory representation due to -- Storable. -- -- XXX: Do we need to worry about endianness? contentHashUpdate_storable :: (Monad m, Storable a) => Context SHA256 -> a -> m (Context SHA256) -- | Path to a regular file -- -- Only the file's content and its executable permission is taken into -- account when generating the content hash. The path itself is ignored. newtype FileContent FileContent :: (Path Abs File) -> FileContent -- | Path to a directory -- -- Only the contents of the directory and their path relative to the -- directory are taken into account when generating the content hash. The -- path to the directory is ignored. newtype DirectoryContent DirectoryContent :: (Path Abs Dir) -> DirectoryContent -- | Path to a file to be treated as _externally assured_. -- -- An externally assured file is handled in a somewhat cheating -- way by funflow. The ContentHashable instance for such assumes -- that some external agent guarantees the integrity of the file being -- referenced. Thus, rather than hashing the file contents, we only -- consider its (absolute) path, size and modification time, which can be -- rapidly looked up from filesystem metadata. -- -- For a similar approach, see the instance for ObjectInBucket -- in Control.Funflow.AWS.S3, where we exploit the fact that S3 is -- already content hashed to avoid performing any hashing. newtype ExternallyAssuredFile ExternallyAssuredFile :: (Path Abs File) -> ExternallyAssuredFile -- | Path to a directory to be treated as _externally assured_. -- -- For an externally assured directory, we _do_ traverse its contents and -- verify those as we would externally assured files, rather than just -- relying on the directory path. Doing this traversal is pretty cheap, -- and it's quite likely for directory contents to be modified without -- modifying the contents. -- -- If an item in the directory cannot be read due to lacking permissions, -- then it will be ignored and not included in the hash. If the flow does -- not have permissions to access the contents of a subdirectory, then -- these contents cannot influence the outcome of a task and it is okay -- to exclude them from the hash. In that case we only hash the name, as -- that could influence the outcome of a task. newtype ExternallyAssuredDirectory ExternallyAssuredDirectory :: (Path Abs Dir) -> ExternallyAssuredDirectory -- | File path appropriate encoding of a hash encodeHash :: ContentHash -> ByteString -- | Inverse of encodeHash if given a valid input. -- --
--   decodeHash (encodeHash x) = Just x
--   
decodeHash :: ByteString -> Maybe ContentHash -- | File path appropriate encoding of a hash hashToPath :: ContentHash -> Path Rel Dir -- | Inverse of hashToPath if given a valid input. -- --
--   pathToHash (hashToPath x) = Just x
--   
pathToHash :: FilePath -> Maybe ContentHash -- | SHA256 cryptographic hash algorithm data SHA256 -- | Represent a context for a given hash algorithm. data Context a -- | Represent a digest for a given hash algorithm. -- -- This type is an instance of ByteArrayAccess from package -- memory. Module Data.ByteArray provides many primitives -- to work with those values including conversion to other types. -- -- Creating a digest from a bytearray is also possible with function -- digestFromByteString. data Digest a instance GHC.Show.Show Control.Funflow.ContentHashable.ExternallyAssuredDirectory instance GHC.Generics.Generic Control.Funflow.ContentHashable.ExternallyAssuredDirectory instance GHC.Show.Show Control.Funflow.ContentHashable.ExternallyAssuredFile instance GHC.Generics.Generic Control.Funflow.ContentHashable.ExternallyAssuredFile instance GHC.Generics.Generic Control.Funflow.ContentHashable.ContentHash instance GHC.Classes.Ord Control.Funflow.ContentHashable.ContentHash instance GHC.Classes.Eq Control.Funflow.ContentHashable.ContentHash instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.ContentHashable.ExternallyAssuredDirectory instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.ContentHashable.ExternallyAssuredDirectory instance Data.Store.Impl.Store Control.Funflow.ContentHashable.ExternallyAssuredDirectory instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.ContentHashable.ExternallyAssuredDirectory instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.ContentHashable.ExternallyAssuredFile instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.ContentHashable.ExternallyAssuredFile instance Data.Store.Impl.Store Control.Funflow.ContentHashable.ExternallyAssuredFile instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.ContentHashable.ExternallyAssuredFile instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.ContentHashable.DirectoryContent instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.ContentHashable.FileContent instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Fingerprint.Type.Fingerprint instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Types.Bool instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Types.Char instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Types.Int instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Int.Int8 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Int.Int16 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Int.Int32 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Int.Int64 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Types.Word instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Word.Word8 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Word.Word16 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Word.Word32 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Word.Word64 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Types.Float instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Types.Double instance (Control.Funflow.ContentHashable.ContentHashable m n, Data.Typeable.Internal.Typeable n) => Control.Funflow.ContentHashable.ContentHashable m (GHC.Real.Ratio n) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.Scientific.Scientific instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Integer.Type.Integer instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m GHC.Natural.Natural instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.ByteString.Internal.ByteString instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.ByteString.Lazy.Internal.ByteString instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.Text.Internal.Text instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.Text.Internal.Lazy.Text instance (Data.Typeable.Internal.Typeable k, Data.Typeable.Internal.Typeable v, Control.Funflow.ContentHashable.ContentHashable m k, Control.Funflow.ContentHashable.ContentHashable m v) => Control.Funflow.ContentHashable.ContentHashable m (Data.Map.Internal.Map k v) instance (Data.Typeable.Internal.Typeable k, Data.Typeable.Internal.Typeable v, Control.Funflow.ContentHashable.ContentHashable m k, Control.Funflow.ContentHashable.ContentHashable m v) => Control.Funflow.ContentHashable.ContentHashable m (Data.HashMap.Base.HashMap k v) instance (Data.Typeable.Internal.Typeable v, Control.Funflow.ContentHashable.ContentHashable m v) => Control.Funflow.ContentHashable.ContentHashable m (Data.HashSet.HashSet v) instance (Data.Typeable.Internal.Typeable a, Control.Funflow.ContentHashable.ContentHashable m a) => Control.Funflow.ContentHashable.ContentHashable m [a] instance (Data.Typeable.Internal.Typeable a, Control.Funflow.ContentHashable.ContentHashable m a) => Control.Funflow.ContentHashable.ContentHashable m (GHC.Base.NonEmpty a) instance (Data.Typeable.Internal.Typeable a, Control.Funflow.ContentHashable.ContentHashable m a) => Control.Funflow.ContentHashable.ContentHashable m (Data.Vector.Vector a) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m () instance (Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b) => Control.Funflow.ContentHashable.ContentHashable m (a, b) instance (Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b, Control.Funflow.ContentHashable.ContentHashable m c) => Control.Funflow.ContentHashable.ContentHashable m (a, b, c) instance (Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b, Control.Funflow.ContentHashable.ContentHashable m c, Control.Funflow.ContentHashable.ContentHashable m d) => Control.Funflow.ContentHashable.ContentHashable m (a, b, c, d) instance (Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b, Control.Funflow.ContentHashable.ContentHashable m c, Control.Funflow.ContentHashable.ContentHashable m d, Control.Funflow.ContentHashable.ContentHashable m e) => Control.Funflow.ContentHashable.ContentHashable m (a, b, c, d, e) instance (GHC.Base.Monad m, Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b, Control.Funflow.ContentHashable.ContentHashable m c, Control.Funflow.ContentHashable.ContentHashable m d, Control.Funflow.ContentHashable.ContentHashable m e, Control.Funflow.ContentHashable.ContentHashable m f) => Control.Funflow.ContentHashable.ContentHashable m (a, b, c, d, e, f) instance (GHC.Base.Monad m, Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b, Control.Funflow.ContentHashable.ContentHashable m c, Control.Funflow.ContentHashable.ContentHashable m d, Control.Funflow.ContentHashable.ContentHashable m e, Control.Funflow.ContentHashable.ContentHashable m f, Control.Funflow.ContentHashable.ContentHashable m g) => Control.Funflow.ContentHashable.ContentHashable m (a, b, c, d, e, f, g) instance Control.Funflow.ContentHashable.ContentHashable m a => Control.Funflow.ContentHashable.ContentHashable m (GHC.Base.Maybe a) instance (Control.Funflow.ContentHashable.ContentHashable m a, Control.Funflow.ContentHashable.ContentHashable m b) => Control.Funflow.ContentHashable.ContentHashable m (Data.Either.Either a b) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.Aeson.Types.Internal.Value instance Control.Funflow.ContentHashable.ContentHashable m c => Control.Funflow.ContentHashable.GContentHashable m (GHC.Generics.K1 i c) instance (GHC.Base.Monad m, Data.Typeable.Internal.Typeable b, Data.Typeable.Internal.Typeable t) => Control.Funflow.ContentHashable.ContentHashable m (Path.Internal.Path b t) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Data.Time.Clock.Internal.UTCTime.UTCTime instance GHC.Base.Monad m => Control.Funflow.ContentHashable.GContentHashable m GHC.Generics.V1 instance GHC.Base.Monad m => Control.Funflow.ContentHashable.GContentHashable m GHC.Generics.U1 instance (GHC.Generics.Constructor c, Control.Funflow.ContentHashable.GContentHashable m f) => Control.Funflow.ContentHashable.GContentHashable m (GHC.Generics.C1 c f) instance (GHC.Generics.Datatype d, Control.Funflow.ContentHashable.GContentHashable m f) => Control.Funflow.ContentHashable.GContentHashable m (GHC.Generics.D1 d f) instance Control.Funflow.ContentHashable.GContentHashable m f => Control.Funflow.ContentHashable.GContentHashable m (GHC.Generics.S1 s f) instance (Control.Funflow.ContentHashable.GContentHashable m a, Control.Funflow.ContentHashable.GContentHashable m b) => Control.Funflow.ContentHashable.GContentHashable m (a GHC.Generics.:*: b) instance (Control.Funflow.ContentHashable.GContentHashable m a, Control.Funflow.ContentHashable.GContentHashable m b) => Control.Funflow.ContentHashable.GContentHashable m (a GHC.Generics.:+: b) instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.ContentHashable.ContentHash instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.ContentHashable.ContentHash instance Data.Hashable.Class.Hashable Control.Funflow.ContentHashable.ContentHash instance GHC.Show.Show Control.Funflow.ContentHashable.ContentHash instance Data.Store.Impl.Store Control.Funflow.ContentHashable.ContentHash instance Database.SQLite.Simple.FromField.FromField Control.Funflow.ContentHashable.ContentHash instance Database.SQLite.Simple.ToField.ToField Control.Funflow.ContentHashable.ContentHash -- | Hash addressed store in file system. -- -- Associates a key (ContentHash) with an item in the store. An -- item can either be Missing, Pending, or Complete. -- The state is persisted in the file system. -- -- Items are stored under a path derived from their hash. Therefore, -- there can be no two copies of the same item in the store. If two keys -- are associated with the same item, then there will be only one copy of -- that item in the store. -- -- The store is thread-safe and multi-process safe. -- -- It is assumed that the user that the process is running under is the -- owner of the store root, or has permission to create it if missing. -- -- It is assumed that the store root and its immediate contents are not -- modified externally. The contents of pending items may be modified -- externally. -- -- Implementation notes: -- -- The hash of an item can only be determined once it is completed. If -- that hash already exists in the store, then the new item is discarded. -- -- Store state is persisted in the file-system: -- -- module Control.Funflow.ContentStore -- | Open the store under the given root and perform the given action. -- Closes the store once the action is complete -- -- See also: open withStore :: (MonadIO m, MonadMask m) => Path Abs Dir -> (ContentStore -> m a) -> m a -- | open root opens a store under the given root directory. -- -- The root directory is created if necessary. -- -- It is not safe to have multiple store objects refer to the same root -- directory. open :: Path Abs Dir -> IO ContentStore -- | Free the resources associated with the given store object. -- -- The store object may not be used afterwards. close :: ContentStore -> IO () -- | List all elements in the store (pending keys, completed keys, -- completed items). listAll :: MonadIO m => ContentStore -> m ([ContentHash], [ContentHash], [Item]) -- | List all pending keys in the store. listPending :: MonadIO m => ContentStore -> m [ContentHash] -- | List all completed keys in the store. listComplete :: MonadIO m => ContentStore -> m [ContentHash] -- | List all completed items in the store. listItems :: MonadIO m => ContentStore -> m [Item] -- | Query the state of the item under the given key. query :: MonadIO m => ContentStore -> ContentHash -> m (Status () () ()) -- | Check if there is no complete or pending item under the given key. isMissing :: MonadIO m => ContentStore -> ContentHash -> m Bool -- | Check if there is a pending item under the given key. isPending :: MonadIO m => ContentStore -> ContentHash -> m Bool -- | Check if there is a completed item under the given key. isComplete :: MonadIO m => ContentStore -> ContentHash -> m Bool -- | Query the state under the given key and return the item if completed. -- Doesn't block if the item is pending. lookup :: MonadIO m => ContentStore -> ContentHash -> m (Status () () Item) -- | Query the state under the given key and return the item if completed. -- Return an Async to await an update, if pending. lookupOrWait :: MonadIO m => ContentStore -> ContentHash -> m (Status () (Async Update) Item) -- | Query the state under the given key and return the item once -- completed. Blocks if the item is pending. Returns Nothing if -- the item is missing, or failed to be completed. waitUntilComplete :: MonadIO m => ContentStore -> ContentHash -> m (Maybe Item) -- | Atomically query the state under the given key and mark pending if -- missing. -- -- Returns Complete item if the item is complete. Returns -- Pending async if the item is pending, where -- async is an Async to await updates on. Returns -- Missing buildDir if the item was missing, and is now -- pending. It should be constructed in the given buildDir, and -- then marked as complete using markComplete. constructOrAsync :: MonadIO m => ContentStore -> ContentHash -> m (Status (Path Abs Dir) (Async Update) Item) -- | Atomically query the state under the given key and mark pending if -- missing. Wait for the item to be completed, if already pending. Throws -- a FailedToConstruct error if construction fails. -- -- Returns Complete item if the item is complete. Returns -- Missing buildDir if the item was missing, and is now -- pending. It should be constructed in the given buildDir, and -- then marked as complete using markComplete. constructOrWait :: MonadIO m => ContentStore -> ContentHash -> m (Status (Path Abs Dir) Void Item) -- | Atomically query the state under the given key and mark pending if -- missing. constructIfMissing :: MonadIO m => ContentStore -> ContentHash -> m (Status (Path Abs Dir) () Item) -- | Atomically query the state under the given key and mark pending if -- missing. Execute the given function to construct the item, mark as -- complete on success and remove on failure. Forcibly removes if an -- uncaught exception occurs during item construction. withConstructIfMissing :: (MonadIO m, MonadMask m) => ContentStore -> ContentHash -> (Path Abs Dir -> m (Either e a)) -> m (Status e () (Maybe a, Item)) -- | Mark a non-existent item as pending. -- -- Creates the build directory and returns its path. -- -- See also: constructIfMissing. markPending :: MonadIO m => ContentStore -> ContentHash -> m (Path Abs Dir) -- | Mark a pending item as complete. markComplete :: MonadIO m => ContentStore -> ContentHash -> m Item -- | Remove a pending item. -- -- It is the callers responsibility to ensure that no other threads or -- processes will attempt to access the item's contents afterwards. removeFailed :: MonadIO m => ContentStore -> ContentHash -> m () -- | Remove a key association independent of the corresponding item state. -- Do nothing if no item exists under the given key. -- -- It is the callers responsibility to ensure that no other threads or -- processes will attempt to access the contents afterwards. -- -- Note, this will leave an orphan item behind if no other keys point to -- it. There is no garbage collection mechanism in place at the moment. removeForcibly :: MonadIO m => ContentStore -> ContentHash -> m () -- | Remove a completed item in the store. Do nothing if not completed. -- -- It is the callers responsibility to ensure that no other threads or -- processes will attempt to access the contents afterwards. -- -- Note, this will leave keys pointing to that item dangling. There is no -- garbage collection mechanism in place at the moment. removeItemForcibly :: MonadIO m => ContentStore -> Item -> m () -- | Link the given alias to the given item. If the alias existed before it -- is overwritten. assignAlias :: MonadIO m => ContentStore -> Alias -> Item -> m () -- | Lookup an item under the given alias. Returns Nothing if the -- alias does not exist. lookupAlias :: MonadIO m => ContentStore -> Alias -> m (Maybe Item) -- | Remove the given alias. removeAlias :: MonadIO m => ContentStore -> Alias -> m () -- | List all aliases and the respective items. listAliases :: MonadIO m => ContentStore -> m [(Alias, Item)] -- | Get all hashes that resulted in the given item. getBackReferences :: MonadIO m => ContentStore -> Item -> m [ContentHash] -- | Define the input items to a subtree. setInputs :: MonadIO m => ContentStore -> ContentHash -> [Item] -> m () -- | Get the input items to a subtree if any were defined. getInputs :: MonadIO m => ContentStore -> ContentHash -> m [Item] -- | Set a metadata entry on an item. setMetadata :: (ToField k, ToField v, MonadIO m) => ContentStore -> ContentHash -> k -> v -> m () -- | Retrieve a metadata entry on an item, or Nothing if missing. getMetadata :: (ToField k, FromField v, MonadIO m) => ContentStore -> ContentHash -> k -> m (Maybe v) -- | Create and open a new metadata file on a pending item in write mode. createMetadataFile :: MonadIO m => ContentStore -> ContentHash -> Path Rel File -> m (Path Abs File, Handle) -- | Return the path to a metadata file if it exists. getMetadataFile :: MonadIO m => ContentStore -> ContentHash -> Path Rel File -> m (Maybe (Path Abs File)) itemHash :: Item -> ContentHash -- | The store path of a completed item. itemPath :: ContentStore -> Item -> Path Abs Dir -- | The scoped path to a content item within the store. itemRelPath :: Item -> Path Rel Dir -- | The absolute path to content within the store. contentPath :: ContentStore -> Content t -> Path Abs t -- | Store item containing the given content. contentItem :: Content t -> Item contentFilename :: Content File -> Path Rel File -- | The root directory of the store. root :: ContentStore -> Path Abs Dir -- | A hash addressed store on the file system. data ContentStore -- | A completed item in the ContentStore. data Item -- | File or directory within a content store Item. data Content t [All] :: Item -> Content Dir [:] :: Item -> Path Rel t -> Content t -- | Append to the path within a store item. (^) :: Content Dir -> Path Rel t -> Content t infixl 4 ^ newtype Alias Alias :: Text -> Alias [unAlias] :: Alias -> Text -- | Status of an item in the store. data Status missing pending complete -- | The item does not exist, yet. Missing :: missing -> Status missing pending complete -- | The item is under construction and not ready for consumption. Pending :: pending -> Status missing pending complete -- | The item is complete and ready for consumption. Complete :: complete -> Status missing pending complete type Status_ = Status () () () -- | Update about the status of a pending item. data Update -- | The item is now completed and ready for consumption. Completed :: Item -> Update -- | Constructing the item failed. Failed :: Update -- | Errors that can occur when interacting with the store. data StoreError -- | An item is not under construction when it should be. NotPending :: ContentHash -> StoreError -- | An item is already under construction when it should be missing. AlreadyPending :: ContentHash -> StoreError -- | An item is already complete when it shouldn't be. AlreadyComplete :: ContentHash -> StoreError -- | The link under the given hash points to an invalid path. CorruptedLink :: ContentHash -> FilePath -> StoreError -- | A failure occurred while waiting for the item to be constructed. FailedToConstruct :: ContentHash -> StoreError -- | IncompatibleStoreVersion storeDir actual expected The given -- store has a version number that is incompatible. IncompatibleStoreVersion :: (Path Abs Dir) -> Int -> Int -> StoreError -- | MalformedMetadataEntry hash key The metadata entry for the -- give hash, key pair is malformed. MalformedMetadataEntry :: ContentHash -> SQLData -> StoreError instance Data.Store.Impl.Store Control.Funflow.ContentStore.Alias instance Database.SQLite.Simple.ToField.ToField Control.Funflow.ContentStore.Alias instance Database.SQLite.Simple.FromField.FromField Control.Funflow.ContentStore.Alias instance GHC.Show.Show Control.Funflow.ContentStore.Alias instance GHC.Classes.Ord Control.Funflow.ContentStore.Alias instance GHC.Classes.Eq Control.Funflow.ContentStore.Alias instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.ContentStore.Alias instance GHC.Show.Show Control.Funflow.ContentStore.Update instance GHC.Classes.Eq Control.Funflow.ContentStore.Update instance GHC.Generics.Generic Control.Funflow.ContentStore.Item instance GHC.Show.Show Control.Funflow.ContentStore.Item instance GHC.Classes.Ord Control.Funflow.ContentStore.Item instance GHC.Classes.Eq Control.Funflow.ContentStore.Item instance GHC.Show.Show Control.Funflow.ContentStore.StoreError instance (GHC.Show.Show missing, GHC.Show.Show pending, GHC.Show.Show complete) => GHC.Show.Show (Control.Funflow.ContentStore.Status missing pending complete) instance (GHC.Classes.Eq missing, GHC.Classes.Eq pending, GHC.Classes.Eq complete) => GHC.Classes.Eq (Control.Funflow.ContentStore.Status missing pending complete) instance GHC.Classes.Eq (Control.Funflow.ContentStore.Content t) instance GHC.Show.Show (Control.Funflow.ContentStore.Content t) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m (Control.Funflow.ContentStore.Content Path.Dir) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m (Control.Funflow.ContentStore.Content Path.File) instance GHC.Base.Monad m => Control.Funflow.ContentHashable.ContentHashable m Control.Funflow.ContentStore.Item instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.ContentStore.Item instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.ContentStore.Item instance Data.Hashable.Class.Hashable Control.Funflow.ContentStore.Item instance Data.Store.Impl.Store Control.Funflow.ContentStore.Item instance GHC.Exception.Exception Control.Funflow.ContentStore.StoreError -- | Definition of external tasks module Control.Funflow.External -- | Set of items which may be treated as an input path to an external -- task. data InputPath -- | An item in the content store. IPItem :: Item -> InputPath -- | An external file whose contents are considered assured by the external -- system. IPExternalFile :: ExternallyAssuredFile -> InputPath -- | An external directory whose contents are considered assured by the -- external system. IPExternalDir :: ExternallyAssuredDirectory -> InputPath -- | Component of a parameter data ParamField -- | Text component. ParamText :: !Text -> ParamField -- | Reference to a path to a content store item. ParamPath :: !InputPath -> ParamField -- | Reference to an environment variable. ParamEnv :: !Text -> ParamField -- | Reference to the effective user ID of the executor. ParamUid :: ParamField -- | Reference to the effective group ID of the executor. ParamGid :: ParamField -- | Reference to the output path in the content store. ParamOut :: ParamField -- | A parameter to an external task -- -- The runtime values to external references, e.g. environment variables, -- should not significantly influence the result of the external task. In -- particular, the content hash will not depend on these runtime values. newtype Param Param :: [ParamField] -> Param -- | Converter of path components. data ConvParam f ConvParam :: Item -> f (Path Abs Dir) -> Text -> f Text -> f CUid -> f CGid -> f (Path Abs Dir) -> ConvParam f -- | Resolve a reference to a content store item. [convPath] :: ConvParam f -> Item -> f (Path Abs Dir) -- | Resolve an environment variable. [convEnv] :: ConvParam f -> Text -> f Text -- | Resolve the effective user ID. [convUid] :: ConvParam f -> f CUid -- | Resolve the effective group ID. [convGid] :: ConvParam f -> f CGid -- | Resolve the output path in the content store. [convOut] :: ConvParam f -> f (Path Abs Dir) paramFieldToText :: Applicative f => ConvParam f -> ParamField -> f Text -- | Transform a parameter to text using the given converter. paramToText :: Applicative f => ConvParam f -> Param -> f Text stringParam :: String -> Param textParam :: Text -> Param -- | Reference to a path to either: - a content store item, or - an -- externally assured file/directory. pathParam :: InputPath -> Param -- | Reference to a path to a file or directory within a store item. contentParam :: Content t -> Param -- | Reference an externally assured file externalFileParam :: ExternallyAssuredFile -> Param -- | Reference an externally assured file externalDirectoryParam :: ExternallyAssuredDirectory -> Param -- | Reference to an environment variable. envParam :: Text -> Param -- | Reference to the effective user ID of the executor. uidParam :: Param -- | Reference to the effective group ID of the executor. gidParam :: Param -- | Reference to the output path in the content store. outParam :: Param -- | Control how and where stdout from the process is captured. Some -- external steps will write their output to stdout rather than to a -- file. data OutputCapture -- | Specify that the step will write its output files directly, and that -- stdout will not be captured in the step output. NoOutputCapture :: OutputCapture -- | Capture output to a file named out in the output directory. StdOutCapture :: OutputCapture -- | Capture output to a custom named file in the output directory. CustomOutCapture :: (Path Rel File) -> OutputCapture -- | Get the file to write output to, if this is desired. outputCaptureToRelFile :: OutputCapture -> Maybe (Path Rel File) -- | A monomorphic description of an external task. This is basically just -- a command which can be run. data ExternalTask ExternalTask :: Text -> [Param] -> [(Text, Param)] -> OutputCapture -> ExternalTask [_etCommand] :: ExternalTask -> Text -- | Environment variables to set for the scope of the execution. [_etParams] :: ExternalTask -> [Param] [_etEnv] :: ExternalTask -> [(Text, Param)] [_etWriteToStdOut] :: ExternalTask -> OutputCapture data TaskDescription TaskDescription :: ContentHash -> ExternalTask -> TaskDescription [_tdOutput] :: TaskDescription -> ContentHash [_tdTask] :: TaskDescription -> ExternalTask etWriteToStdOut :: Lens' ExternalTask OutputCapture etParams :: Lens' ExternalTask [Param] etEnv :: Lens' ExternalTask [(Text, Param)] etCommand :: Lens' ExternalTask Text tdTask :: Lens' TaskDescription ExternalTask tdOutput :: Lens' TaskDescription ContentHash instance GHC.Show.Show Control.Funflow.External.TaskDescription instance GHC.Generics.Generic Control.Funflow.External.TaskDescription instance GHC.Show.Show Control.Funflow.External.ExternalTask instance GHC.Generics.Generic Control.Funflow.External.ExternalTask instance GHC.Show.Show Control.Funflow.External.OutputCapture instance GHC.Generics.Generic Control.Funflow.External.OutputCapture instance GHC.Show.Show Control.Funflow.External.Param instance GHC.Base.Semigroup Control.Funflow.External.Param instance GHC.Base.Monoid Control.Funflow.External.Param instance GHC.Generics.Generic Control.Funflow.External.Param instance GHC.Show.Show Control.Funflow.External.ParamField instance GHC.Generics.Generic Control.Funflow.External.ParamField instance GHC.Show.Show Control.Funflow.External.InputPath instance GHC.Generics.Generic Control.Funflow.External.InputPath instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.ExternalTask instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.External.ExternalTask instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.External.ExternalTask instance Data.Store.Impl.Store Control.Funflow.External.ExternalTask instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.OutputCapture instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.External.OutputCapture instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.External.OutputCapture instance Data.Store.Impl.Store Control.Funflow.External.OutputCapture instance Data.String.IsString Control.Funflow.External.Param instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.Param instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.External.Param instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.External.Param instance Data.Store.Impl.Store Control.Funflow.External.Param instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.ParamField instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.External.ParamField instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.External.ParamField instance Data.Store.Impl.Store Control.Funflow.External.ParamField instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.InputPath instance Data.Aeson.Types.FromJSON.FromJSON Control.Funflow.External.InputPath instance Data.Aeson.Types.ToJSON.ToJSON Control.Funflow.External.InputPath instance Data.Store.Impl.Store Control.Funflow.External.InputPath -- | Module supporting the use of docker containers as external tasks. -- -- In general, an external task can be any command. This module just -- makes it easier to specify certain tasks which will run inside docker -- containers. It handles constructing the call to docker, mounting input -- and output directories, and specifying the docker image and version to -- use. module Control.Funflow.External.Docker data Config Config :: Text -> Maybe Text -> Param -> [Param] -> [(Text, Param)] -> OutputCapture -> Config [image] :: Config -> Text [optImageID] :: Config -> Maybe Text [command] :: Config -> Param [args] :: Config -> [Param] [env] :: Config -> [(Text, Param)] [stdout] :: Config -> OutputCapture toExternal :: Config -> ExternalTask instance GHC.Generics.Generic Control.Funflow.External.Docker.Docker instance GHC.Generics.Generic Control.Funflow.External.Docker.Config instance GHC.Generics.Generic Control.Funflow.External.Docker.Bind instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.Docker.Docker instance Control.Funflow.ContentHashable.ContentHashable GHC.Types.IO Control.Funflow.External.Docker.Bind instance GHC.Base.Semigroup Control.Funflow.External.Docker.Bind instance GHC.Base.Monoid Control.Funflow.External.Docker.Bind -- | A Funflow coordinator is used to distribute tasks amongst multiple -- executors. It provides a functionality to submit tasks, to fetch them -- for execution, and to check on their status. -- -- There are multiple possible instantiations of the Coordinator -- class. module Control.Funflow.External.Coordinator -- | Information about an executor capable of running tasks. Currently this -- is just a newtype wrapper around hostname. newtype Executor Executor :: HostName -> Executor data TaskStatus -- | Task is in the queue and has not begun executing Pending :: TaskStatus Running :: ExecutionInfo -> TaskStatus Completed :: ExecutionInfo -> TaskStatus -- | Task has failed with failure count Failed :: ExecutionInfo -> Int -> TaskStatus data TaskInfo KnownTask :: TaskStatus -> TaskInfo UnknownTask :: TaskInfo data ExecutionInfo ExecutionInfo :: Executor -> TimeSpec -> ExecutionInfo [_eiExecutor] :: ExecutionInfo -> Executor [_eiElapsed] :: ExecutionInfo -> TimeSpec data TaskError ExternalTaskFailed :: TaskDescription -> TaskInfo -> (Maybe (Path Abs File)) -> (Maybe (Path Abs File)) -> TaskError class Coordinator c where { type family Config c; type family Hook c = h | h -> c; } -- | Perform any necessary initialisation to connect to the coordinator. initialise :: (Coordinator c, MonadIO m) => Config c -> m (Hook c) -- | Submit a task to the task queue. It is allowed to overwrite a known -- task. submitTask :: (Coordinator c, MonadIO m) => Hook c -> TaskDescription -> m () -- | View the size of the current task queue queueSize :: (Coordinator c, MonadIO m) => Hook c -> m Int -- | Fetch information on the current task taskInfo :: (Coordinator c, MonadIO m) => Hook c -> ContentHash -> m TaskInfo -- | Pop a task off of the queue for execution. The popped task should be -- added to the execution queue popTask :: (Coordinator c, MonadIO m) => Hook c -> Executor -> m (Maybe TaskDescription) -- | Await task completion. -- -- If the task is complete, this will return 'KnownTask Completed'. If -- the task is failed, this will return 'KnownTask Failed'. If the task -- is not known to the system, this will return UnknownTask. -- Otherwise (if the task is pending or running), this will block until -- the task either completes or fails. awaitTask :: (Coordinator c, MonadIO m) => Hook c -> ContentHash -> m TaskInfo -- | Update execution status for a running task. This should error for a -- task which is not running. updateTaskStatus :: (Coordinator c, MonadIO m) => Hook c -> ContentHash -> TaskStatus -> m () -- | Remove all pending tasks from the queue. dropTasks :: (Coordinator c, MonadIO m) => Hook c -> m () eiExecutor :: Lens' ExecutionInfo Executor eiElapsed :: Lens' ExecutionInfo TimeSpec startTask :: (Coordinator c, MonadIO m) => Hook c -> m (Maybe TaskDescription) -- | Check if a task is currently 'in progress' - e.g. pending or running. isInProgress :: (Coordinator c, MonadIO m) => Hook c -> ContentHash -> m Bool -- | Pop a task off of the queue for execution. Passes the popped task to -- the given function for execution. If the function returns success -- (Right), then the task will be marked as completed in the given -- time. If the function returns failure (Left), then the task -- will be marked as failed. If the function raises an exception or is -- interrupted by an asynchronous exception, then the task will be placed -- back on the task queue and the exception propagated. Returns -- Nothing if no task is available and Just () on -- task completion or regular failure. withPopTask :: (Coordinator c, MonadIO m, MonadMask m, KatipContext m) => Hook c -> Executor -> (TaskDescription -> m (TimeSpec, Either Int ())) -> m (Maybe ()) instance Data.Store.Impl.Store Control.Funflow.External.Coordinator.TaskInfo instance Data.Store.Impl.Store Control.Funflow.External.Coordinator.ExecutionInfo instance Data.Store.Impl.Store Control.Funflow.External.Coordinator.TaskStatus instance GHC.Show.Show Control.Funflow.External.Coordinator.TaskError instance GHC.Show.Show Control.Funflow.External.Coordinator.TaskInfo instance GHC.Show.Show Control.Funflow.External.Coordinator.TaskStatus instance GHC.Show.Show Control.Funflow.External.Coordinator.ExecutionInfo instance Data.Store.Impl.Store Control.Funflow.External.Coordinator.Executor instance GHC.Show.Show Control.Funflow.External.Coordinator.Executor instance GHC.Exception.Exception Control.Funflow.External.Coordinator.TaskError -- | Executor for external tasks. -- -- An executor will poll for tasks on the co-ordinator, mark them as in -- progress and then execute them. -- -- You probably want to start with executeLoop. module Control.Funflow.External.Executor data ExecutionResult -- | The result already exists in the store and there is no need to -- execute. This is also returned if the job is already running -- elsewhere. Cached :: ExecutionResult -- | The computation is already running elsewhere. This is probably -- indicative of a bug, because the coordinator should only allow one -- instance of a task to be running at any time. AlreadyRunning :: ExecutionResult -- | Execution completed successfully after a certain amount of time. Success :: TimeSpec -> ExecutionResult -- | Execution failed with the following exit code. TODO where should logs -- go? Failure :: TimeSpec -> Int -> ExecutionResult -- | The executor itself failed to execute the external task. E.g. because -- the executable was not found. ExecutorFailure :: IOException -> ExecutionResult -- | Execute an individual task. execute :: ContentStore -> TaskDescription -> KatipContextT IO ExecutionResult -- | Execute tasks forever executeLoop :: forall c. Coordinator c => c -> Config c -> ContentStore -> IO () -- | Same as executeLoop, but allows specifying a custom -- Scribe for logging executeLoopWithScribe :: forall c. Coordinator c => c -> Config c -> ContentStore -> Scribe -> IO () -- | withFollowFile in out follows the file in and prints -- contents to out as they appear. The file must exist. Doesn't -- handle file truncation. withFollowFile :: Path Abs File -> Handle -> IO a -> IO a -- | SQLLite co-ordinator for Funflow. -- -- This co-ordinator effectively uses the shared filesystem as a tool for -- task distribution and sequencing. This means that it can control a -- distributed funflow task without needing any additional processes -- running. module Control.Funflow.External.Coordinator.SQLite -- | SQLite coordinator tag. data SQLite SQLite :: SQLite instance GHC.Show.Show Control.Funflow.External.Coordinator.SQLite.SQLiteCoordinatorError instance Database.SQLite.Simple.FromField.FromField Control.Funflow.External.Coordinator.SQLite.SqlExternal instance GHC.Exception.Exception Control.Funflow.External.Coordinator.SQLite.SQLiteCoordinatorError instance Control.Funflow.External.Coordinator.Coordinator Control.Funflow.External.Coordinator.SQLite.SQLite instance Database.SQLite.Simple.FromRow.FromRow Control.Funflow.External.Coordinator.SQLite.SqlTask instance Database.SQLite.Simple.ToField.ToField Control.Funflow.External.Coordinator.SQLite.SqlExternal instance Database.SQLite.Simple.FromRow.FromRow Control.Funflow.External.Coordinator.SQLite.SqlTaskInfo instance GHC.Enum.Enum Control.Funflow.External.Coordinator.SQLite.SqlTaskStatus instance Database.SQLite.Simple.FromField.FromField Control.Funflow.External.Coordinator.SQLite.SqlExecutor instance Database.SQLite.Simple.ToField.ToField Control.Funflow.External.Coordinator.SQLite.SqlExecutor instance Database.SQLite.Simple.FromField.FromField Control.Funflow.External.Coordinator.SQLite.SqlTaskStatus instance Database.SQLite.Simple.ToField.ToField Control.Funflow.External.Coordinator.SQLite.SqlTaskStatus -- | Redis-based co-ordinator for Funflow. -- -- There are two co-ordinators defined in this module. They differ in -- whether they open a new connection to Redis or re-use an existing one. -- Other than that they behave identically. module Control.Funflow.External.Coordinator.Redis data Redis Redis :: Redis data RedisPreconnected RedisPreconnected :: RedisPreconnected instance Control.Funflow.External.Coordinator.Coordinator Control.Funflow.External.Coordinator.Redis.RedisPreconnected instance Control.Funflow.External.Coordinator.Coordinator Control.Funflow.External.Coordinator.Redis.Redis -- | In-memory co-ordinator for funflow. This module is not greatly useful -- except for testing purposes. module Control.Funflow.External.Coordinator.Memory data MemoryCoordinator MemoryCoordinator :: MemoryCoordinator data MemHook MemHook :: TVar [TaskDescription] -> TVar (Map ContentHash TaskStatus) -> MemHook [_mhTaskQueue] :: MemHook -> TVar [TaskDescription] [_mhExecutionQueue] :: MemHook -> TVar (Map ContentHash TaskStatus) mhTaskQueue :: Lens' MemHook (TVar [TaskDescription]) mhExecutionQueue :: Lens' MemHook (TVar (Map ContentHash TaskStatus)) createMemoryCoordinator :: IO MemHook instance Control.Funflow.External.Coordinator.Coordinator Control.Funflow.External.Coordinator.Memory.MemoryCoordinator -- | This module contains the means to execute a pipeline. -- -- You should probably start with withSimpleLocalRunner and -- runSimpleFlow. The other functions in this module provide more -- flexible versions of runSimpleFlow. module Control.Funflow.Exec.Simple -- | Run a flow, discarding all logging. runFlow :: forall c eff ex a b. (Coordinator c, Exception ex) => c -> Config c -> ContentStore -> (eff ~> AsyncA IO) -> Int -> Flow eff ex a b -> a -> IO (Either ex b) -- | Simple evaulation of a flow runFlowEx :: forall c eff ex a b. (Coordinator c, Exception ex) => c -> Config c -> ContentStore -> (eff ~> AsyncA (KatipContextT IO)) -> Int -> Flow eff ex a b -> a -> KatipContextT IO b -- | Run a simple flow. Logging will be sent to stderr runSimpleFlow :: forall c a b. (Coordinator c) => c -> Config c -> ContentStore -> SimpleFlow a b -> a -> IO (Either SomeException b) -- | Create a full pipeline runner locally. This includes an executor for -- executing external tasks. This function is specialised to -- SimpleFlow since in cases where a custom term algebra is in -- use, we assume that probably a centralised coordinator and external -- runners may be desired as well. withSimpleLocalRunner :: Path Abs Dir -> ((SimpleFlow a b -> a -> IO (Either SomeException b)) -> IO c) -> IO c -- | Template Haskell splices for the funflow cache. module Control.Funflow.Cache.TH -- | Create a default cacher with a random identity. -- -- Note that this cacher is deliberately conservative - e.g. if the -- application is recompiled, the cache will not be reused. defaultCacher :: Q Exp -- | Create a default cacher based on the location of this splice. Note -- that this may lead to invalid cacheing if the code is changed without -- the version being updated. defaultCacherLoc :: Int -> Q Exp instance Data.Hashable.Class.Hashable Language.Haskell.TH.Syntax.Loc -- | Pretty-printer for Funflow diagrams. module Control.Funflow.Pretty ppFlow :: Flow eff ex a b -> Doc showFlow :: Flow eff ex a b -> String -- | Miscallaneous steps to form part of Funflow computations. module Control.Funflow.Steps -- | `retry n s f` reruns f on failure at most n times with a -- delay of s seconds between retries retry :: forall arr eff ex a b. (Exception ex, Store a, ArrowFlow eff ex arr) => Int -> Int -> arr a b -> arr a b assignAliasInStore :: ArrowFlow eff ex arr => arr (Alias, Item) () -- | copyDirToStore (dIn, Nothing) copies the contents of -- dIn into the store right under the subtree. -- -- | copyDirToStore (dIn, Just dOut) copies the contents of -- dIn into the store under relative path dOut within -- the subtree copyDirToStore :: ArrowFlow eff ex arr => arr (DirectoryContent, Maybe (Path Rel Dir)) (Content Dir) -- | copyFileToStore (fIn, fOut) copies the contents of -- fIn into the store under the relative path fOut -- within the subtree. copyFileToStore :: ArrowFlow eff ex arr => arr (FileContent, Path Rel File) (Content File) -- | List the contents of a directory within the store listDirContents :: ArrowFlow eff ex arr => arr (Content Dir) ([Content Dir], [Content File]) -- | Search for files in the directory matching the given text string, as a -- glob pattern. globDir :: ArrowFlow eff ex arr => arr (Content Dir, String) [Content File] -- | Search for files in the directory matching the given pattern. globDirPattern :: ArrowFlow eff ex arr => arr (Content Dir, Pattern) [Content File] lookupAliasInStore :: ArrowFlow eff ex arr => arr Alias (Maybe Item) -- | Merge a number of store directories together into a single output -- directory. This uses hardlinks to avoid duplicating the data on disk. mergeDirs :: ArrowFlow eff ex arr => arr [Content Dir] (Content Dir) -- | Merge a number of files into a single output directory. mergeFiles :: ArrowFlow eff ex arr => arr [Content File] (Content Dir) putInStoreAt :: (ContentHashable IO a, Typeable t, ArrowFlow eff ex arr) => (Path Abs t -> a -> IO ()) -> arr (a, Path Rel t) (Content t) -- | Read the contents of the given file in the store. readString :: ArrowFlow eff ex arr => arr (Content File) String -- | Read the contents of a file named out within the given item. readString_ :: ArrowFlow eff ex arr => arr Item String -- | Read a YAML file from the given file in the store. readYaml :: FromJSON a => SimpleFlow (Content File) (Either ParseException a) writeExecutableString :: ArrowFlow eff ex arr => arr (String, Path Rel File) (Content File) -- | Create and write into a file under the given path in the store. writeString :: ArrowFlow eff ex arr => arr (String, Path Rel File) (Content File) -- | Create and write into a file named out within the given item. writeString_ :: ArrowFlow eff ex arr => arr String (Content File) -- | Write a YAML file under the given name to the store. writeYaml :: (ContentHashable IO a, ToJSON a) => SimpleFlow (a, Path Rel File) (Content File) -- | Write a YAML file named out.yaml to the store. writeYaml_ :: (ContentHashable IO a, ToJSON a) => SimpleFlow a (Content File) docker :: (ContentHashable IO a, ArrowFlow eff ex arr) => (a -> Config) -> arr a Item promptFor :: (Read a, ArrowFlow eff ex arr) => arr String a printS :: (Show a, ArrowFlow eff ex arr) => arr a () failStep :: ArrowFlow eff ex arr => arr () () worstBernoulli :: (Exception ex, ArrowFlow eff ex arr) => (String -> ex) -> arr Double Double -- | pause for a given number of seconds. Thread through a value to ensure -- delay does not happen inparallel with other processing pauseWith :: (Store a, ArrowFlow eff ex arr) => arr (Int, a) a -- | on first invocation die and leave a suicide note on second invocation -- it is resurrected and destroys suicide note, returning contents melancholicLazarus :: ArrowFlow eff ex arr => arr String String -- | Central Funflow module. -- -- This module just re-exports various other modules for convenience. module Control.Funflow type Flow eff ex = ErrorChoice ex (Flow' eff) type SimpleFlow = Flow NoEffect SomeException type ==> = SimpleFlow data NoEffect a b data Flow' eff a b [Step] :: Properties a b -> (a -> b) -> Flow' eff a b [StepIO] :: Properties a b -> (a -> IO b) -> Flow' eff a b [External] :: ExternalProperties a -> (a -> ExternalTask) -> Flow' eff a Item [PutInStore] :: ContentHashable IO a => (Path Abs Dir -> a -> IO ()) -> Flow' eff a Item [GetFromStore] :: (Path Abs t -> IO a) -> Flow' eff (Content t) a [InternalManipulateStore] :: (ContentStore -> a -> IO b) -> Flow' eff a b [Wrapped] :: Properties a b -> eff a b -> Flow' eff a b -- | A cacher is responsible for controlling how steps are cached. data Cacher i o -- | This step cannot be cached (default). NoCache :: Cacher i o Cache :: Int -> i -> ContentHash -> o -> ByteString -> ByteString -> o -> Cacher i o -- | Function to encode the input into a content hash. This function -- additionally takes an identities which gets incorporated into -- the cacher. [cacherKey] :: Cacher i o -> Int -> i -> ContentHash [cacherStoreValue] :: Cacher i o -> o -> ByteString -- | Attempt to read the cache value back. May throw exceptions. [cacherReadValue] :: Cacher i o -> ByteString -> o -- | Additional properties associated with external tasks. data ExternalProperties a ExternalProperties :: MDWriter a () -> Bool -> ExternalProperties a -- | Write additional metadata to the content store. [ep_mdpolicy] :: ExternalProperties a -> MDWriter a () -- | Specify that this external step is impure, and as such should not be -- cached. [ep_impure] :: ExternalProperties a -> Bool -- | Metadata writer type MDWriter i o = Maybe (i -> o -> [(Text, ByteString)]) data Properties i o Properties :: Maybe Text -> Cacher i o -> MDWriter i o -> Properties i o -- | Name of this step. Used when describing the step in diagrams or other -- reporting. [name] :: Properties i o -> Maybe Text -- | Specify whether this step can be cached or not and, if so, how to do -- so. [cache] :: Properties i o -> Cacher i o -- | Write additional metadata to the content store. [mdpolicy] :: Properties i o -> MDWriter i o defaultCacherWithIdent :: (Store o, ContentHashable Identity i) => Int -> Cacher i o -- | Create a default cacher with a random identity. -- -- Note that this cacher is deliberately conservative - e.g. if the -- application is recompiled, the cache will not be reused. defaultCacher :: Q Exp -- | Create a default cacher based on the location of this splice. Note -- that this may lead to invalid cacheing if the code is changed without -- the version being updated. defaultCacherLoc :: Int -> Q Exp class (ArrowChoice arr, ArrowError ex arr) => ArrowFlow eff ex arr | arr -> eff ex -- | Create a flow from a pure function. step' :: ArrowFlow eff ex arr => Properties a b -> (a -> b) -> arr a b -- | Create a flow from an IO action. stepIO' :: ArrowFlow eff ex arr => Properties a b -> (a -> IO b) -> arr a b -- | Create an external task in the flow. external :: ArrowFlow eff ex arr => (a -> ExternalTask) -> arr a Item -- | Create an external task with additional properties external' :: ArrowFlow eff ex arr => ExternalProperties a -> (a -> ExternalTask) -> arr a Item -- | Create a flow from a user-defined effect. wrap' :: ArrowFlow eff ex arr => Properties a b -> eff a b -> arr a b -- | Create a flow which will write its incoming data to the store. putInStore :: (ArrowFlow eff ex arr, ContentHashable IO a) => (Path Abs Dir -> a -> IO ()) -> arr a Item -- | Create a flow which will read data from the given store item. getFromStore :: ArrowFlow eff ex arr => (Path Abs t -> IO a) -> arr (Content t) a -- | Perform some internal manipulation of the content store. internalManipulateStore :: ArrowFlow eff ex arr => (ContentStore -> a -> IO b) -> arr a b -- | Create a flow from a pure function. This is a variant on step' -- which uses the default properties. step :: ArrowFlow eff ex arr => (a -> b) -> arr a b -- | Create a flow from an IO action. This is a variant on stepIO' -- which uses the default properties. stepIO :: ArrowFlow eff ex arr => (a -> IO b) -> arr a b wrap :: ArrowFlow eff ex arr => eff a b -> arr a b -- | Open the store under the given root and perform the given action. -- Closes the store once the action is complete -- -- See also: open withStore :: (MonadIO m, MonadMask m) => Path Abs Dir -> (ContentStore -> m a) -> m a