{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Database.Bloodhound.Internal.Client.Doc
  ( DocVersion (..),
    ExternalDocVersion (..),
    mkDocVersion,
    VersionControl (..),
  )
where

import Data.Aeson
import Data.Maybe
import GHC.Enum

-- | 'DocVersion' is an integer version number for a document between 1
-- and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
newtype DocVersion = DocVersion
  { DocVersion -> Int
docVersionNumber :: Int
  }
  deriving stock (DocVersion -> DocVersion -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DocVersion -> DocVersion -> Bool
$c/= :: DocVersion -> DocVersion -> Bool
== :: DocVersion -> DocVersion -> Bool
$c== :: DocVersion -> DocVersion -> Bool
Eq, Int -> DocVersion -> ShowS
[DocVersion] -> ShowS
DocVersion -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DocVersion] -> ShowS
$cshowList :: [DocVersion] -> ShowS
show :: DocVersion -> String
$cshow :: DocVersion -> String
showsPrec :: Int -> DocVersion -> ShowS
$cshowsPrec :: Int -> DocVersion -> ShowS
Show, Eq DocVersion
DocVersion -> DocVersion -> Bool
DocVersion -> DocVersion -> Ordering
DocVersion -> DocVersion -> DocVersion
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DocVersion -> DocVersion -> DocVersion
$cmin :: DocVersion -> DocVersion -> DocVersion
max :: DocVersion -> DocVersion -> DocVersion
$cmax :: DocVersion -> DocVersion -> DocVersion
>= :: DocVersion -> DocVersion -> Bool
$c>= :: DocVersion -> DocVersion -> Bool
> :: DocVersion -> DocVersion -> Bool
$c> :: DocVersion -> DocVersion -> Bool
<= :: DocVersion -> DocVersion -> Bool
$c<= :: DocVersion -> DocVersion -> Bool
< :: DocVersion -> DocVersion -> Bool
$c< :: DocVersion -> DocVersion -> Bool
compare :: DocVersion -> DocVersion -> Ordering
$ccompare :: DocVersion -> DocVersion -> Ordering
Ord)
  deriving newtype ([DocVersion] -> Encoding
[DocVersion] -> Value
DocVersion -> Encoding
DocVersion -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [DocVersion] -> Encoding
$ctoEncodingList :: [DocVersion] -> Encoding
toJSONList :: [DocVersion] -> Value
$ctoJSONList :: [DocVersion] -> Value
toEncoding :: DocVersion -> Encoding
$ctoEncoding :: DocVersion -> Encoding
toJSON :: DocVersion -> Value
$ctoJSON :: DocVersion -> Value
ToJSON)

-- | Smart constructor for in-range doc version
mkDocVersion :: Int -> Maybe DocVersion
mkDocVersion :: Int -> Maybe DocVersion
mkDocVersion Int
i
  | Int
i forall a. Ord a => a -> a -> Bool
>= DocVersion -> Int
docVersionNumber forall a. Bounded a => a
minBound
      Bool -> Bool -> Bool
&& Int
i forall a. Ord a => a -> a -> Bool
<= DocVersion -> Int
docVersionNumber forall a. Bounded a => a
maxBound =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Int -> DocVersion
DocVersion Int
i
  | Bool
otherwise = forall a. Maybe a
Nothing

instance Bounded DocVersion where
  minBound :: DocVersion
minBound = Int -> DocVersion
DocVersion Int
1
  maxBound :: DocVersion
maxBound = Int -> DocVersion
DocVersion Int
9200000000000000000 -- 9.2e+18

instance Enum DocVersion where
  succ :: DocVersion -> DocVersion
succ DocVersion
x
    | DocVersion
x forall a. Eq a => a -> a -> Bool
/= forall a. Bounded a => a
maxBound = Int -> DocVersion
DocVersion (forall a. Enum a => a -> a
succ forall a b. (a -> b) -> a -> b
$ DocVersion -> Int
docVersionNumber DocVersion
x)
    | Bool
otherwise = forall a. String -> a
succError String
"DocVersion"
  pred :: DocVersion -> DocVersion
pred DocVersion
x
    | DocVersion
x forall a. Eq a => a -> a -> Bool
/= forall a. Bounded a => a
minBound = Int -> DocVersion
DocVersion (forall a. Enum a => a -> a
pred forall a b. (a -> b) -> a -> b
$ DocVersion -> Int
docVersionNumber DocVersion
x)
    | Bool
