mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
✨ Report update loops throttled by the update scheduler
When the scheduler throttles an update loop, it only logs a console warning, so a loop that no longer crashes leaves no trace. Send an error report too, with the events in flight and the last events, at most once per report window. Relates to #12580 AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
379470bdd2
commit
eeb89aecab
@ -438,17 +438,30 @@
|
||||
(volatile! 0))
|
||||
|
||||
(defn on-update-loop
|
||||
"Handler for the rumext update scheduler trips: logs the throttled
|
||||
update loop with the events being processed, at most once per
|
||||
"Handler for the rumext update scheduler trips: logs and reports the
|
||||
throttled update loop with the events being processed, at most once per
|
||||
`report-window-ms`. Runs inside store watchers and effect bodies, so it
|
||||
never throws."
|
||||
[_]
|
||||
[{:keys [rounds]}]
|
||||
(try
|
||||
(let [now (inst-ms (ct/now))]
|
||||
(when (>= (- now @update-loop-warned-at) report-window-ms)
|
||||
(vreset! update-loop-warned-at now)
|
||||
(.warn js/console "[update-scheduler] update loop throttled; in-flight events:"
|
||||
(into-array (map ptk/repr-event (ptk/in-flight-events st/state))))))
|
||||
(let [events (ptk/in-flight-events st/state)
|
||||
cause (ex-info "update loop throttled"
|
||||
{:type :internal
|
||||
:code :update-loop-throttled
|
||||
:rounds rounds})]
|
||||
(.warn js/console "[update-scheduler] update loop throttled; in-flight events:"
|
||||
(into-array (map ptk/repr-event events)))
|
||||
(when (seq events)
|
||||
(.set in-flight-by-cause cause (in-flight-lines events)))
|
||||
;; Report outside the loop that tripped the scheduler
|
||||
(ts/schedule
|
||||
#(submit-report :event-name "handled-exception"
|
||||
:hint (ex-message cause)
|
||||
:report (fn [] (generate-report cause))
|
||||
:cause cause)))))
|
||||
(catch :default _
|
||||
nil)))
|
||||
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
- events in flight – the full report lists the events the
|
||||
store was processing when it caught the exception; a failing stream
|
||||
pipeline lists the emitters of the value, not its own event
|
||||
- on-update-loop – never throws into the scheduler's caller
|
||||
- on-update-loop – never throws into the scheduler's caller;
|
||||
reports the throttled loop with the events in flight
|
||||
- flash schedules async report and toast – neither the report nor
|
||||
ntf/show is emitted synchronously
|
||||
- organization SSO recovery – expired SSO sessions go back to the provider
|
||||
@ -554,6 +555,28 @@
|
||||
{ptk/in-flight-events (fn [_] (throw (js/Error. "in-flight read failure")))}
|
||||
(t/is (nil? (errors/on-update-loop {:rounds 26}))))))
|
||||
|
||||
(t/deftest ^:async update-loop-is-reported-with-the-events-in-flight
|
||||
(errors/reset-report-governor!)
|
||||
(vreset! @#'errors/update-loop-warned-at 0)
|
||||
(let [events (atom [])
|
||||
loop-ev (ptk/reify ::test-update-loop-source)]
|
||||
(await
|
||||
(mock/with-mocks*
|
||||
{st/emit! (mock/stub (fn [& emitted] (swap! events into emitted)))
|
||||
ptk/in-flight-events (fn [_] [loop-ev])
|
||||
st/format-last-events (mock/stub (fn [& _] "(stub last events)"))
|
||||
rt/get-current-href (constantly "https://penpot.example.com/#/workspace")
|
||||
tm/schedule (mock/stub (fn [f] (f)))}
|
||||
(errors/on-update-loop {:rounds 26})
|
||||
;; A second trip within the window is not reported again
|
||||
(errors/on-update-loop {:rounds 26})
|
||||
(t/is (= 1 (count @events)))
|
||||
(let [props (deref (first @events))]
|
||||
(t/is (= "handled-exception" (::ev/name props)))
|
||||
(t/is (= "update loop throttled" (:hint props)))
|
||||
(t/is (str/includes? (in-flight-section (:report props))
|
||||
"test-update-loop-source")))))))
|
||||
|
||||
;; ---------------------------------------------------------------------------
|
||||
;; Expired organization SSO session
|
||||
;;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user