Unlocking New Workflows with Background Tasks
What is a background task and how can it help you build better apps?
Masen Furer
·
Reflex just released v0.2.8 earlier last week and with it, one of the most exciting features I've worked on: background tasks.
Why?
If you're a current developer of Reflex apps, you've no doubt noticed that slow events block the UI from receiving input. This is because Reflex intentionally processes events one at a time. While this is great for keeping your app's state consistent, it can be frustrating when you need to execute a long-running task and still keep the UI interactive and responsive to user input.
In previous releases, the main way to retain interactivity while running a long
task was to explicitly chain steps of the calculation together using yield
or
return
statements.
The following code example defines State.get_post
which recursively queues itself
to fetch 10 posts from an API, while still allowing over queued events to be
processed in between.
This works okay for some types of problems, but it complicates the code, hindering readability and future maintenance. Further, the event queue is still blocked while each step in the process runs. So while this does allow for some interactivity, it's not a complete solution.
Enter background tasks...
A background task is a special type of async EventHandler
that may run
concurrently with other EventHandler
functions. They mostly work like normal
EventHandler
functions on a State, however they must be async
and they
cannot directly modify the state.
Wait a sec... if they cannot modify the state, how are they useful?
Well, a background task can modify the state, but only inside of an async with self
context block. Python 3.7 added support for async contextmanagers,
and Reflex takes advantage of this feature to provide a safe way to modify the
state from a background task.
So what does async with self
actually do?
When a background task enters an async with self
context block, it refreshes
the state instance and takes an exclusive lock on it.
- Inside the context block, the background task is guaranteed that
self
has the latest values and no otherEventHandler
functions are modifying the state.
- After exiting the context block, an update is sent to the frontend to reflect the new state, and the lock is released, allowing any queued events to be processed.
- Outside of the context block, the state may be stale, but other event handlers
can execute while the task is
await
ing long-running processes.
Using Background Tasks
Rewriting the example above shows how background tasks work in practice:
The background task can fetch all of the posts while allowing the app to continue processing UI events in the foreground. The only time the UI is blocked is during the short period of time where the response is being appended to the state.
For a more complete example with comparisons of the two styles, see the
random-number-range
app in the
reflex-examples
repository.
Parallelizing Work
Aside from UI interactivity, the other motivation for using background tasks is to parallelize work within the app. For example the user can be monitoring responses from several API calls at once. Or the app can define different background tasks for a multi-view dashboard UI and have separate portions of the screen updating and processing simultaneously.
Full code for this example is available in reflex-examples/lorem-stream.
Next Steps
Background tasks is a powerful new feature that enables you to build long-running workflows that can respond to user input in real time. We hope you find unique and creative ways to use them in your apps.
Please see the docs for more information on background tasks and check out the complete v0.2.8 release notes for all the new features and bug fixes.
🔧 Happy Building 🚀
-- Reflex Team
More Posts
New Core Graphing Components
Using Reflex's new core graphing feature to build a live streaming graphing app.
Alek Petuskey
Announcing our Seed Round
Reflex has raised a $5M seed led by Lux Capital.
Reflex Team
Pynecone is now Reflex
We have some exciting news to share about the next stage of our company!
Nikhil Rao