2019-04-18 12:38:01 +02:00
|
|
|
{- This file is part of Vervis.
|
|
|
|
-
|
|
|
|
- Written in 2019 by fr33domlover <fr33domlover@riseup.net>.
|
|
|
|
-
|
|
|
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
|
|
|
-
|
|
|
|
- The author(s) have dedicated all copyright and related and neighboring
|
|
|
|
- rights to this software to the public domain worldwide. This software is
|
|
|
|
- distributed without any warranty.
|
|
|
|
-
|
|
|
|
- You should have received a copy of the CC0 Public Domain Dedication along
|
|
|
|
- with this software. If not, see
|
|
|
|
- <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
|
|
-}
|
|
|
|
|
|
|
|
-- | A typeclass providing a subset of what 'HandlerFor' does, allowing to
|
|
|
|
-- write monadic actions that can run both inside a request handler and outside
|
|
|
|
-- of the web server context.
|
|
|
|
module Yesod.MonadSite
|
|
|
|
( Site (..)
|
|
|
|
, MonadSite (..)
|
2019-06-15 18:24:34 +02:00
|
|
|
, askUrlRender
|
2019-04-18 12:38:01 +02:00
|
|
|
, asksSite
|
|
|
|
, runSiteDB
|
|
|
|
, WorkerT ()
|
|
|
|
, runWorkerT
|
|
|
|
, WorkerFor
|
|
|
|
, runWorker
|
2019-05-10 06:36:21 +02:00
|
|
|
, forkWorker
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
, asyncWorker
|
2019-04-18 12:38:01 +02:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Control.Exception
|
|
|
|
import Control.Monad.Fail
|
|
|
|
import Control.Monad.IO.Class
|
|
|
|
import Control.Monad.IO.Unlift
|
|
|
|
import Control.Monad.Logger.CallStack
|
|
|
|
import Control.Monad.Trans.Class
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
import Control.Monad.Trans.Except
|
2019-09-25 12:43:05 +02:00
|
|
|
import Control.Monad.Trans.Maybe
|
2019-04-18 12:38:01 +02:00
|
|
|
import Control.Monad.Trans.Reader
|
|
|
|
import Data.Functor
|
|
|
|
import Data.Text (Text)
|
|
|
|
import Database.Persist.Sql
|
|
|
|
import UnliftIO.Async
|
|
|
|
import UnliftIO.Concurrent
|
2019-05-10 06:36:21 +02:00
|
|
|
import Yesod.Core hiding (logError)
|
2019-04-18 12:38:01 +02:00
|
|
|
import Yesod.Core.Types
|
|
|
|
import Yesod.Persist.Core
|
|
|
|
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
import qualified Control.Monad.Trans.RWS.Lazy as RWSL
|
2019-05-10 06:36:21 +02:00
|
|
|
import qualified Data.Text as T
|
|
|
|
|
2019-04-18 12:38:01 +02:00
|
|
|
class PersistConfig (SitePersistConfig site) => Site site where
|
|
|
|
type SitePersistConfig site
|
|
|
|
siteApproot :: site -> Text
|
|
|
|
sitePersistConfig :: site -> SitePersistConfig site
|
|
|
|
sitePersistPool :: site -> PersistConfigPool (SitePersistConfig site)
|
|
|
|
siteLogger :: site -> Logger
|
|
|
|
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
class (MonadIO m, MonadLogger m) => MonadSite m where
|
2019-04-18 12:38:01 +02:00
|
|
|
type SiteEnv m
|
2019-06-15 18:24:34 +02:00
|
|
|
askSite :: m (SiteEnv m)
|
|
|
|
askUrlRenderParams :: m (Route (SiteEnv m) -> [(Text, Text)] -> Text)
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
{-
|
2019-04-18 12:38:01 +02:00
|
|
|
forkSite :: (SomeException -> m ()) -> m () -> m ()
|
|
|
|
asyncSite :: m a -> m (m (Either SomeException a))
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
-}
|
|
|
|
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRender :: MonadSite m => m (Route (SiteEnv m) -> Text)
|
|
|
|
askUrlRender = do
|
|
|
|
render <- askUrlRenderParams
|
|
|
|
return $ \ route -> render route []
|
|
|
|
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
instance MonadSite m => MonadSite (ReaderT r m) where
|
|
|
|
type SiteEnv (ReaderT r m) = SiteEnv m
|
|
|
|
askSite = lift askSite
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRenderParams = lift askUrlRenderParams
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
|
2019-09-25 12:43:05 +02:00
|
|
|
instance MonadSite m => MonadSite (MaybeT m) where
|
|
|
|
type SiteEnv (MaybeT m) = SiteEnv m
|
|
|
|
askSite = lift askSite
|
|
|
|
askUrlRenderParams = lift askUrlRenderParams
|
|
|
|
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
instance MonadSite m => MonadSite (ExceptT e m) where
|
|
|
|
type SiteEnv (ExceptT e m) = SiteEnv m
|
|
|
|
askSite = lift askSite
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRenderParams = lift askUrlRenderParams
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
|
|
|
|
instance (Monoid w, MonadSite m) => MonadSite (RWSL.RWST r w s m) where
|
|
|
|
type SiteEnv (RWSL.RWST r w s m) = SiteEnv m
|
|
|
|
askSite = lift askSite
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRenderParams = lift askUrlRenderParams
|
2019-04-18 12:38:01 +02:00
|
|
|
|
|
|
|
asksSite :: MonadSite m => (SiteEnv m -> a) -> m a
|
|
|
|
asksSite f = f <$> askSite
|
|
|
|
|
|
|
|
runSiteDB
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
:: (MonadUnliftIO m, MonadSite m, Site (SiteEnv m))
|
2019-04-18 12:38:01 +02:00
|
|
|
=> PersistConfigBackend (SitePersistConfig (SiteEnv m)) m a
|
|
|
|
-> m a
|
|
|
|
runSiteDB action = do
|
|
|
|
site <- askSite
|
|
|
|
runPool (sitePersistConfig site) action (sitePersistPool site)
|
|
|
|
|
|
|
|
instance MonadSite (HandlerFor site) where
|
|
|
|
type SiteEnv (HandlerFor site) = site
|
|
|
|
askSite = getYesod
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRenderParams = getUrlRenderParams
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
{-
|
2019-04-18 12:38:01 +02:00
|
|
|
forkSite = forkHandler
|
|
|
|
asyncSite action = do
|
|
|
|
mvar <- newEmptyMVar
|
|
|
|
let handle e = putMVar mvar $ Left e
|
|
|
|
forkHandler handle $ do
|
|
|
|
result <- action
|
|
|
|
putMVar mvar $ Right result
|
|
|
|
return $ liftIO $ readMVar mvar
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
-}
|
|
|
|
|
|
|
|
instance MonadSite (WidgetFor site) where
|
|
|
|
type SiteEnv (WidgetFor site) = site
|
|
|
|
askSite = getYesod
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRenderParams = getUrlRenderParams
|
2019-04-18 12:38:01 +02:00
|
|
|
|
|
|
|
newtype WorkerT site m a = WorkerT
|
|
|
|
{ unWorkerT :: LoggingT (ReaderT site m) a
|
|
|
|
}
|
|
|
|
deriving
|
|
|
|
( Functor, Applicative, Monad, MonadFail, MonadIO, MonadLogger
|
|
|
|
, MonadLoggerIO
|
|
|
|
)
|
|
|
|
|
|
|
|
instance MonadUnliftIO m => MonadUnliftIO (WorkerT site m) where
|
|
|
|
askUnliftIO =
|
|
|
|
WorkerT $ withUnliftIO $ \ u ->
|
|
|
|
return $ UnliftIO $ unliftIO u . unWorkerT
|
|
|
|
withRunInIO inner =
|
|
|
|
WorkerT $ withRunInIO $ \ run -> inner (run . unWorkerT)
|
|
|
|
|
|
|
|
instance MonadTrans (WorkerT site) where
|
|
|
|
lift = WorkerT . lift . lift
|
|
|
|
|
|
|
|
instance (MonadUnliftIO m, Yesod site, Site site) => MonadSite (WorkerT site m) where
|
|
|
|
type SiteEnv (WorkerT site m) = site
|
|
|
|
askSite = WorkerT $ lift ask
|
2019-06-15 18:24:34 +02:00
|
|
|
askUrlRenderParams = do
|
2019-04-18 12:38:01 +02:00
|
|
|
site <- askSite
|
2019-06-15 18:24:34 +02:00
|
|
|
return $ yesodRender site (siteApproot site)
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
{-
|
2019-04-18 12:38:01 +02:00
|
|
|
forkSite handler action = void $ forkFinally action handler'
|
|
|
|
where
|
|
|
|
handler' (Left e) = handler e
|
|
|
|
handler' (Right _) = pure ()
|
|
|
|
asyncSite action = waitCatch <$> async action
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
-}
|
2019-04-18 12:38:01 +02:00
|
|
|
|
|
|
|
runWorkerT :: (Yesod site, Site site) => WorkerT site m a -> site -> m a
|
|
|
|
runWorkerT (WorkerT action) site = runReaderT (runLoggingT action logFunc) site
|
|
|
|
where
|
|
|
|
logFunc = messageLoggerSource site (siteLogger site)
|
|
|
|
|
|
|
|
type WorkerFor site = WorkerT site IO
|
|
|
|
|
|
|
|
runWorker :: (Yesod site, Site site) => WorkerFor site a -> site -> IO a
|
|
|
|
runWorker = runWorkerT
|
2019-05-10 06:36:21 +02:00
|
|
|
|
|
|
|
forkWorker
|
|
|
|
:: (MonadSite m, Yesod site, Site site, SiteEnv m ~ site)
|
|
|
|
=> Text
|
|
|
|
-> WorkerFor site ()
|
|
|
|
-> m ()
|
|
|
|
forkWorker err worker = do
|
|
|
|
site <- askSite
|
|
|
|
void $ liftIO $ forkFinally (runWorker worker site) (handler site)
|
|
|
|
where
|
|
|
|
handler site r = flip runWorker site $
|
|
|
|
case r of
|
|
|
|
Left e ->
|
|
|
|
logError $
|
|
|
|
"Worker thread threw exception: " <> err <> ": " <>
|
|
|
|
T.pack (displayException e)
|
|
|
|
Right _ -> return ()
|
Yesod.MonadSite module gets some nice upgrades
- Fork and async are no longer class methods, which simplifies things a lot and
allows for many more trivial instances, much like with MonadHandler. Fork and
async are still available, but instead of unnecessarily being class methods,
they are now provided as follows: You can fork and async a worker (no more
fork/async for handler, because I never actually need that, and not sure
there's ever a need for that in general), and you can do that from any
MonadSite. So, you can fork or async a worker from a Handler, from a Worker,
from a ReaderT on top of them e.g. inside runDB, and so on.
- Following the simplification, new MonadSite instances are provided, so far
just the ones in actual use in the code. ReaderT, ExceptT and lazy RWST. More
can be added easily. Oh, and WidgetFor got an instance too.
In particular, this change means there's no usage of `forkHandler` anymore, at
all. I wonder if it ever makes a difference to `forkWorker` versus
`forkHandler`. Like, does it cause memory leaks or anything. I guess could
check why `forkResource` etc. is good for in `forkHandler` implementation. I
suppose if needed, I could fix possible memory leaks in `forkWorker`.
2019-06-14 19:10:12 +02:00
|
|
|
|
|
|
|
asyncWorker
|
|
|
|
:: (MonadSite m, SiteEnv m ~ site, Yesod site, Site site)
|
|
|
|
=> WorkerFor site a
|
|
|
|
-> m (m (Either SomeException a))
|
|
|
|
asyncWorker worker = do
|
|
|
|
site <- askSite
|
|
|
|
liftIO $ waitCatch <$> async (runWorker worker site)
|