From 25d7e7275faab38f72f8db05d5be8681044326ad Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Thu, 30 Jul 2020 07:25:24 +0000 Subject: [PATCH] Add function `withMinimumExecutionTimeOnFailure`. --- lib/core/src/Cardano/Wallet.hs | 32 +- .../Wallet/Api/ApiStakePool.faulty.json | 387 ++++++++++++++++++ 2 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 lib/core/test/data/Cardano/Wallet/Api/ApiStakePool.faulty.json diff --git a/lib/core/src/Cardano/Wallet.hs b/lib/core/src/Cardano/Wallet.hs index 886bc089f4f..e88469fd898 100644 --- a/lib/core/src/Cardano/Wallet.hs +++ b/lib/core/src/Cardano/Wallet.hs @@ -381,7 +381,9 @@ import Data.Set import Data.Text.Class ( ToText (..) ) import Data.Time.Clock - ( UTCTime, getCurrentTime ) + ( NominalDiffTime, UTCTime, addUTCTime, getCurrentTime ) +import Data.Time.Utils + ( waitUntil ) import Data.Type.Equality ( (:~:) (..), testEquality ) import Data.Vector.Shuffle @@ -2118,6 +2120,34 @@ withRootKey ctx wid pwd embed action = db & \DBLayer{..} -> do where db = ctx ^. dbLayer @s @k +-- | Runs the given action, returning immediately on success, but suspending +-- the current thread for a period of time in the event of a failure. +-- +-- In the event of a failure, this function aims to require a total execution +-- time that is approximately equal to the specified 'minimumExecutionTime' +-- argument, and independent of the time period actually required to run the +-- action. +-- +-- However, this property can /only/ be guaranteed if the 'minimumExecutionTime' +-- argument is longer than the time period actually required to run the action. +-- +-- Therefore, it's important to choose a value of 'minimumExecutionTime' that is +-- likely to be longer than the time required to run the action. +-- +withMinimumExecutionTimeOnFailure + :: MonadIO m + => NominalDiffTime + -> ExceptT e m a + -> ExceptT e m a +withMinimumExecutionTimeOnFailure minimumExecutionTime action = do + timeAtStart <- liftIO getCurrentTime + lift (runExceptT action) >>= \case + Left failure -> do + waitUntil (minimumExecutionTime `addUTCTime` timeAtStart) + throwE failure + Right result -> + pure result + {------------------------------------------------------------------------------- Errors -------------------------------------------------------------------------------} diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiStakePool.faulty.json b/lib/core/test/data/Cardano/Wallet/Api/ApiStakePool.faulty.json new file mode 100644 index 00000000000..f66206912be --- /dev/null +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiStakePool.faulty.json @@ -0,0 +1,387 @@ +{ + "seed": -7107996085184291435, + "samples": [ + { + "metrics": { + "saturation": 0.6160834418134742, + "non_myopic_member_rewards": { + "quantity": 615953285512, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 18143234, + "unit": "block" + }, + "relative_stake": { + "quantity": 48.63, + "unit": "percent" + } + }, + "retirement": { + "epoch_start_time": "1862-01-29T20:48:02.108295353453Z", + "epoch_number": 21897 + }, + "cost": { + "quantity": 205, + "unit": "lovelace" + }, + "margin": { + "quantity": 47.85, + "unit": "percent" + }, + "pledge": { + "quantity": 3, + "unit": "lovelace" + }, + "metadata": { + "homepage": "\u0013$󹳯92\u001b\u001f󂠙9s\u0017ur\u001c", + "name": ">*h!x", + "ticker": "k \u0000r򞰴", + "description": "O&\u0004nE\u001cY\"򝽇;\u0003xY􌦨7\u0005:\u0016Ht󕊭񩖖15'\u001b~񦅕X󈥱!󼙰򮣫\u0006\n\u0019𐳓E򂆐/\u0016\n\u0019򕝓\u00004񳓍Ih" + }, + "id": "daf2fc7a68224fe46e8ef8acf12696338216914d65de0127bd615061" + }, + { + "metrics": { + "saturation": 4.24150348278511, + "non_myopic_member_rewards": { + "quantity": 569121601446, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 9835933, + "unit": "block" + }, + "relative_stake": { + "quantity": 11.86, + "unit": "percent" + } + }, + "retirement": { + "epoch_start_time": "1866-12-28T21:00:00Z", + "epoch_number": 14356 + }, + "cost": { + "quantity": 182, + "unit": "lovelace" + }, + "margin": { + "quantity": 15.3, + "unit": "percent" + }, + "pledge": { + "quantity": 166, + "unit": "lovelace" + }, + "metadata": { + "homepage": "񄏆E򶶈oZ_iJ{[MI\u0013񣦕\u001e];ᚹ\\𸆖\\{\"g󼦲񓶏k񺖸󐱪󌄪\u000bgh7", + "name": "\u0018񤱦", + "ticker": "^o\u0013dp", + "description": "GzI炼󏩥z|J7ko\u000b󚵱\u0013\u00160򐇖I𶈽p05񠀱@\u0007𬷃󳪎V\u0014󈝹p\u0004\u0008r!𬴑f\"\u000ec&򻎺T󘃥[<\u0017>񆓭Ce\u001b0`k\u0001Ij򠉜M񧆀󨽈\u0018\u001d.񄱞7D\\\u0000u\"\u0014\u0010!\u0011d񛯎C𮚝򽺫*D򯞣SU𺹜Z?*}󷶏id0,D" + }, + "id": "b01379b2a600a1ca4f96ee68d54a6eeb1f80e1485f8770c4406026c7" + }, + { + "metrics": { + "saturation": 4.403490945522135, + "non_myopic_member_rewards": { + "quantity": 363326578681, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 20235169, + "unit": "block" + }, + "relative_stake": { + "quantity": 64.63, + "unit": "percent" + } + }, + "retirement": { + "epoch_start_time": "1907-03-31T05:41:28.388760714365Z", + "epoch_number": 29422 + }, + "cost": { + "quantity": 235, + "unit": "lovelace" + }, + "margin": { + "quantity": 30.4, + "unit": "percent" + }, + "pledge": { + "quantity": 227, + "unit": "lovelace" + }, + "id": "d63b64ed971e4f22aa6ce52ccfb01ce72e61ed8de467a5bd5cfef7fd" + }, + { + "metrics": { + "saturation": 4.037147815384624, + "non_myopic_member_rewards": { + "quantity": 71413835287, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 9722930, + "unit": "block" + }, + "relative_stake": { + "quantity": 81.96, + "unit": "percent" + } + }, + "cost": { + "quantity": 21, + "unit": "lovelace" + }, + "margin": { + "quantity": 92.16, + "unit": "percent" + }, + "pledge": { + "quantity": 241, + "unit": "lovelace" + }, + "metadata": { + "homepage": "􇏙~𛍾󘏷v򟖥RV򌑓_V򁠪F\u001dn+򒾍񵞖0", + "name": "Lk;*%%;~oVcZ\u0006𵮦󺼋SH\r\u001f\u0011񷬛Z.\u0002𣥿J16󟾎\u0005񅃾{\u001fK놏\u0018𠞰򨅗h/\u0015􍖯\u0007r\n\u001d\u000c\u0007C󝫆u󺌉e\\򶫇\u001d\u001bH2A􏣄Iz\"񣞔񰫝\u001a\u0005򦻣4II\u0015h\u0004񐁭6R\"I%𜁦@=7\u0013l񀆥򵹡\\\u0012S<񜲯񀍢R|i\rX4\u000fL򹬏LhT\u001a򃾆\u0014󳀁\u001a\u0014'a󄃙P$\n\"5K" + }, + "id": "e5744a67d18f5c450db119f4019b5f0487156d3ac6c7fd998a4b63d3" + }, + { + "metrics": { + "saturation": 2.518417801630494, + "non_myopic_member_rewards": { + "quantity": 960222820750, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 16170724, + "unit": "block" + }, + "relative_stake": { + "quantity": 28.8, + "unit": "percent" + } + }, + "retirement": { + "epoch_start_time": "1882-11-06T13:36:07.373487126339Z", + "epoch_number": 16701 + }, + "cost": { + "quantity": 46, + "unit": "lovelace" + }, + "margin": { + "quantity": 78.67, + "unit": "percent" + }, + "pledge": { + "quantity": 224, + "unit": "lovelace" + }, + "metadata": { + "homepage": "7𻞔􌣱ja|%|q򽿹f򯏯񚜱􍶑򪈱\\k\u001e䦕񵵂c񥗹^6\u0012@2\u001c1񖳔C#򁹫\u0006l􄢏񋟘:MfAO𙤪a𹼉CH\u0018⽤\u001a񏑅dk#L񲟣SU\"\u0012G\u001d򬦧񤿫򎊉HNILzeZ\u0006._\u001f\"񵕺󨅱𧯬J\u0006sJc-𠴑(\u0011\u0014", + "name": "𢇽", + "ticker": "𐮱\u0015b\u0018", + "description": "񁭈[򣂕js𼜴|򁾽󋮵\u0015V蕧\u0012Qg\u0000~C\u0003yN\u000c.󪰝t\t򅎄p󈉜󑒖񟦒򮜵􎁉B+\u001cy\\\u0013YxnOJ𰕪𘵭\r򔮾=@􏖗𯽿C󕷵A*\u0015\u0013{\u0008?񅟂Z\noR}+5l퉨*󿱌򇁝\u0001\n\u0008)𫝚S\u001e𤓒Te 񗞂m\r󸘜󦬃\u0003񔱂y򑐻񘗠󡚺񆷛񟙖Jf$pKObq0\u0015'𼪈􍴼\u0016S\nY򭁉\u0004R􈡟\u0016W9C]XV򼶸\u0007񭐃B-𫝊򦺟B-񦰥~J$򭻴핥􋠒7񑀍K#fB🪆󡇱J𑷱󾺗}'򅎒񝥪C􌭪􂅆E==~4,񟥜JCPd\u0012T\u0003-O\u001b0n\u0013Ol򤪦[\u0005R􄙉󥿦yp\u0014\u0014𾮀񸫒fq\u00044}" + }, + "id": "f69e9ecea710a69885c01a6c2f0eac91a33a97f8a8d1e3b74e3fbec3" + }, + { + "metrics": { + "saturation": 2.0811709133682035, + "non_myopic_member_rewards": { + "quantity": 90128575339, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 4622136, + "unit": "block" + }, + "relative_stake": { + "quantity": 95.4, + "unit": "percent" + } + }, + "retirement": { + "epoch_start_time": "1905-12-29T00:00:00Z", + "epoch_number": 12871 + }, + "cost": { + "quantity": 211, + "unit": "lovelace" + }, + "margin": { + "quantity": 19.2, + "unit": "percent" + }, + "pledge": { + "quantity": 106, + "unit": "lovelace" + }, + "metadata": { + "homepage": " G^L])a󒘵#򸲄aᶨ\u0007\u0004[𽒙i>:olo򰛰L)󧔟񄣷+'󬅲l򧟄\t󄼐𺚡󳄮\tw桞\u001e󔛗\u001aST\"1\u000biIUc\u000c.m򇒷6󤄑c*\u001a\u001a%\u001b񩓁񒬻 Y\u0000\u001d񕣻\u001cd\u0005󔉌VM\u0019󇰐C󩞪", + "name": "M$򹄶", + "ticker": "\u0019C+񟅗\u0010", + "description": "G\u001aj񤄐󠪞탄񯲲F󡮠a󷳭C򋩑&dV𣲾\u001d􅔝}𵆦No'M>:bu#\n󙤫󼔬򳈈\u0013+9󋞏f\u000b\\d|9D*u=\u001b󾏧\u0002\u0006;*t񽡑:󺋭i&Sj\u001e񫏦G\u0015JJ]\u0013Ay򆮬\u0013C1I\u000f\r𖚘񆾌H\u0019;C🌍PKL\u001c\u001f(cK\u001fF!򂡿\"幣𷨅󈍴(*\u0000pၗdY󾏤󨾇|E?񜦫\u001d\u0014Vx\u00126S񎹬vxQP𦃶@􄥖\u0001~c}\u000b2\t󾶒򻑖\u0018u<򚾥\u0013\u0019;񂈡ym,𨉖򘦲󯔼6", + "name": "\u001eo(^\t4{\u001c񪤓U򎨥\u001e򎉤x􀶛P)󅧦\u0001\u0002\"2EM&0eV򎒎E\u00115@>򝫜[\u0019񺄥\u000b󞬮wb0Qz+Om}\u0014𸁃uof*A\u0005\u001fP򤡿򻂊]NjP1\u000f0:dg󂇆h\u0000@񶅳\u001c仭y󶅡vZ\u001f񳷼PIPGsZ%􆁞0sL񋆤򌔇/:h\u000b?򣓞$+9\u0018򈿟0E3O雀\u0003\u0010򯣿\u0002J\u0002eF|󑊜t񰇆:󸨶$\u000e񾭺9O𞥕\n􉨣\u0016;\u0014񡮣Nf񴽅󰅽e4𻲑I򥗾UnzWF򚯄񃆒u򙸱\u0005\u0002󔑖-6pk\\򰛘>󖹘\u000b򽊝H'.\u0002q𖯀񛭔\u001d󔬼𽃃;o*U\u0002[%5𸧟}򯆴$\u0015\u0016\u000fg7\u0011Kh\u001dK􏼺7󃞑򆣁JMBKVc񦎿\u001b=>\u0001e8\u0000`\r򆠼󣉧3򧵈R𘤒\u0011\u001c.\u0014I𓪌d0" + }, + "id": "76802e9eca33c94f5d3882053a62966ccb7e5e8003cc540cc235afd6" + }, + { + "metrics": { + "saturation": 2.21718534073677, + "non_myopic_member_rewards": { + "quantity": 575812827990, + "unit": "lovelace" + }, + "produced_blocks": { + "quantity": 7372117, + "unit": "block" + }, + "relative_stake": { + "quantity": 76.08, + "unit": "percent" + } + }, + "cost": { + "quantity": 239, + "unit": "lovelace" + }, + "margin": { + "quantity": 21.22, + "unit": "percent" + }, + "pledge": { + "quantity": 222, + "unit": "lovelace" + }, + "metadata": { + "homepage": "𙋬F\u0015o\u001fH󗻢X򛿆񊧢M\u0010򎋵\u001e\u0015V󩦱z󜷏t\u001a<󣚚d%󘤆𷠿󮒗A.Qy񍼸=񹥏\n񴵸񿄲򸣏'򄛢\u000e&\r-.Q[T񕛳򲙑72Lc􊕕󞍞5\u0012򽫵𾟿ch򉶹O񻓴QB{\u0006\u0015X!<@V𝸚򲥲󏍢󥾽PIDE^򟔜", + "name": "\u001d񂣖\u0008\u00026", + "ticker": "󊻏񞑡󬬽hM", + "description": "\u001fNvKx:5y\u0016w\u0013I󤉶񳖁-IY򌑅7𱹽\u001b\u001fS;򎢖(\u000b%_S{Xz𦯩qN6򅞘𨡑}#6tm=<\u0003R4𭀍bU\u001evT񢨿@h+\u000cblqCgG\u0010򄬜s\\𘜪!^t\u0003 𜠥#񮥿򈜝)-\"?\u0008\u000e𺤢 o'D\u0006\u001a\u0019򜏷򍑫򐎶\u001c9򰄘z6OZw7tv\t\r򞽘x󗁘=s钁󥆭CNH򫂡;\u00011'g\n\u0003Q\u0018󳕔#2ZTz񅧇xK\u001b򆏐\u0001\u0011\u0016NI饤񸍬.󕱟_\u0000r78򗣳y\u0005\u0016𿹞f\u0005\u0013Hp\u0002񻦚\r2𔐖yS;2򂪦\u0010AG𮮹b󒸚/򠛳V􌪩a\u0003H򨦀b\"{M\u0000\u0010Tk񨷭Y\u0006U.AG\u0014Z򉌎򄗬񍗇c9\u000e,ojpbFMj>" + }, + "id": "0dae6bef590313895306c2ae1ae2f9337bc93d1716375abcb0d784a5" + } + ] +} \ No newline at end of file