module ZooKeeper.Recipe.Utils
(
SequenceNumWithGUID(..)
, mkSequenceNumWithGUID
, extractSeqNum
, createSeqEphemeralZNode
) where
import Control.Exception
import qualified Data.List as L
import Z.Data.CBytes (CBytes)
import qualified Z.Data.CBytes as CB
import ZooKeeper
import ZooKeeper.Exception
import ZooKeeper.Types
newtype SequenceNumWithGUID = SequenceNumWithGUID
{ SequenceNumWithGUID -> CBytes
unSequenceNumWithGUID :: CBytes
}
mkSequenceNumWithGUID :: CBytes -> SequenceNumWithGUID
mkSequenceNumWithGUID :: CBytes -> SequenceNumWithGUID
mkSequenceNumWithGUID = CBytes -> SequenceNumWithGUID
SequenceNumWithGUID
instance Eq SequenceNumWithGUID where
(SequenceNumWithGUID CBytes
s1) == :: SequenceNumWithGUID -> SequenceNumWithGUID -> Bool
== (SequenceNumWithGUID CBytes
s2) =
CBytes -> CBytes
extractSeqNum CBytes
s1 CBytes -> CBytes -> Bool
forall a. Eq a => a -> a -> Bool
== CBytes -> CBytes
extractSeqNum CBytes
s2
instance Ord SequenceNumWithGUID where
(SequenceNumWithGUID CBytes
s1) <= :: SequenceNumWithGUID -> SequenceNumWithGUID -> Bool
<= (SequenceNumWithGUID CBytes
s2) =
CBytes -> CBytes
extractSeqNum CBytes
s1 CBytes -> CBytes -> Bool
forall a. Ord a => a -> a -> Bool
<= CBytes -> CBytes
extractSeqNum CBytes
s2
instance Show SequenceNumWithGUID where
show :: SequenceNumWithGUID -> String
show (SequenceNumWithGUID CBytes
s) = CBytes -> String
CB.unpack CBytes
s
extractSeqNum :: CBytes -> CBytes
= String -> CBytes
CB.pack (String -> CBytes) -> (CBytes -> String) -> CBytes -> CBytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
reverse ShowS -> (CBytes -> String) -> CBytes -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'_') ShowS -> (CBytes -> String) -> CBytes -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
reverse ShowS -> (CBytes -> String) -> CBytes -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CBytes -> String
CB.unpack
createSeqEphemeralZNode :: ZHandle -> CBytes -> CBytes -> IO StringCompletion
createSeqEphemeralZNode :: ZHandle -> CBytes -> CBytes -> IO StringCompletion
createSeqEphemeralZNode ZHandle
zk CBytes
prefixPath CBytes
guid = do
let seqPath :: CBytes
seqPath = CBytes
prefixPath CBytes -> CBytes -> CBytes
forall a. Semigroup a => a -> a -> a
<> CBytes
"/" CBytes -> CBytes -> CBytes
forall a. Semigroup a => a -> a -> a
<> CBytes
guid CBytes -> CBytes -> CBytes
forall a. Semigroup a => a -> a -> a
<> CBytes
"_"
IO StringCompletion
-> [Handler StringCompletion] -> IO StringCompletion
forall a. IO a -> [Handler a] -> IO a
catches (HasCallStack =>
ZHandle
-> CBytes
-> Maybe Bytes
-> AclVector
-> CreateMode
-> IO StringCompletion
ZHandle
-> CBytes
-> Maybe Bytes
-> AclVector
-> CreateMode
-> IO StringCompletion
zooCreate ZHandle
zk CBytes
seqPath Maybe Bytes
forall a. Maybe a
Nothing AclVector
zooOpenAclUnsafe CreateMode
ZooEphemeralSequential)
[ (ZCONNECTIONLOSS -> IO StringCompletion)
-> Handler StringCompletion
forall a e. Exception e => (e -> IO a) -> Handler a
Handler (\(ZCONNECTIONLOSS
_ :: ZCONNECTIONLOSS ) -> IO StringCompletion
retry)
, (ZOPERATIONTIMEOUT -> IO StringCompletion)
-> Handler StringCompletion
forall a e. Exception e => (e -> IO a) -> Handler a
Handler (\(ZOPERATIONTIMEOUT
_ :: ZOPERATIONTIMEOUT) -> IO StringCompletion
retry)
]
where
retry :: IO StringCompletion
retry :: IO StringCompletion
retry = do
(StringsCompletion (StringVector [CBytes]
children)) <- HasCallStack => ZHandle -> CBytes -> IO StringsCompletion
ZHandle -> CBytes -> IO StringsCompletion
zooGetChildren ZHandle
zk CBytes
prefixPath
case (CBytes -> Bool) -> [CBytes] -> Maybe CBytes
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
L.find (\CBytes
child -> CBytes -> String
CB.unpack CBytes
guid String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`L.isSubsequenceOf` CBytes -> String
CB.unpack CBytes
child) [CBytes]
children of
Just CBytes
child -> StringCompletion -> IO StringCompletion
forall (m :: * -> *) a. Monad m => a -> m a
return (StringCompletion -> IO StringCompletion)
-> StringCompletion -> IO StringCompletion
forall a b. (a -> b) -> a -> b
$ CBytes -> StringCompletion
StringCompletion CBytes
child
Maybe CBytes
Nothing -> ZHandle -> CBytes -> CBytes -> IO StringCompletion
createSeqEphemeralZNode ZHandle
zk CBytes
prefixPath CBytes
guid