{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Database.EventStore.Internal.Subscription.Api where
import Database.EventStore.Internal.Callback
import Database.EventStore.Internal.Communication
import Database.EventStore.Internal.Control
import Database.EventStore.Internal.Types
import Database.EventStore.Internal.Prelude
import Database.EventStore.Internal.Stream
import Database.EventStore.Internal.Subscription.Packages
import Database.EventStore.Internal.Subscription.Types
submit :: Callback SubAction -> ResolvedEvent -> IO ()
submit s xs = fulfill s (Submit xs)
dropped :: Callback SubAction -> SubDropReason -> IO ()
dropped s r = fulfill s (Dropped r)
confirmed :: Callback SubAction -> SubDetails -> IO ()
confirmed s d = fulfill s (Confirmed d)
class Subscription s where
nextEventMaybeSTM :: s -> STM (Maybe ResolvedEvent)
getSubscriptionDetailsSTM :: s -> STM SubDetails
unsubscribe :: s -> IO ()
class SubscriptionStream s t | t -> s where
subscriptionStream :: s -> StreamId t
nextEvent :: Subscription s => s -> IO ResolvedEvent
nextEvent s = atomically $ do
outcome <- nextEventMaybeSTM s
case outcome of
Just e -> return e
Nothing -> retrySTM
nextEventMaybe :: Subscription s => s -> IO (Maybe ResolvedEvent)
nextEventMaybe = atomically . nextEventMaybeSTM
waitConfirmation :: Subscription s => s -> IO ()
waitConfirmation s = atomically $ do
_ <- getSubscriptionDetailsSTM s
return ()
unsubscribeConfirmedSTM :: Subscription s => s -> STM Bool
unsubscribeConfirmedSTM s = do
let action = do
_ <- getSubscriptionDetailsSTM s
return False
catchSTM action $ \(_ :: SomeException) -> return True
unsubscribeConfirmed :: Subscription s => s -> IO Bool
unsubscribeConfirmed = atomically . unsubscribeConfirmedSTM
waitUnsubscribeConfirmed :: Subscription s => s -> IO ()
waitUnsubscribeConfirmed s = atomically $
unlessM (unsubscribeConfirmedSTM s) retrySTM
subUnsubscribe :: (Pub pub, Subscription s) => pub -> s -> IO ()
subUnsubscribe pub s = do
outcome <- atomically $ do
unsubscribed <- unsubscribeConfirmedSTM s
if unsubscribed
then return Nothing
else Just <$> getSubscriptionDetailsSTM s
for_ outcome $ \details -> do
let pkg = createUnsubscribePackage (subId details)
publishWith pub (SendPackage pkg)
getSubscriptionId :: Subscription s => s -> IO SubscriptionId
getSubscriptionId s = atomically $ do
details <- getSubscriptionDetailsSTM s
return (SubscriptionId $ subId details)