Paste: retries
Author: | erg |
Mode: | factor |
Date: | Tue, 30 Mar 2021 14:24:21 |
Plain Text |
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> retries-strategy-immediate
TUPLE: retries-strategy-random < retries-strategy lo hi ;
C: <retries-strategy-random> retries-strategy-random
TUPLE: retries-strategy-exponential < retries-strategy exp nanos ;
C: <retries-strategy-exponential> retries-strategy-exponential
TUPLE: retries count max-retries strategy ;
: <retries> ( 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 -- )
[ <retries-strategy-immediate> <retries> ] dip with-retries ; inline
: with-n-random-retries ( n lo hi quot -- )
[ <retries-strategy-random> <retries> ] dip with-retries ; inline
: with-n-exponential-retries ( n exp nanos quot -- )
[ <retries-strategy-exponential> <retries> ] 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
Author: | erg |
Mode: | factor |
Date: | Thu, 1 Apr 2021 04:03:38 |
Plain Text |
USING: accessors arrays calendar combinators combinators.extras
continuations kernel math math.functions math.parser math.ranges
namespaces prettyprint random sequences system threads ;
IN: retries
TUPLE: retries count time-strategy errors ;
: new-retries ( class -- obj )
new
0 >>count
V{ } clone >>errors ; inline
TUPLE: counted-retries < retries max-retries ;
: <counted-retries> ( time-strategy max-retries -- retries )
counted-retries new-retries
swap >>max-retries
swap >>time-strategy ; inline
TUPLE: sequence-retries < retries seq ;
: <sequence-retries> ( time-strategy seq -- retries )
sequence-retries new-retries
swap >>seq
swap >>time-strategy ; inline
GENERIC: retries* ( time-strategy seq/n -- obj )
M: integer retries* <counted-retries> ;
M: sequence retries* <sequence-retries> ;
TUPLE: time-strategy ;
TUPLE: immediate < time-strategy ;
C: <immediate> immediate
TUPLE: random-wait < time-strategy lo hi ;
C: <random-wait> random-wait
TUPLE: exponential-wait < time-strategy exp nanos ;
C: <exponential-wait> exponential-wait
GENERIC: retry-obj ( retries -- elt/obj/index retry? )
GENERIC: retry-sleep-time ( retries time-strategy -- nanos/timestamp/0 )
: next-retry ( retries -- elt/obj/index nanos/timestamp/0 ? )
{
[ retry-obj ]
[ [ ] [ time-strategy>> ] bi retry-sleep-time ]
[ pick [ [ 1 + ] change-count drop ] [ drop ] if swap ]
} cleave ;
M: immediate retry-sleep-time 2drop 0 ;
M: random-wait retry-sleep-time nip [ lo>> ] [ hi>> ] bi [a,b] random ;
M: exponential-wait retry-sleep-time [ count>> ] [ [ exp>> ^ ] [ nanos>> * ] bi ] bi* ;
: nth* ( n seq -- elt/f ? ) 2dup bounds-check? [ nth t ] [ 2drop f f ] if ;
M: counted-retries retry-obj [ count>> ] [ max-retries>> ] bi dupd < ;
M: sequence-retries retry-obj [ count>> ] [ seq>> ] bi nth* ;
SYMBOL: current-retries
ERROR: retries-failed retries quot ;
: with-retries ( retries quot -- result )
[ current-retries ] dip dup '[
[
current-retries get next-retry [
[ sleep ] unless-zero
_ [ f ] compose [
current-retries get count>>
now 4array current-retries get errors>> push f t
] recover
] [
current-retries get _ retries-failed
] if
] loop1
] with-variable ; inline
: retries ( quot time-strategy n/seq -- result )
retries* swap with-retries ; inline
[ "/bin" XATTR_NOFOLLOW swapd list-xattrs-impl ]
<immediate> { 2 4 100000 } retries .
New Annotation