otherwise = forall a. String -> a
predError String
"DocVersion"
  toEnum :: Int -> DocVersion
toEnum Int
i =
    forall a. a -> Maybe a -> a
fromMaybe (forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int
i forall a. [a] -> [a] -> [a]
++ String
" out of DocVersion range") forall a b. (a -> b) -> a -> b
$ Int -> Maybe DocVersion
mkDocVersion Int
i
  fromEnum :: DocVersion -> Int
fromEnum = DocVersion -> Int
docVersionNumber
  enumFrom :: DocVersion -> [DocVersion]
enumFrom = forall a. (Enum a, Bounded a) => a -> [a]
boundedEnumFrom
  enumFromThen :: DocVersion -> DocVersion -> [DocVersion]
enumFromThen = forall a. (Enum a, Bounded a) => a -> a -> [a]
boundedEnumFromThen

instance FromJSON DocVersion where
  parseJSON :: Value -> Parser DocVersion
parseJSON Value
v = do
    Int
i <- forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
    forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"DocVersion out of range") forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Int -> Maybe DocVersion
mkDocVersion Int
i

-- | 'ExternalDocVersion' is a convenience wrapper if your code uses its
-- own version numbers instead of ones from ES.
newtype ExternalDocVersion = ExternalDocVersion DocVersion
  deriving (ExternalDocVersion -> ExternalDocVersion -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExternalDocVersion -> ExternalDocVersion -> Bool
$c/= :: ExternalDocVersion -> ExternalDocVersion -> Bool
== :: ExternalDocVersion -> ExternalDocVersion -> Bool
$c== :: ExternalDocVersion -> ExternalDocVersion -> Bool
Eq, Int -> ExternalDocVersion -> ShowS
[ExternalDocVersion] -> ShowS
ExternalDocVersion -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExternalDocVersion] -> ShowS
$cshowList :: [ExternalDocVersion] -> ShowS
show :: ExternalDocVersion -> String
$cshow :: ExternalDocVersion -> String
showsPrec :: Int -> ExternalDocVersion -> ShowS
$cshowsPrec :: Int -> ExternalDocVersion -> ShowS
Show, Eq ExternalDocVersion
ExternalDocVersion -> ExternalDocVersion -> Bool
ExternalDocVersion -> ExternalDocVersion -> Ordering
ExternalDocVersion -> ExternalDocVersion -> ExternalDocVersion
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ExternalDocVersion -> ExternalDocVersion -> ExternalDocVersion
$cmin :: ExternalDocVersion -> ExternalDocVersion -> ExternalDocVersion
max :: ExternalDocVersion -> ExternalDocVersion -> ExternalDocVersion
$cmax :: ExternalDocVersion -> ExternalDocVersion -> ExternalDocVersion
>= :: ExternalDocVersion -> ExternalDocVersion -> Bool
$c>= :: ExternalDocVersion -> ExternalDocVersion -> Bool
> :: ExternalDocVersion -> ExternalDocVersion -> Bool
$c> :: ExternalDocVersion -> ExternalDocVersion -> Bool
<= :: ExternalDocVersion -> ExternalDocVersion -> Bool
$c<= :: ExternalDocVersion -> ExternalDocVersion -> Bool
< :: ExternalDocVersion -> ExternalDocVersion -> Bool
$c< :: ExternalDocVersion -> ExternalDocVersion -> Bool
compare :: ExternalDocVersion -> ExternalDocVersion -> Ordering
$ccompare :: ExternalDocVersion -> ExternalDocVersion -> Ordering
Ord, ExternalDocVersion
forall a. a -> a -> Bounded a
maxBound :: ExternalDocVersion
$cmaxBound :: ExternalDocVersion
minBound :: ExternalDocVersion
$cminBound :: ExternalDocVersion
Bounded, Int -> ExternalDocVersion
ExternalDocVersion -> Int
ExternalDocVersion -> [ExternalDocVersion]
ExternalDocVersion -> ExternalDocVersion
ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
ExternalDocVersion
-> ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: ExternalDocVersion
-> ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
$cenumFromThenTo :: ExternalDocVersion
-> ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
enumFromTo :: ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
$cenumFromTo :: ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
enumFromThen :: ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
$cenumFromThen :: ExternalDocVersion -> ExternalDocVersion -> [ExternalDocVersion]
enumFrom :: ExternalDocVersion -> [ExternalDocVersion]
$cenumFrom :: ExternalDocVersion -> [ExternalDocVersion]
fromEnum :: ExternalDocVersion -> Int
$cfromEnum :: ExternalDocVersion -> Int
toEnum :: Int -> ExternalDocVersion
$ctoEnum :: Int -> ExternalDocVersion
pred :: ExternalDocVersion -> ExternalDocVersion
$cpred :: ExternalDocVersion -> ExternalDocVersion
succ :: ExternalDocVersion -> ExternalDocVersion
$csucc :: ExternalDocVersion -> ExternalDocVersion
Enum, [ExternalDocVersion] -> Encoding
[ExternalDocVersion] -> Value
ExternalDocVersion -> Encoding
ExternalDocVersion -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [ExternalDocVersion] -> Encoding
$ctoEncodingList :: [ExternalDocVersion] -> Encoding
toJSONList :: [ExternalDocVersion] -> Value
$ctoJSONList :: [ExternalDocVersion] -> Value
toEncoding :: ExternalDocVersion -> Encoding
$ctoEncoding :: ExternalDocVersion -> Encoding
toJSON :: ExternalDocVersion -> Value
$ctoJSON :: ExternalDocVersion -> Value
ToJSON)

