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