packages feed

extensible-effects-concurrent 0.17.0 → 0.18.0

raw patch · 4 files changed

+58/−61 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Eff.Concurrent: spawnLinkObservationQueue :: forall o q a. (Typeable o, Show o, HasLogging IO q, Lifted IO q, HasCallStack) => Server (ObserverRegistry o) -> Int -> Eff (ObservationQueueReader o : InterruptableProcess q) a -> Eff (InterruptableProcess q) a
- Control.Eff.Concurrent.Api.Observer.Queue: spawnLinkObservationQueue :: forall o q a. (Typeable o, Show o, HasLogging IO q, Lifted IO q, HasCallStack) => Server (ObserverRegistry o) -> Int -> Eff (ObservationQueueReader o : InterruptableProcess q) a -> Eff (InterruptableProcess q) a
+ Control.Eff.Concurrent: spawnLinkObservationQueueWriter :: forall o q. (Typeable o, Show o, HasLogging IO q, Lifted IO q, HasCallStack) => ObservationQueue o -> Eff (InterruptableProcess q) (Observer o)
+ Control.Eff.Concurrent: withObservationQueue :: forall o b e len. (HasCallStack, Typeable o, Show o, HasLogging IO e, Integral len, Member Interrupts e) => len -> Eff (ObservationQueueReader o : e) b -> Eff e b
+ Control.Eff.Concurrent.Api.Observer.Queue: spawnLinkObservationQueueWriter :: forall o q. (Typeable o, Show o, HasLogging IO q, Lifted IO q, HasCallStack) => ObservationQueue o -> Eff (InterruptableProcess q) (Observer o)
+ Control.Eff.Concurrent.Api.Observer.Queue: withObservationQueue :: forall o b e len. (HasCallStack, Typeable o, Show o, HasLogging IO e, Integral len, Member Interrupts e) => len -> Eff (ObservationQueueReader o : e) b -> Eff e b

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for extensible-effects-concurrent +## 0.18.0++- Split-up and replace `spawnLinkObservationQueue` with a simpler (but more verbose) alternative+ ## 0.17.0  - Rename misspelled `spawnLinkObserverationQueue` to `spawnLinkObservationQueue`
extensible-effects-concurrent.cabal view
@@ -1,5 +1,5 @@ name:           extensible-effects-concurrent-version:        0.17.0+version:        0.18.0 description:    Please see the README on GitHub at <https://github.com/sheyll/extensible-effects-concurrent#readme> synopsis:       Message passing concurrency as extensible-effect homepage:       https://github.com/sheyll/extensible-effects-concurrent#readme
src/Control/Eff/Concurrent.hs view
@@ -208,7 +208,8 @@                                                 , readObservationQueue                                                 , tryReadObservationQueue                                                 , flushObservationQueue-                                                , spawnLinkObservationQueue+                                                , withObservationQueue+                                                , spawnLinkObservationQueueWriter                                                 ) import           Control.Eff.Concurrent.Process.ForkIOScheduler                                                 ( schedule
src/Control/Eff/Concurrent/Api/Observer/Queue.hs view
@@ -1,23 +1,21 @@--- | A small process to capture and _share_ observation's by enqueueing them into an STM 'TBQeueu'.+-- | A small process to capture and _share_ observation's by enqueueing them into an STM 'TBQueue'. module Control.Eff.Concurrent.Api.Observer.Queue   ( ObservationQueue()   , ObservationQueueReader   , readObservationQueue   , tryReadObservationQueue   , flushObservationQueue-  , spawnLinkObservationQueue+  , withObservationQueue+  , spawnLinkObservationQueueWriter   ) where  import           Control.Concurrent.STM import           Control.Eff-import           Control.Eff.Extend import           Control.Eff.ExceptionExtra     ( ) import           Control.Eff.Lift import           Control.Eff.Concurrent.Process import           Control.Eff.Log-import           Control.Eff.Concurrent.Api-import           Control.Eff.Concurrent.Api.Client import           Control.Eff.Concurrent.Api.Observer import           Control.Eff.Concurrent.Api.Server import           Control.Eff.Reader.Strict@@ -25,11 +23,10 @@ import           Control.Monad.IO.Class import           Control.Monad                  ( unless ) import           Data.Typeable-import           Text.Printf import           GHC.Stack  -- | Contains a 'TBQueue' capturing observations received by 'enqueueObservationsRegistered'--- or 'spawnLinkObservationQueue'.+-- or 'spawnLinkObservationQueueWriter'. newtype ObservationQueue a = ObservationQueue (TBQueue a)  -- | A 'Reader' for an 'ObservationQueue'.@@ -38,7 +35,7 @@ logPrefix :: forall o proxy . (HasCallStack, Typeable o) => proxy o -> String logPrefix px = "observation queue: " ++ show (typeRep px) --- | Read queued observations captured and enqueued in the shared 'TBQueue' by 'spawnLinkObservationQueue'.+-- | Read queued observations captured and enqueued in the shared 'TBQueue' by 'spawnLinkObservationQueueWriter'. -- This blocks until something was captured or an interrupt or exceptions was thrown. For a non-blocking -- variant use 'tryReadObservationQueue' or 'flushObservationQueue'. readObservationQueue@@ -54,7 +51,7 @@   ObservationQueue q <- ask @(ObservationQueue o)   liftIO (atomically (readTBQueue q)) --- | Read queued observations captured and enqueued in the shared 'TBQueue' by 'spawnLinkObservationQueue'.+-- | Read queued observations captured and enqueued in the shared 'TBQueue' by 'spawnLinkObservationQueueWriter'. -- Return the oldest enqueued observation immediately or 'Nothing' if the queue is empty. -- Use 'readObservationQueue' to block until an observation is observed. tryReadObservationQueue@@ -70,7 +67,7 @@   ObservationQueue q <- ask @(ObservationQueue o)   liftIO (atomically (tryReadTBQueue q)) --- | Read at once all currently queued observations captured and enqueued in the shared 'TBQueue' by 'spawnLinkObservationQueue'.+-- | Read at once all currently queued observations captured and enqueued in the shared 'TBQueue' by 'spawnLinkObservationQueueWriter'. -- This returns immediately all currently enqueued 'Observation's. For a blocking -- variant use 'readObservationQueue'. flushObservationQueue@@ -86,54 +83,24 @@   ObservationQueue q <- ask @(ObservationQueue o)   liftIO (atomically (flushTBQueue q)) ---- | Capture an observation.-data instance Api (ObservationQueue a) r where-  EnqueueObservation :: a -> Api (ObservationQueue a) 'Asynchronous-  StopObservationQueue :: Api (ObservationQueue a) ('Synchronous ())---- | Observe a 'Server' that implements an 'Observable' 'Api'. The observations--- can be obtained by 'readObservationQueue'. All observations are captured up to--- the queue size limit, such that the first message received will be first message--- returned by 'readObservationQueue'.-spawnLinkObservationQueue-  :: forall o q a-   . (Typeable o, Show o, HasLogging IO q, Lifted IO q, HasCallStack)-  => Server (ObserverRegistry o)-  -> Int-  -> Eff (ObservationQueueReader o ': InterruptableProcess q) a-  -> Eff (InterruptableProcess q) a-spawnLinkObservationQueue oSvr queueLimit k = withQueue-  queueLimit-  (do-    ObservationQueue q <- ask @(ObservationQueue o)-    do-      logDebug-        (printf "%s starting with queue limit: %d"-                (logPrefix (Proxy @o))-                queueLimit-        )-      cbo <- raise-        (spawnLinkApiServer-          (handleCasts-            (\case-              EnqueueObservation o -> do-                lift (atomically (writeTBQueue q o))-                pure AwaitNext-            )-          )-          stopServerOnInterrupt-        )-      let thisObserver = toObserverFor EnqueueObservation cbo-      registerObserver thisObserver oSvr-      res <- k-      forgetObserver thisObserver oSvr-      call cbo StopObservationQueue-      logDebug (printf "%s stopped observer process" (logPrefix (Proxy @o)))-      return res-  )--withQueue+-- | Create a mutable queue for observations. Use 'spawnLinkObservationQueueWriter' for a simple way to get+-- a process that enqueues all observations.+--+-- ==== __Example__ ====+--+-- @+-- withObservationQueue 100 $ do+--   q  <- ask @(ObservationQueueReader TestEvent)+--   wq <- spawnLinkObservationQueueWriter q+--   registerObserver wq testServer+--   ...+--   cast testServer DoSomething+--   evt <- readObservationQueue @TestEvent+--   ...+-- @+--+-- @since 0.18.0+withObservationQueue   :: forall o b e len    . ( HasCallStack      , Typeable o@@ -145,7 +112,7 @@   => len   -> Eff (ObservationQueueReader o ': e) b   -> Eff e b-withQueue queueLimit e = do+withObservationQueue queueLimit e = do   q   <- liftIO (newTBQueueIO (fromIntegral queueLimit))   res <- handleInterrupts (return . Left)                           (Right <$> runReader (ObservationQueue q) e)@@ -154,3 +121,28 @@     (null rest)     (logNotice (logPrefix (Proxy @o) ++ " unread observations: " ++ show rest))   either (\em -> logError (show em) >> liftIO (throwIO em)) return res++-- | Spawn a process that can be used as an 'Observer' that enqueues the observations into an+--   'ObservationQueue'. See 'withObservationQueue' for an example.+--+-- The observations can be obtained by 'readObservationQueue'. All observations are captured up to+-- the queue size limit, such that the first message received will be first message+-- returned by 'readObservationQueue'.+--+-- @since 0.18.0+spawnLinkObservationQueueWriter+  :: forall o q+   . (Typeable o, Show o, HasLogging IO q, Lifted IO q, HasCallStack)+  => ObservationQueue o+  -> Eff (InterruptableProcess q) (Observer o)+spawnLinkObservationQueueWriter (ObservationQueue q) = do+  cbo <- spawnLinkApiServer+    (handleObservations+      (\case+        o -> do+          lift (atomically (writeTBQueue q o))+          pure AwaitNext+      )+    )+    stopServerOnInterrupt+  pure (toObserver cbo)