45 lines
1.8 KiB
Scheme
45 lines
1.8 KiB
Scheme
;; utils/ssh/retry.scm - Pure retry logic
|
|
|
|
(define-module (utils ssh retry)
|
|
#:use-module (utils logging)
|
|
#:use-module (utils ssh remote-command)
|
|
#:export (with-retry
|
|
run-command-with-retry))
|
|
|
|
;; Pure function: Retry operation with exponential backoff
|
|
;; Input: operation (thunk), max-retries number, delay-fn (retry-count -> seconds)
|
|
;; Output: result of operation or #f if all retries failed
|
|
(define (with-retry operation max-retries . delay-fn)
|
|
"Pure retry logic - operation should return (values success? result)"
|
|
(let ((delay-func (if (null? delay-fn)
|
|
(lambda (retry) (* retry 2)) ; Default: exponential backoff
|
|
(car delay-fn))))
|
|
(let loop ((retries 0))
|
|
(call-with-values operation
|
|
(lambda (success result)
|
|
(if success
|
|
(values #t result)
|
|
(if (< retries max-retries)
|
|
(begin
|
|
(sleep (delay-func retries))
|
|
(loop (+ retries 1)))
|
|
(values #f result))))))))
|
|
|
|
;; Impure wrapper: Run command with retry and logging
|
|
(define (run-command-with-retry machine-name command max-retries . args)
|
|
"Run command with retry logic (with side effects: logging)"
|
|
(let ((operation (lambda ()
|
|
(apply run-remote-command machine-name command args))))
|
|
(let loop ((retries 0))
|
|
(call-with-values operation
|
|
(lambda (success output)
|
|
(if success
|
|
(values #t output)
|
|
(if (< retries max-retries)
|
|
(begin
|
|
(log-warn "Command failed, retrying (~a/~a)..." (+ retries 1) max-retries)
|
|
(sleep 2)
|
|
(loop (+ retries 1)))
|
|
(begin
|
|
(log-error "Command failed after ~a retries" max-retries)
|
|
(values #f output))))))))))
|