Skip to content

Commit dabfb1b

Browse files
committed
Implement basic blockfrost rate limit handling
1 parent 3a18d29 commit dabfb1b

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

spago.dhall

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ You can edit this file as you like.
2626
, "parallel"
2727
, "partial"
2828
, "prelude"
29+
, "random"
2930
, "transformers"
3031
, "tuples"
3132
, "uint"

src/Seabug/Contract/MarketPlaceListNft.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Control.Parallel (parTraverse)
2222
import Data.Array (catMaybes, mapMaybe)
2323
import Data.Map as Map
2424
import Seabug.MarketPlace (marketplaceValidator)
25-
import Seabug.Metadata (FullSeabugMetadata, getFullSeabugMetadata)
25+
import Seabug.Metadata (FullSeabugMetadata, getFullSeabugMetadataWithBackoff)
2626
import Seabug.Types (MarketplaceDatum(MarketplaceDatum))
2727

2828
type ListNftResult =
@@ -60,6 +60,6 @@ marketPlaceListNft = do
6060
MaybeT $ pure $ fromData $ unwrap plutusData
6161
guard $ valueOf out.amount curr name == one
6262
metadata <- MaybeT $ map hush $
63-
getFullSeabugMetadata (curr /\ name) projectId
63+
getFullSeabugMetadataWithBackoff (curr /\ name) projectId
6464
pure { input, output, metadata }
6565
pure $ catMaybes withMetadata

src/Seabug/Metadata.purs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Seabug.Metadata
33
, FullSeabugMetadata
44
, Hash
55
, getFullSeabugMetadata
6+
, getFullSeabugMetadataWithBackoff
67
) where
78

89
import Contract.Prelude
@@ -31,6 +32,8 @@ import Data.Argonaut as Argonaut
3132
import Data.Bifunctor (lmap)
3233
import Data.Function (on)
3334
import Data.HTTP.Method (Method(GET))
35+
import Effect.Aff (delay)
36+
import Effect.Random (randomRange)
3437
import Metadata.Seabug (SeabugMetadata(SeabugMetadata))
3538
import Partial.Unsafe (unsafePartial)
3639
import Types.CborBytes (cborBytesToByteArray)
@@ -55,6 +58,32 @@ type BlockfrostFetch a = ExceptT BlockfrostFetchError
5558
(ReaderT { projectId :: String } Aff)
5659
a
5760

61+
-- | Tries to get the metadata for the given asset using
62+
-- | Blockfrost. If the rate limit is hit, retries after a random
63+
-- | delay, up to 5 times. Uses a very simple back-off mechanism.
64+
-- | Instead of relying on this, refactor so the rate limit isn't hit.
65+
getFullSeabugMetadataWithBackoff
66+
:: CurrencySymbol /\ TokenName
67+
-> String
68+
-> Aff (Either BlockfrostFetchError FullSeabugMetadata)
69+
getFullSeabugMetadataWithBackoff asset projectId = go 1.0
70+
where
71+
go n = do
72+
r <- getFullSeabugMetadata asset projectId
73+
case r of
74+
Left BlockfrostRateLimit
75+
| n < 5.0 -> do
76+
let n' = n + 1.0
77+
log "Blockfrost rate limit hit, backing off"
78+
-- Wait a random amount of time in the range of [1, 3 *
79+
-- (attempt + 1)) seconds, this is just a heuristic based
80+
-- on my testing
81+
delay <<< wrap <<< (_ * 1000.0) =<<
82+
(liftEffect $ randomRange 1.0 (3.0 * n'))
83+
log $ "Retrying, attempt " <> show n'
84+
go n'
85+
_ -> pure r
86+
5887
getFullSeabugMetadata
5988
:: CurrencySymbol /\ TokenName
6089
-> String

0 commit comments

Comments
 (0)