! Copyright (C) 2021 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel math math.functions math.ranges namespaces random threads ; IN: retries TUPLE: retries-strategy ; TUPLE: retries-strategy-immediate < retries-strategy ; C: retries-strategy-immediate TUPLE: retries-strategy-random < retries-strategy lo hi ; C: retries-strategy-random TUPLE: retries-strategy-exponential < retries-strategy exp nanos ; C: retries-strategy-exponential TUPLE: retries count max-retries strategy ; : ( max-retries strategy -- retries ) retries new 0 >>count swap >>strategy swap >>max-retries ; inline : retry? ( retries -- ? ) [ count>> ] [ max-retries>> ] bi < ; GENERIC: next-retry ( retries retry-strategy -- nanos/timestamp ) M: retries-strategy-immediate next-retry 2drop 0 ; M: retries-strategy-random next-retry nip [ lo>> ] [ hi>> ] bi [a,b] random ; M: retries-strategy-exponential next-retry [ count>> ] [ [ exp>> ^ ] [ nanos>> * ] bi ] bi* ; SYMBOL: current-retries ERROR: retries-failed retry quot ; : with-retries ( retries quot -- ) [ current-retries ] dip dup '[ [ current-retries get dup retry? [ [ dup strategy>> next-retry [ dup number>string "sleeping " prepend . sleep ] unless-zero @ ] keep swap [ drop f ] [ [ 1 + ] change-count drop t ] if ] [ _ retries-failed ] if ] loop ] with-variable ; inline : with-n-immediate-retries ( n quot -- ) [ ] dip with-retries ; inline : with-n-random-retries ( n lo hi quot -- ) [ ] dip with-retries ; inline : with-n-exponential-retries ( n exp nanos quot -- ) [ ] dip with-retries ; inline 10 [ 5 random dup . 30 = ] with-n-immediate-retries 10 500,000,000 1,000,000,000 [ 5 random dup . 30 = ] with-n-random-retries 10 1.5 100,000,000 [ 5 random dup . 30 = ] with-n-exponential-retries