v / cmd / tools / vretry.v
60 lines · 56 sloc · 1.52 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1import os
2import time
3import flag
4
5struct Context {
6mut:
7 show_help bool
8 timeout time.Duration
9 delay time.Duration
10 retries int
11}
12
13fn main() {
14 mut context := Context{}
15 args := os.args#[1..]
16 // dump(args)
17 mut fp := flag.new_flag_parser(args)
18 fp.application('v retry')
19 fp.version('0.0.1')
20 fp.description('Run the command CMD in a loop, until it succeeds, or until a predetermined amount of seconds pass.')
21 fp.arguments_description('CMD')
22 fp.skip_executable()
23 fp.limit_free_args_to_at_least(1)!
24 context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
25 context.timeout = fp.float('timeout', `t`, 900.0,
26 'Timeout in seconds (for all retries). Default: 900.0 seconds (15 minutes).') * time.second
27 context.delay = fp.float('delay', `d`, 1.0,
28 'Delay between each retry in seconds. Default: 1.0 second.') * time.second
29 context.retries = fp.int('retries', `r`, 10, 'Maximum number of retries. Default: 10.')
30 if context.show_help {
31 println(fp.usage())
32 exit(0)
33 }
34 command_args := fp.finalize() or {
35 eprintln('error: ${err}')
36 exit(1)
37 }
38 cmd := command_args.join(' ')
39 // dump(cmd)
40
41 spawn fn (context Context) {
42 time.sleep(context.timeout)
43 eprintln('error: exceeded maximum timeout (${context.timeout.seconds()}s)!')
44 exit(1)
45 }(context)
46
47 mut res := 0
48 for i in 0 .. context.retries {
49 res = os.system(cmd)
50 if res == 0 {
51 break
52 }
53 if i == context.retries - 1 {
54 eprintln('error: exceeded maximum number of retries (${context.retries})!')
55 exit(res)
56 }
57 time.sleep(context.delay)
58 }
59 exit(res)
60}
61