-- | 'VersionControl' is specified when indexing documents as a
-- optimistic concurrency control.
data VersionControl
  = -- | Don't send a version. This is a pure overwrite.
    NoVersionControl
  | -- | Use the default ES versioning scheme. Only
    -- index the document if the version is the same
    -- as the one specified. Only applicable to
    -- updates, as you should be getting Version from
    -- a search result.
    InternalVersion DocVersion
  | -- | Use your own version numbering. Only index
    -- the document if the version is strictly higher
    -- OR the document doesn't exist. The given
    -- version will be used as the new version number
    -- for the stored document. N.B. All updates must
    -- increment this number, meaning there is some
    -- global, external ordering of updates.
    ExternalGT ExternalDocVersion
  | -- | Use your own version numbering. Only index
    -- the document if the version is equal or higher
    -- than the stored version. Will succeed if there
    -- is no existing document. The given version will
    -- be used as the new version number for the
    -- stored document. Use with care, as this could
    -- result in data loss.
    ExternalGTE ExternalDocVersion
  | -- | The document will always be indexed and the
    -- given version will be the new version. This is
    -- typically used for correcting errors. Use with
    -- care, as this could result in data loss.
    ForceVersion ExternalDocVersion
  deriving (VersionControl -> VersionControl -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: VersionControl -> VersionControl -> Bool
$c/= :: VersionControl -> VersionControl -> Bool
== :: VersionControl -> VersionControl -> Bool
$c== :: VersionControl -> VersionControl -> Bool
Eq, Int -> VersionControl -> ShowS
[VersionControl] -> ShowS
VersionControl -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [VersionControl] -> ShowS
$cshowList :: [VersionControl] -> ShowS
show :: VersionControl -> String
$cshow :: VersionControl -> String
showsPrec :: Int -> VersionControl -> ShowS
$cshowsPrec :: Int -> VersionControl -> ShowS
Show, Eq VersionControl
VersionControl -> VersionControl -> Bool
VersionControl -> VersionControl -> Ordering
VersionControl -> VersionControl -> VersionControl
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: VersionControl -> VersionControl -> VersionControl
$cmin :: VersionControl -> VersionControl -> VersionControl
max :: VersionControl -> VersionControl -> VersionControl
$cmax :: VersionControl -> VersionControl -> VersionControl
>= :: VersionControl -> VersionControl -> Bool
$c>= :: VersionControl -> VersionControl -> Bool
> :: VersionControl -> VersionControl -> Bool
$c> :: VersionControl -> VersionControl -> Bool
<= :: VersionControl -> VersionControl -> Bool
$c<= :: VersionControl -> VersionControl -> Bool
< :: VersionControl -> VersionControl -> Bool
$c< :: VersionControl -> VersionControl -> Bool
compare :: VersionControl -> VersionControl -> Ordering
$ccompare :: VersionControl -> VersionControl -> Ordering
Ord)