diff --git a/ui/src/ErrorBoundary.js b/ui/src/ErrorBoundary.js index 0f805a25f..242f73fc8 100644 --- a/ui/src/ErrorBoundary.js +++ b/ui/src/ErrorBoundary.js @@ -35,6 +35,7 @@ class ErrorBoundary extends Component { constructor(props) { super(props); + this.timer = null; this.state = { cachedError: null, reloadSeconds: 60 }; } @@ -55,7 +56,10 @@ class ErrorBoundary extends Component { }); Sentry.captureException(error); // reload after 60s, this is to fix wall monitors automatically - setInterval(this.reloadApp, 1000); + // but only if the timer isn't set yet + if (this.timer === null) { + this.timer = setInterval(this.reloadApp, 1000); + } } render() { diff --git a/ui/src/ErrorBoundary.test.js b/ui/src/ErrorBoundary.test.js index 1f050867e..f7b87412c 100644 --- a/ui/src/ErrorBoundary.test.js +++ b/ui/src/ErrorBoundary.test.js @@ -70,4 +70,19 @@ describe("", () => { expect(reloadSpy).toHaveBeenCalled(); expect(consoleSpy).toHaveBeenCalled(); }); + + it("reloadSeconds is 40 after 20s with multiple exceptions", () => { + jest.spyOn(console, "error").mockImplementation(() => {}); + const tree = MountedFailingComponent(); + const instance = tree.instance(); + + instance.componentDidCatch("foo", { foo: "bar" }); + jest.runTimersToTime(1000 * 10); + instance.componentDidCatch("foo", { foo: "bar" }); + jest.runTimersToTime(1000 * 5); + instance.componentDidCatch("foo", { foo: "bar" }); + jest.runTimersToTime(1000 * 5); + instance.componentDidCatch("foo", { foo: "bar" }); + expect(tree.instance().state.reloadSeconds).toBe(40); + }); });