@@ -3,6 +3,7 @@ module Seabug.Metadata
33 , FullSeabugMetadata
44 , Hash
55 , getFullSeabugMetadata
6+ , getFullSeabugMetadataWithBackoff
67 ) where
78
89import Contract.Prelude
@@ -31,6 +32,8 @@ import Data.Argonaut as Argonaut
3132import Data.Bifunctor (lmap )
3233import Data.Function (on )
3334import Data.HTTP.Method (Method (GET))
35+ import Effect.Aff (delay )
36+ import Effect.Random (randomRange )
3437import Metadata.Seabug (SeabugMetadata (SeabugMetadata))
3538import Partial.Unsafe (unsafePartial )
3639import 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+
5887getFullSeabugMetadata
5988 :: CurrencySymbol /\ TokenName
6089 -> String
0 commit comments