{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS -Wno-orphans #-}
--------------------------------------------------------------------------------
-- |
-- Module : Database.EventStore.Internal.Subscription.Regular
-- Copyright : (C) 2017 Yorick Laupa
-- License : (see the file LICENSE)
--
-- Maintainer : Yorick Laupa <yo.eight@gmail.com>
-- Stability : provisional
-- Portability : non-portable
--
--------------------------------------------------------------------------------
module Database.EventStore.Internal.Subscription.Regular where

--------------------------------------------------------------------------------
import Database.EventStore.Internal.Communication
import Database.EventStore.Internal.Control
import Database.EventStore.Internal.Exec
import Database.EventStore.Internal.Operation.Volatile
import Database.EventStore.Internal.Prelude
import Database.EventStore.Internal.Stream
import Database.EventStore.Internal.Subscription.Api
import Database.EventStore.Internal.Subscription.Types
import Database.EventStore.Internal.Subscription.Packages

--------------------------------------------------------------------------------
-- | Also referred as volatile subscription. For example, if a stream has 100
--   events in it when a subscriber connects, the subscriber can expect to see
--   event number 101 onwards until the time the subscription is closed or
--   dropped.
data RegularSubscription t =
  RegularSubscription
  { RegularSubscription t -> Exec
_regExec :: Exec
  , RegularSubscription t -> UUID
_regSubId :: UUID
  , RegularSubscription t -> StreamId t
_regStream :: StreamId t
  , RegularSubscription t -> Chan SubAction
_regChan :: Chan SubAction
  }

--------------------------------------------------------------------------------
instance Subscription (RegularSubscription s) where
  nextSubEvent :: RegularSubscription s -> IO SubAction
nextSubEvent RegularSubscription s
s = Chan SubAction -> IO SubAction
forall (m :: * -> *) a. MonadBase IO m => Chan a -> m a
readChan (RegularSubscription s -> Chan SubAction
forall t. RegularSubscription t -> Chan SubAction
_regChan RegularSubscription s
s)

  unsubscribe :: RegularSubscription s -> IO ()
unsubscribe RegularSubscription s
s = Exec -> SendPackage -> IO ()
forall p a (m :: * -> *).
(Pub p, Typeable a, MonadIO m) =>
p -> a -> m ()
publishWith (RegularSubscription s -> Exec
forall t. RegularSubscription t -> Exec
_regExec RegularSubscription s
s) (Package -> SendPackage
SendPackage Package
pkg)
    where
      pkg :: Package
pkg = UUID -> Package
createUnsubscribePackage (RegularSubscription s -> UUID
forall t. RegularSubscription t -> UUID
_regSubId RegularSubscription s
s)

--------------------------------------------------------------------------------
instance SubscriptionStream (RegularSubscription t) t where
    subscriptionStream :: RegularSubscription t -> StreamId t
subscriptionStream = RegularSubscription t -> StreamId t
forall t. RegularSubscription t -> StreamId t
_regStream

--------------------------------------------------------------------------------
newRegularSubscription
  :: Exec
  -> StreamId t
  -> Bool
  -> Maybe Credentials
  -> IO (RegularSubscription t)
newRegularSubscription :: Exec
-> StreamId t
-> Bool
-> Maybe Credentials
-> IO (RegularSubscription t)
newRegularSubscription Exec
exec StreamId t
streamId Bool
tos Maybe Credentials
cred
  = do (UUID
subId, Chan SubAction
chan) <- Exec
-> StreamId t
-> Bool
-> Maybe Credentials
-> IO (UUID, Chan SubAction)
forall t.
Exec
-> StreamId t
-> Bool
-> Maybe Credentials
-> IO (UUID, Chan SubAction)
volatile Exec
exec StreamId t
streamId Bool
tos Maybe Credentials
cred
       let sub :: RegularSubscription t
sub =
             RegularSubscription :: forall t.
Exec
-> UUID -> StreamId t -> Chan SubAction -> RegularSubscription t
RegularSubscription
             { _regExec :: Exec
_regExec = Exec
exec
             , _regSubId :: UUID
_regSubId = UUID
subId
             , _regStream :: StreamId t
_regStream = StreamId t
streamId
             , _regChan :: Chan SubAction
_regChan = Chan SubAction
chan
             }

       RegularSubscription t -> IO (RegularSubscription t)
forall (f :: * -> *) a. Applicative f => a -> f a
pure RegularSubscription t
sub