module Hasura.GraphQL.Execute.Subscription.Options
  ( SubscriptionsOptions (..),
    LiveQueriesOptions,
    StreamQueriesOptions,
    BatchSize (..),
    RefetchInterval (..),
    mkSubscriptionsOptions,
    mkBatchSize,
    mkRefetchInterval,
  )
where

import Data.Aeson qualified as J
import Hasura.Prelude
import Hasura.RQL.Types.Numeric (NonNegativeDiffTime, NonNegativeInt)
import Hasura.RQL.Types.Numeric qualified as Numeric

data SubscriptionsOptions = SubscriptionsOptions
  { SubscriptionsOptions -> BatchSize
_lqoBatchSize :: !BatchSize,
    SubscriptionsOptions -> RefetchInterval
_lqoRefetchInterval :: !RefetchInterval
  }
  deriving (Int -> SubscriptionsOptions -> ShowS
[SubscriptionsOptions] -> ShowS
SubscriptionsOptions -> String
(Int -> SubscriptionsOptions -> ShowS)
-> (SubscriptionsOptions -> String)
-> ([SubscriptionsOptions] -> ShowS)
-> Show SubscriptionsOptions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscriptionsOptions] -> ShowS
$cshowList :: [SubscriptionsOptions] -> ShowS
show :: SubscriptionsOptions -> String
$cshow :: SubscriptionsOptions -> String
showsPrec :: Int -> SubscriptionsOptions -> ShowS
$cshowsPrec :: Int -> SubscriptionsOptions -> ShowS
Show, SubscriptionsOptions -> SubscriptionsOptions -> Bool
(SubscriptionsOptions -> SubscriptionsOptions -> Bool)
-> (SubscriptionsOptions -> SubscriptionsOptions -> Bool)
-> Eq SubscriptionsOptions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscriptionsOptions -> SubscriptionsOptions -> Bool
$c/= :: SubscriptionsOptions -> SubscriptionsOptions -> Bool
== :: SubscriptionsOptions -> SubscriptionsOptions -> Bool
$c== :: SubscriptionsOptions -> SubscriptionsOptions -> Bool
Eq)

type LiveQueriesOptions = SubscriptionsOptions

type StreamQueriesOptions = SubscriptionsOptions

mkSubscriptionsOptions :: Maybe BatchSize -> Maybe RefetchInterval -> SubscriptionsOptions
mkSubscriptionsOptions :: Maybe BatchSize -> Maybe RefetchInterval -> SubscriptionsOptions
mkSubscriptionsOptions Maybe BatchSize
batchSize Maybe RefetchInterval
refetchInterval =
  SubscriptionsOptions :: BatchSize -> RefetchInterval -> SubscriptionsOptions
SubscriptionsOptions
    { _lqoBatchSize :: BatchSize
_lqoBatchSize = BatchSize -> Maybe BatchSize -> BatchSize
forall a. a -> Maybe a -> a
fromMaybe (NonNegativeInt -> BatchSize
BatchSize (NonNegativeInt -> BatchSize) -> NonNegativeInt -> BatchSize
forall a b. (a -> b) -> a -> b
$ Int -> NonNegativeInt
Numeric.unsafeNonNegativeInt Int
100) Maybe BatchSize
batchSize,
      _lqoRefetchInterval :: RefetchInterval
_lqoRefetchInterval = RefetchInterval -> Maybe RefetchInterval -> RefetchInterval
forall a. a -> Maybe a -> a
fromMaybe (NonNegativeDiffTime -> RefetchInterval
RefetchInterval NonNegativeDiffTime
1) Maybe RefetchInterval
refetchInterval
    }

instance J.ToJSON SubscriptionsOptions where
  toJSON :: SubscriptionsOptions -> Value
toJSON (SubscriptionsOptions BatchSize
batchSize RefetchInterval
refetchInterval) =
    [Pair] -> Value
J.object
      [ Key
"batch_size" Key -> BatchSize -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
J..= BatchSize
batchSize,
        Key
"refetch_delay" Key -> RefetchInterval -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
J..= RefetchInterval
refetchInterval
      ]

instance J.FromJSON SubscriptionsOptions where
  parseJSON :: Value -> Parser SubscriptionsOptions
parseJSON = String
-> (Object -> Parser SubscriptionsOptions)
-> Value
-> Parser SubscriptionsOptions
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"live query options" \Object
o ->
    BatchSize -> RefetchInterval -> SubscriptionsOptions
