Background processes

Many workflows provide a convenient interface to applications and/or web services.

For performance reasons, it’s common for workflows to cache data locally, but updating this cache typically takes a few seconds, making your workflow unresponsive while an update is occurring, which is very un-Alfred-like.

To avoid such delays, Alfred-PyWorkflow provides the background module to allow you to easily run scripts in the background.

There are two functions, run_in_background() and is_running(), that provide the main interface. The processes started are full daemon processes, so you can start real servers as easily as simple scripts.

Here’s an example of a common usage pattern (updating cached data in the background). What we’re doing is:

  1. Checking the age of the cached data and running the update script via run_in_background() if the cached data are too old or don’t exist.

  2. (Optionally) informing the user that data are being updated.

  3. Loading the cached data regardless of age.

  4. Displaying the cached data (if any).

 1 from workflow import Workflow, ICON_INFO
 2 from workflow.background import run_in_background, is_running
 3
 4 def main(wf):
 5     # Is cache over 1 hour old or non-existent?
 6     if not wf.cached_data_fresh('exchange-rates', 3600):
 7         run_in_background('update',
 8                           ['/usr/bin/env', 'python3',
 9                            wf.workflowfile('update_exchange_rates.py')])
10
11     if is_running('update'):
12         # Tell Alfred to run the script again every 0.5 seconds
13         # until the `update` job is complete (and Alfred is
14         # showing results based on the newly-retrieved data)
15         wf.rerun = 0.5
16         # Add a notification if the script is running
17         wf.add_item('Updating exchange rates...', icon=ICON_INFO)
18
19     # max_age=0 will load any cached data regardless of age
20     exchange_rates = wf.cached_data('exchage-rates', max_age=0)
21
22     # Display (possibly stale) cache data
23     if exchange_rates:
24         for rate in exchange_rates:
25             wf.add_item(rate)
26
27     # Send results to Alfred
28     wf.send_feedback()
29
30 if __name__ == '__main__':
31    # Use Workflow so we can use Alfred 3's awesome `rerun` feature
32    wf = Workflow()
33    wf.run(main)

For a working example, see Part 2 of the Tutorial or the source code of my Git Repos workflow, which is a bit smarter about showing the user update information.