module Data.SequenceId
( checkSeqId
, incrementSeqId
, checkSeqIdM
, incrementSeqIdM
, lastSeqIdM
, SequenceIdT
, evalSequenceIdT
, SequenceIdError (..)
, SequenceIdErrorType (..)
, SequenceId
) where
import Control.Monad.Trans.State (StateT, evalStateT, get, modify',
put)
import Data.Word (Word32)
type SequenceIdT = StateT SequenceId
type SequenceId = Word32
evalSequenceIdT :: Monad m => SequenceIdT m b -> SequenceId -> m b
evalSequenceIdT = evalStateT
data SequenceIdError =
SequenceIdError
{ errType :: !SequenceIdErrorType
, lastSeqId :: !SequenceId
, currSeqId :: !SequenceId
} deriving (Eq, Show)
data SequenceIdErrorType
= SequenceIdDropped
| SequenceIdDuplicated
deriving (Eq, Show)
checkSeqIdM :: Monad m => SequenceId
-> (SequenceIdT m) (Maybe SequenceIdError)
checkSeqIdM currSeq = do
lastSeq <- get
put $ max lastSeq currSeq
return $ checkSeqId lastSeq currSeq
checkSeqId :: SequenceId
-> SequenceId
-> Maybe SequenceIdError
checkSeqId lastSeq currSeq
| delta lastSeq currSeq > 1 = Just $ SequenceIdError SequenceIdDropped lastSeq currSeq
| delta lastSeq currSeq < 1 = Just $ SequenceIdError SequenceIdDuplicated lastSeq currSeq
| otherwise = Nothing
delta :: SequenceId -> SequenceId -> Integer
delta lastSeq currSeq = toInteger currSeq toInteger lastSeq
incrementSeqIdM :: Monad m => SequenceIdT m SequenceId
incrementSeqIdM = modify' incrementSeqId >> get
incrementSeqId :: SequenceId
-> SequenceId
incrementSeqId = (+1)
lastSeqIdM :: Monad m => SequenceIdT m SequenceId
lastSeqIdM = get