diff --git a/README.md b/README.md index e0de10c..146f962 100644 --- a/README.md +++ b/README.md @@ -1076,7 +1076,7 @@ If you have that data, then you can reproduce the exception. re-frame allows you to time travel. Install the "checkpoint" state into `app-db` and then "play forward" through the collection dispatched events. -The only way the system "moves forwards" is via events. "Replaying events" moves you +The only way the app "moves forwards" is via events. "Replaying events" moves you step by step towards the exception causing problem. This is utterly, utterly perfect for debugging assuming, of course, you are in a position to capture @@ -1100,45 +1100,25 @@ modify `app-db` themselves. That is always done in a handler. to dispatch their outcome. All events are handled via dispatch. on-success should never ever change `app-db`. +## The CPU Hog Problem -### The CPU Hog +Sometime a handler has a lot of CPU intensive work to do, and it takes a while to get through. -If a handler hogs the CPU, this will freeze the GUI - browsers -only give us one thread of execution. +When a handler hogs the CPU, nothing else can happen. Browsers only give us one thread of +execution and that CPU-hogging handler owns it, and it isn't giving it up. The UI will be +frozen and there will be +no processing of any other handlers (eg: on-success of POSTs), etc, etc. Nothing. -Long running handlers must somehow hand control -back to the GUI every so often, while still continuing on with the -computation when the GUI update work has been done. +And a frozen UI is a problem. GUI repaints are not happening. And user interactions are not being processed. -Luckily re-frame has a fairly easily solution. +How are we to show progress updates like "Hey, X% completed"? Or how can we handle the +user clicking on that "Cancel" button trying to stop this long running process? -First, you have to organise for your handler to break up the work into chunks. -After each chunk is done, a handler should not go on to the next, and instead it should -re-dispatch to itself an event which (1) says the work is not finished; and -(2) supplies the work completed so far, along with info about the chunk to be -undertaken next. +We need a means by which long running handlers can hand control +back for "other" processing every so often, while still continuing on with their +computation. -The event handler will then do another chunk, before `dispatching` to itself again, -and so on. - -In between each `dispatch`, re-frame hands back -control to the GUI thread, so it can render any pending updates, -before then continuing on to handle -the next dispatched event, which in our case would be the next chunk of work. - -At a certain point, when all the work is done, the handler will likely put the -fruits of its labour into `app-db` and clear any flags which might, for example, -cause a modal dialog to be displayed explaining progress. - -This arrangement is nice and flexible. For example, -in some cases, your modal dialog explaining progress might have a "cancel" button. If clicked, this -button will dispatch a cancel event and the handler for the event will tweak the `app-db` -indicating that that computation should be abandoned. When a chunk-processing-handler -next begins, it will check the cancel flag, and, if it is found, will -stop the CPU intensive process. - -Events arriving from a server might also cause the calculation to have to be restarted, -or modified. This is all fairly easily handled within the chunked dispatch approach just described. +Luckily, [re-frame has a solution](https://github.com/Day8/re-frame/wiki/The-CPU-Hog-Problem). ### In Summary