Skip to content

Commit e675327

Browse files
Report bytestring parsing errors in get as exceptions
Until now, bytestring parsing in `get` and friends would return `Nothing`, which is indistinguishable from the key not being present.
1 parent 9cab160 commit e675327

File tree

1 file changed

+23
-7
lines changed

1 file changed

+23
-7
lines changed

src/Database/Redis/Schema.hs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ class Value inst val where
332332
txValGet :: Identifier val -> Tx inst (Maybe val)
333333

334334
default txValGet :: SimpleValue inst val => Identifier val -> Tx inst (Maybe val)
335-
txValGet (SviTopLevel keyBS) = fmap (fromBS =<<) . txWrap $ Hedis.get keyBS
336-
txValGet (SviHash keyBS hkeyBS) = fmap (fromBS =<<) . txWrap $ Hedis.hget keyBS hkeyBS
335+
txValGet (SviTopLevel keyBS) = txFromBSOrThrow $ txWrap (Hedis.get keyBS)
336+
txValGet (SviHash keyBS hkeyBS) = txFromBSOrThrow $ txWrap (Hedis.hget keyBS hkeyBS)
337337

338338
-- | Write a value to Redis in a transaction.
339339
txValSet :: Identifier val -> val -> Tx inst ()
@@ -367,10 +367,10 @@ class Value inst val where
367367
valGet :: Identifier val -> RedisM inst (Maybe val)
368368

369369
default valGet :: SimpleValue inst val => Identifier val -> RedisM inst (Maybe val)
370-
valGet (SviTopLevel keyBS) =
371-
fmap (fromBS =<<) . expectRight "valGet/plain" =<< Hedis.get keyBS
372-
valGet (SviHash keyBS hkeyBS) =
373-
fmap (fromBS =<<) . expectRight "valGet/hash" =<< Hedis.hget keyBS hkeyBS
370+
valGet ident = do
371+
traverse fromBSOrThrow =<< expectRight "valGet" =<< case ident of
372+
SviTopLevel keyBS -> Hedis.get keyBS
373+
SviHash keyBS hkeyBS -> Hedis.hget keyBS hkeyBS
374374

375375
-- | Write a value.
376376
valSet :: Identifier val -> val -> RedisM inst ()
@@ -568,6 +568,21 @@ watch ref = case toIdentifier ref of
568568
unwatch :: RedisM inst ()
569569
unwatch = Redis Hedis.unwatch >>= expect "unwatch: OK expected" (Right Hedis.Ok)
570570

571+
fromBSOrThrow :: Serializable val => ByteString -> RedisM inst val
572+
fromBSOrThrow bs = case fromBS bs of
573+
Nothing -> throw $ CouldNotDecodeValue (Just bs)
574+
Just val -> pure val
575+
576+
-- Tx is Applicative so it's tricky to decouple the handling
577+
-- of missing values from the handling of other exceptions.
578+
-- This function does both to keep things simple.
579+
txFromBSOrThrow :: Serializable val => Tx inst (Maybe ByteString) -> Tx inst (Maybe val)
580+
txFromBSOrThrow = txCheckMap $ \case
581+
Nothing -> Right Nothing -- item not present
582+
Just bs -> case fromBS bs of
583+
Nothing -> Left $ CouldNotDecodeValue (Just bs)
584+
Just val -> Right (Just val)
585+
571586
-- | Decode a list of ByteStrings.
572587
-- On failure, return the first ByteString that could not be decoded.
573588
fromBSMany :: Serializable val => [ByteString] -> Either ByteString [val]
@@ -868,7 +883,8 @@ lPushLeft (toIdentifier -> keyBS) vals =
868883
lPopRight :: forall ref a. (Ref ref, ValueType ref ~ [a], Serializable a) => ref -> RedisM (RefInstance ref) (Maybe a)
869884
lPopRight (toIdentifier -> keyBS) =
870885
Redis (Hedis.rpop keyBS)
871-
>>= fmap (fromBS =<<) . expectRight "rpop"
886+
>>= expectRight "rpop"
887+
>>= traverse fromBSOrThrow
872888

873889
-- | Pop from the right, blocking.
874890
lPopRightBlocking :: forall ref a. (Ref ref, ValueType ref ~ [a], Serializable a) => TTL -> ref -> RedisM (RefInstance ref) (Maybe a)

0 commit comments

Comments
 (0)