1 -- | Running your app inside GHCi.
3 -- To start up GHCi for usage with Yesod, first make sure you are in dev mode:
5 -- > cabal configure -fdev
7 -- Note that @yesod devel@ automatically sets the dev flag.
8 -- Now launch the repl:
10 -- > cabal repl --ghc-options="-O0 -fobject-code"
12 -- To start your app, run:
17 -- You can also call @DevelMain.shutdown@ to stop the app
19 -- You will need to add the foreign-store package to your .cabal file.
20 -- It is very light-weight.
22 -- If you don't use cabal repl, you will need
23 -- to run the following in GHCi or to add it to
28 -- There is more information about this approach,
29 -- on the wiki: https://github.com/yesodweb/yesod/wiki/ghci
31 module DevelMain where
34 import Application (getApplicationRepl, shutdownApp)
36 import Control.Exception (finally)
37 import Control.Monad ((>=>))
38 import Control.Concurrent
41 import Network.Wai.Handler.Warp
44 -- | Start or restart the server.
45 -- newStore is from foreign-store.
46 -- A Store holds onto some data across ghci reloads
49 mtidStore <- lookupStore tidStoreNum
53 done <- storeAction doneStore newEmptyMVar
55 _ <- storeAction (Store tidStoreNum) (newIORef tid)
57 -- server is already running
58 Just tidStore -> restartAppInNewThread tidStore
60 doneStore :: Store (MVar ())
63 -- shut the server down with killThread and wait for the done signal
64 restartAppInNewThread :: Store (IORef ThreadId) -> IO ()
65 restartAppInNewThread tidStore = modifyStoredIORef tidStore $ \tid -> do
67 withStore doneStore takeMVar
68 readStore doneStore >>= start
71 -- | Start the server in a separate thread.
72 start :: MVar () -- ^ Written to when the thread is killed.
75 (port, site, app) <- getApplicationRepl
76 forkIO (finally (runSettings (setPort port defaultSettings) app)
77 -- Note that this implies concurrency
78 -- between shutdownApp and the next app that is starting.
79 -- Normally this should be fine
80 (putMVar done () >> shutdownApp site))
85 mtidStore <- lookupStore tidStoreNum
88 Nothing -> putStrLn "no Yesod app running"
90 withStore tidStore $ readIORef >=> killThread
91 putStrLn "Yesod app is shutdown"
96 modifyStoredIORef :: Store (IORef a) -> (a -> IO a) -> IO ()
97 modifyStoredIORef store f = withStore store $ \ref -> do
99 f v >>= writeIORef ref