|
102 | 102 |
|
103 | 103 | (def max-pending-lifecycle-events 5) |
104 | 104 |
|
| 105 | +;; Some init systems can deliver duplicate HUP events for a single reload |
| 106 | +;; request. Debounce at the signal handler boundary to avoid back-to-back |
| 107 | +;; restart cycles that can interrupt in-flight agent requests. |
| 108 | +(def min-sighup-restart-interval-ms 500) |
| 109 | +(def last-sighup-restart-ms (atom nil)) |
| 110 | + |
| 111 | +(defn now-ms [] |
| 112 | + (System/currentTimeMillis)) |
| 113 | + |
| 114 | +(defn should-handle-sighup-restart? |
| 115 | + [] |
| 116 | + (let [current-ms (now-ms) |
| 117 | + accepted? (atom false)] |
| 118 | + (swap! last-sighup-restart-ms |
| 119 | + (fn [last-ms] |
| 120 | + (if (and (some? last-ms) |
| 121 | + (< (- current-ms last-ms) min-sighup-restart-interval-ms)) |
| 122 | + last-ms |
| 123 | + (do |
| 124 | + (reset! accepted? true) |
| 125 | + current-ms)))) |
| 126 | + @accepted?)) |
| 127 | + |
| 128 | +(defn app-log-id |
| 129 | + [app] |
| 130 | + (str "app=0x" (Integer/toHexString (System/identityHashCode app)))) |
| 131 | + |
105 | 132 | (defn service-graph? |
106 | 133 | "Predicate that tests whether or not the argument is a valid trapperkeeper |
107 | 134 | service graph." |
|
368 | 395 | [apps] |
369 | 396 | (log/info (i18n/trs "SIGHUP handler restarting TK apps.")) |
370 | 397 | (doseq [app apps] |
| 398 | + (log/info (i18n/trs "Queueing SIGHUP restart for TK {0}" (app-log-id app))) |
371 | 399 | (let [{:keys [lifecycle-channel]} @(a/app-context app) |
372 | 400 | restart-fn #(a/restart app)] |
373 | 401 | (when-not (async/offer! lifecycle-channel |
|
376 | 404 | (log/warn (i18n/trs "Ignoring new SIGHUP restart requests; too many requests queued ({0})" |
377 | 405 | max-pending-lifecycle-events)))))) |
378 | 406 |
|
| 407 | +(defn maybe-restart-tk-apps |
| 408 | + "Restart all TK apps unless this SIGHUP request is a rapid duplicate." |
| 409 | + [apps] |
| 410 | + (if (should-handle-sighup-restart?) |
| 411 | + (restart-tk-apps apps) |
| 412 | + (log/warn (i18n/trs "Ignoring duplicate SIGHUP restart request received within {0} ms" |
| 413 | + min-sighup-restart-interval-ms)))) |
| 414 | + |
379 | 415 | (defn register-sighup-handler |
380 | 416 | "Register a handler for SIGHUP that restarts all trapperkeeper apps. The |
381 | 417 | default handler terminates the process, so we always overwrite that. This |
|
384 | 420 | (register-sighup-handler @tk-apps)) |
385 | 421 | ([apps] |
386 | 422 | (log/debug (i18n/trs "Registering SIGHUP handler for restarting TK apps")) |
387 | | - (reset! (beckon/signal-atom "HUP") #{(partial restart-tk-apps apps)}))) |
| 423 | + (reset! (beckon/signal-atom "HUP") #{(partial maybe-restart-tk-apps apps)}))) |
388 | 424 |
|
389 | 425 | ;;;; Application Shutdown Support |
390 | 426 | ;;;; |
|
767 | 803 | this))) |
768 | 804 | (a/restart [this] |
769 | 805 | (try |
| 806 | + (log/info (i18n/trs "Starting restart for TK {0}" (app-log-id this))) |
770 | 807 | (notice-service-reloading) |
771 | 808 | (run-lifecycle-fns app-context s/stop "stop" (reverse ordered-services)) |
772 | 809 | (doseq [svc-id (keys services-by-id)] (swap! app-context assoc-in [:service-contexts svc-id] {})) |
|
775 | 812 | (run-lifecycle-fns app-context s/start "start" ordered-services) |
776 | 813 | (enable-ready-notifications-for-app! services-by-id) |
777 | 814 | (notice-service-ready-if-uncoordinated! services-by-id) |
| 815 | + (log/info (i18n/trs "Finished restart for TK {0}" (app-log-id this))) |
778 | 816 | (inc-restart-counter! this) |
779 | 817 | this |
780 | 818 | (catch Throwable t |
|
0 commit comments