syndicate-rkt/syndicate/distributed/heartbeat.rkt

41 lines
1.4 KiB
Racket

#lang imperative-syndicate
(provide heartbeat)
(require "wire-protocol.rkt")
(require/activate imperative-syndicate/drivers/timer)
(define-logger syndicate/distributed)
;; TODO: move heartbeats to transport level, and use separate transport-activity timeouts from
;; message-activity timeouts. Using message-activity only has problems when messages are large
;; and links are slow. Also, moving to transport level lets us use e.g. WebSocket's ping
;; mechanism rather than a message-level mechanism.
(define (heartbeat who send-message teardown)
(define period (ping-interval))
(define grace (* 3 period))
(log-syndicate/distributed-debug
"Peer ~v heartbeat period ~ams; must not experience silence longer than ~ams"
who period grace)
(field [next-ping-time 0]) ;; when we are to send the next ping
(field [last-received-traffic (current-inexact-milliseconds)]) ;; when we last heard from the peer
(define (schedule-next-ping!)
(next-ping-time (+ (current-inexact-milliseconds) period)))
(on (asserted (later-than (next-ping-time)))
(schedule-next-ping!)
(send-message (Ping)))
(on (asserted (later-than (+ (last-received-traffic) grace)))
(log-syndicate/distributed-info "Peer ~v heartbeat timeout after ~ams of inactivity"
who grace)
(teardown))
(lambda ()
(schedule-next-ping!)
(last-received-traffic (current-inexact-milliseconds))))