At the start of a relatively large app, I want to run a background task that searches four data tables and returns four search iterators (relatively large iterators).
I would like them to return as soon as they have finished rather than wait for all to finish. The intention is to have a more efficient method for retrieving the data needed for the app to run and avoid server time outs: i.e start sending the data back from the first search as soon as it is available before the remaining searches complete.
I thought of using the task_state of a background task with four keys. Using a timer on the client side to poll the task_state and return the results as they finish.
Has anyone attempted something like this before?
What I’ve tried and what’s not working:
I have the code working with a timer that checks the task_state on the client but the task state only seems to update when the entire background task finishes. The task.get_task_state() on the client is a blank dict until the task completes. This doesn’t seem like the intended function.
If it was me, I would create 4 background task objects in your callable, returning a dictionary with keys to label each task object.
The task objects are None until they are done, so you could set up a timer that iterates through the dictionary looking for task objects that are: is not None
If you found one, return the results and clean up the dictionary for that task object.
Thanks for the response @ianb. This was my first approach and it worked but all four background tasks took longer than just one server call or one background task so it defeated the purpose. Hence why I started looking down the line of one task with multiple return points.
Is it that the background tasks run sequentially? (I have not run into a situation where I had to use multiple long running background tasks, so I am asking, I really don’t know.)
If so, what stops background_fetch() from doing the same thing?
Also I got something wrong above, I check the result of task.get_return_value() to see if it is None not the task object itself.
I am not sure if it is sequential or not - Watching the tasks complete, the shorter ones seemed to complete first but they were not launched first so I suspect not.
I wonder if my server hardware is hitting a CPU or thread limit or something (dedicated hosting but only 2 vCPUs). I am not sure of how this runs in the backend…
Just a code explanation for what we are talking about that @rickhurlbatt says is not fast for him.
(At least I think we are talking about the same thing)
@anvil.server.callable
def launch_background_fetch():
tables = [
'Table1',
'Table2',
'Table3',
'Table4',
]
return { x : anvil.server.launch_background_task('background_fetch', x ) for x in tables }
@anvil.server.background_task
def background_fetch(table_name):
b_task = getattr(app_tables, table_name).search( )
return b_task