SubscriptionsOptions (BatchSize -> RefetchInterval -> SubscriptionsOptions)
-> Parser BatchSize
-> Parser (RefetchInterval -> SubscriptionsOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser BatchSize
forall a. FromJSON a => Object -> Key -> Parser a
J..: Key
"batch_size"
      Parser (RefetchInterval -> SubscriptionsOptions)
-> Parser RefetchInterval -> Parser SubscriptionsOptions
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser RefetchInterval
forall a. FromJSON a => Object -> Key -> Parser a
J..: Key
"refetch_delay"

newtype BatchSize = BatchSize {BatchSize -> NonNegativeInt
unBatchSize :: NonNegativeInt}
  deriving (Int -> BatchSize -> ShowS
[BatchSize] -> ShowS
BatchSize -> String
(Int -> BatchSize -> ShowS)
-> (BatchSize -> String)
-> ([BatchSize] -> ShowS)
-> Show BatchSize
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BatchSize] -> ShowS
$cshowList :: [BatchSize] -> ShowS
show :: BatchSize -> String
$cshow :: BatchSize -> String
showsPrec :: Int -> BatchSize -> ShowS
$cshowsPrec :: Int -> BatchSize -> ShowS
Show, BatchSize -> BatchSize -> Bool
(BatchSize -> BatchSize -> Bool)
-> (BatchSize -> BatchSize -> Bool) -> Eq BatchSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BatchSize -> BatchSize -> Bool
$c/= :: BatchSize -> BatchSize -> Bool
== :: BatchSize -> BatchSize -> Bool
$c== :: BatchSize -> BatchSize -> Bool
Eq, [BatchSize] -> Value
[BatchSize] -> Encoding
BatchSize -> Value
BatchSize -> Encoding
(BatchSize -> Value)
-> (BatchSize -> Encoding)
-> ([BatchSize] -> Value)
-> ([BatchSize] -> Encoding)
-> ToJSON BatchSize
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [BatchSize] -> Encoding
$ctoEncodingList :: [BatchSize] -> Encoding
toJSONList :: [BatchSize] -> Value
$ctoJSONList :: [BatchSize] -> Value
toEncoding :: BatchSize -> Encoding
$ctoEncoding :: BatchSize -> Encoding
toJSON :: BatchSize -> Value
$ctoJSON :: BatchSize -> Value
J.ToJSON, Value -> Parser [BatchSize]
Value -> Parser BatchSize
(Value -> Parser BatchSize)
-> (Value -> Parser [BatchSize]) -> FromJSON BatchSize
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [BatchSize]
$cparseJSONList :: Value -> Parser [BatchSize]
parseJSON :: Value -> Parser BatchSize
$cparseJSON :: Value -> Parser BatchSize
J.FromJSON)

mkBatchSize :: Int -> Maybe BatchSize
mkBatchSize :: Int -> Maybe BatchSize
mkBatchSize Int
x = NonNegativeInt -> BatchSize
BatchSize (NonNegativeInt -> BatchSize)
-> Maybe NonNegativeInt -> Maybe BatchSize
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Maybe NonNegativeInt
Numeric.mkNonNegativeInt Int
x

-- TODO this is treated as milliseconds in fromEnv and as seconds in ToJSON.
--      ideally this would have e.g. ... unRefetchInterval :: Milliseconds
newtype RefetchInterval = RefetchInterval {RefetchInterval -> NonNegativeDiffTime
unRefetchInterval :: NonNegativeDiffTime}
  deriving (Int -> RefetchInterval -> ShowS
[RefetchInterval] -> ShowS
RefetchInterval -> String
(Int -> RefetchInterval -> ShowS)
-> (RefetchInterval -> String)
-> ([RefetchInterval] -> ShowS)
-> Show RefetchInterval
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RefetchInterval] -> ShowS
$cshowList :: [RefetchInterval] -> ShowS
show :: RefetchInterval -> String
$cshow :: RefetchInterval -> String
showsPrec :: Int -> RefetchInterval -> ShowS
$cshowsPrec :: Int -> RefetchInterval -> ShowS
Show, RefetchInterval -> RefetchInterval -> Bool
(RefetchInterval -> RefetchInterval -> Bool)
-> (RefetchInterval -> RefetchInterval -> Bool)
-> Eq RefetchInterval
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RefetchInterval -> RefetchInterval -> Bool
$c/= :: RefetchInterval -> RefetchInterval -> Bool
== :: RefetchInterval -> RefetchInterval -> Bool
$c== :: RefetchInterval -> RefetchInterval -> Bool
Eq, [RefetchInterval] -> Value
[RefetchInterval] -> Encoding
RefetchInterval -> Value
RefetchInterval -> Encoding
(RefetchInterval -> Value)
-> (RefetchInterval -> Encoding)
-> ([RefetchInterval] -> Value)
-> ([RefetchInterval] -> Encoding)
-> ToJSON RefetchInterval
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [RefetchInterval] -> Encoding
$ctoEncodingList :: [RefetchInterval] -> Encoding
toJSONList :: [RefetchInterval] -> Value
$ctoJSONList :: [RefetchInterval] -> Value
toEncoding :: RefetchInterval -> Encoding
$ctoEncoding :: RefetchInterval -> Encoding
toJSON :: RefetchInterval -> Value
$ctoJSON :: RefetchInterval -> Value
J.ToJSON, Value -> Parser [RefetchInterval]
Value -> Parser RefetchInterval
(Value -> Parser RefetchInterval)
-> (Value -> Parser [RefetchInterval]) -> FromJSON RefetchInterval
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [RefetchInterval]
$cparseJSONList :: Value -> Parser [RefetchInterval]
parseJSON :: Value -> Parser RefetchInterval
$cparseJSON :: Value -> Parser RefetchInterval
J.FromJSON)

mkRefetchInterval :: DiffTime -> Maybe RefetchInterval
mkRefetchInterval :: DiffTime -> Maybe RefetchInterval
mkRefetchInterval DiffTime
x = NonNegativeDiffTime -> RefetchInterval
RefetchInterval (NonNegativeDiffTime -> RefetchInterval)
-> Maybe NonNegativeDiffTime -> Maybe RefetchInterval
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DiffTime -> Maybe NonNegativeDiffTime
Numeric.mkNonNegativeDiffTime DiffTime
x