packages feed

rapid 0.1.1 → 0.1.2

raw patch · 3 files changed

+136/−32 lines, 3 files

Files

CHANGELOG.md view
@@ -1,3 +1,8 @@+# 0.1.2++  * Added `restartWith` and `startWith`.+  * Better documentation.+ # 0.1.1    * Minor documentation fixes.
Rapid.hs view
@@ -12,7 +12,7 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}  -- | -- Module:     Rapid@@ -20,15 +20,22 @@ -- License:    Apache License 2.0 -- Maintainer: Ertugrul Söylemez <esz@posteo.de> ----- This library provides a safer and more convenient wrapper around the--- <https://hackage.haskell.org/package/foreign-store foreign-store library>.+-- This module provides a rapid prototyping suite for GHCi that can be+-- used standalone or integrated into editors.  You can hot-reload+-- individual running components as you make changes to their code.  It+-- is designed to shorten the development cycle during the development+-- of long-running programs like servers, web applications and+-- interactive user interfaces. ----- You can use it for background services within a GHCi session that--- survive loading, reloading and unloading modules, which is--- particularly useful when writing long-running programs like servers--- and user interfaces.+-- It can also be used in the context of batch-style programs:  Keep+-- resources that are expensive to create in memory and reuse them+-- across module reloads instead of reloading/recomputing them after+-- every code change. ----- __Please read the "Safety and securty" section below!__+-- Technically this package is a safe and convenient wrapper around+-- <https://hackage.haskell.org/package/foreign-store foreign-store>.+--+-- __Read the "Safety and securty" section before using this module!__  module Rapid     ( -- * Introduction@@ -40,6 +47,9 @@       -- ** Reusing expensive resources       -- $reusing +      -- ** Cabal notes+      -- $cabal+       -- ** Emacs integration       -- $emacs @@ -52,7 +62,9 @@        -- * Threads       restart,+      restartWith,       start,+      startWith,       stop,        -- * Communication@@ -182,10 +194,27 @@     -> k        -- ^ Name of the thread.     -> IO ()    -- ^ Action the thread runs.     -> IO ()-restart r k action =+restart = restartWith async+++-- | Create a thread with the given name that runs the given action.+--+-- The thread is restarted each time an update occurs.+--+-- The first argument is the function used to create the thread.  It can+-- be used to select between 'async', 'asyncBound' and 'asyncOn'.++restartWith+    :: (Ord k)+    => (forall a. IO a -> IO (Async a))  -- ^ Thread creation function.+    -> Rapid k  -- ^ Rapid state handle.+    -> k        -- ^ Name of the thread.+    -> IO ()    -- ^ Action the thread runs.+    -> IO ()+restartWith myAsync r k action =     withThread r k $ \mtv -> do         whenJust mtv cancelAndWait-        Just <$> async action+        Just <$> myAsync action   -- | Create a thread with the given name that runs the given action.@@ -193,13 +222,36 @@ -- When an update occurs and the thread is currently not running, it is -- started. -start :: (Ord k) => Rapid k -> k -> IO () -> IO ()-start r k action =+start+    :: (Ord k)+    => Rapid k  -- ^ Rapid state handle.+    -> k        -- ^ Name of the thread.+    -> IO ()    -- ^ Action the thread runs.+    -> IO ()+start = startWith async+++-- | Create a thread with the given name that runs the given action.+--+-- When an update occurs and the thread is currently not running, it is+-- started.+--+-- The first argument is the function used to create the thread.  It can+-- be used to select between 'async', 'asyncBound' and 'asyncOn'.++startWith+    :: (Ord k)+    => (forall a. IO a -> IO (Async a))  -- ^ Thread creation function.+    -> Rapid k  -- ^ Rapid state handle.+    -> k        -- ^ Name of the thread.+    -> IO ()    -- ^ Action the thread runs.+    -> IO ()+startWith myAsync r k action =     withThread r k $-        maybe (Just <$> async action)+        maybe (Just <$> myAsync action)               (\tv -> poll tv >>=                       maybe (pure (Just tv))-                            (\_ -> Just <$> async action))+                            (\_ -> Just <$> myAsync action))   -- | Delete the thread with the given name.@@ -270,6 +322,32 @@         fmap (\x -> (Just (toDyn x), x)) gen  +{- $cabal++In general a Cabal project should not have this library as a build-time+dependency.  However, in certain environments (like Nix-based+development) it may be beneficial to include it in the @.cabal@ file+regardless.  A simple solution is to add a flag:++> flag Devel+>     default: False+>     description: Enable development dependencies+>     manual: True+>+> library+>     build-depends:+>         base >= 4.8 && < 5,+>         {- ... -}+>     if flag(devel)+>         build-depends: rapid+>     {- ... -}++Now you can configure your project with @-fdevel@ during development and+have this module available.++-}++ {- $communication  If you need your background threads to communicate with each other, for@@ -351,6 +429,12 @@  {- $intro +While working on a project you may want to have your code running in the+background and restart parts of it as you make changes.  The premise of+this introduction is that you already have such a project, for example a+web application, and that you use a persistent GHCi session (either+standalone or built into your editor).+ To use this library in your project create a module conventionally named @DevelMain@ that exports an action conventionally named @update@: @@ -361,14 +445,14 @@ > update :: IO () > update = >     rapid 0 $ \r ->->         -- Your service management goes here.+>         -- We'll list our components here shortly. >         pure () -The idea is that within a GHCi session this @update@ action is run+The idea is that within a GHCi session you run this @update@ action whenever you want to reload your project during development.  In the simplest case, like in a web application, your project consists of a-single service that is just restarted each time you reload.  Here is an-example using the Snap Framework:+single HTTP server thread that is just restarted each time you reload.+Here is an example using the Snap Framework:  > import qualified Data.Text as T > import Rapid@@ -383,10 +467,10 @@ Once you run @update@ in a GHCi session, a server is started (port 8000) that keeps running in the background, even when you reload modules.  The REPL is fully responsive, so you can continue working.  When you want to-apply the changes you have made, you run @update@ again.  To see this in-action, change the text string in the example, reload the module and-then run @update@.  Also observe that nothing is changed until you-actually run @update@.+apply the changes you have made, you reload the @DevelMain@ module and+run @update@ again.  To see this in action, change the text string in+the example, reload the module and then run @update@.  Also observe that+nothing is changed until you actually run @update@.  When you want to stop a running background thread, replace 'restart' within the @update@ action by 'stop' and run @update@.  The action given@@ -397,14 +481,24 @@ are not restarted during a reload, but are only started and then kept running: +> import MyProject.MyDatabase+> import MyProject.MyBackgroundWorker+> import MyProject.MyWebServer+> import Rapid+> > update =->     rapid 0 $ \r ->+>     rapid 0 $ \r -> do >         start r "database" myDatabase >         start r "worker" myBackgroundWorker >         restart r "webserver" myWebServer  Usually you would put 'restart' in front of the component that you are currently working on, while using 'start' with all others.++Note that even though you are working on the code in+@MyProject.MyWebServer@ you are always reloading the @DevelMain@ module.+There is nothing wrong with loading and reloading other modules, but+only this module gives you access to your @update@ action.  -} 
rapid.cabal view
@@ -13,9 +13,9 @@ -- limitations under the License.  name:     rapid-version:  0.1.1+version:  0.1.2 category: Development-synopsis: GHCi background threads, hot reloading and reload-surviving values+synopsis: Rapid prototyping with GHCi: hot reloading of running components and reload-surviving values  maintainer:   Ertugrul Söylemez <esz@posteo.de> author:       Ertugrul Söylemez <esz@posteo.de>@@ -25,15 +25,20 @@ license:      Apache license-file: LICENSE -description:  This package provides a safe and convenient wrapper around-    <https://hackage.haskell.org/package/foreign-store foreign-store>-    for hot-reloadable background threads during a GHCi session, useful-    for the development of long-running programs like servers, web+description:  This package provides a rapid prototyping suite for GHCi+    that can be used standalone or integrated into editors.  You can+    hot-reload individual running components as you make changes to+    their code.  It is designed to shorten the development cycle during+    the development of long-running programs like servers, web     applications and interactive user interfaces.     .-    It can also be used in the context of batch-style programs to keep-    resources that are expensive to create in memory instead of having-    to recreate them after every module reload.+    It can also be used in the context of batch-style programs:  Keep+    resources that are expensive to create in memory and reuse them+    across module reloads instead of reloading/recomputing them after+    every code change.+    .+    Technically this package is a safe and convenient wrapper around+    <https://hackage.haskell.org/package/foreign-store foreign-store>.  build-type:         Simple cabal-version:      >= 1.10