Communication with background task

I’m having a problem to establish the communication with the backgroun task.

  1. start the task on client side
  2. return task to the client side and start timer
  3. let timer check the status and progress.

For my previous background tasks I was using database to store the data from the task. But now I would like to use it right away. For some reason I can’t get anything back from the task.
It’s always None

I’ve tried so far:

  • anvil.server.task_state['progress'] = 'yes' server side
    client side: state = self.task.get_state() test = state.get('progress')
    just some pointless message to test it. returning only None or default value if set
  • found_rows = self.task.get_return_value() If I get it correctly, it should return me the return from the background task? The result was too always only None. The task was completed so it shouldn’t be None.
  • get_return_value(): returns the return value of the task, or None if the task has not yet returned.

client side:

class progressminature(progressminatureTemplate):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    list_barcodes = common.list_to_search_scan_in_tool
    barcode_type = common.search_type_barcode
    task = anvil.server.call('get_sample_database_scan_in_tool', list_barcodes, barcode_type)
    self.task = task
      
    
  def timer_1_tick(self, **event_args):
    """This method is called Every [interval] seconds. Does not trigger if [interval] is 0."""
    with anvil.server.no_loading_indicator:
      # Show progress
      state = self.task.get_state()
      test = state.get('progress')
      print (test)
      if self.task.is_running():
        self.timer_1.interval = 0
        #found_rows = state.get('date')
        found_rows = self.task.get_return_value()
        print (found_rows)

server side:

@anvil.server.callable
def get_sample_database_scan_in_tool(list_barcodes, barcode_type):
  task = anvil.server.launch_background_task('background_get_sample_database_scan_in_tool',list_barcodes, barcode_type)
  return task


@anvil.server.background_task
def background_get_sample_database_scan_in_tool(list_barcodes, barcode_type):
  """fetch the basic data of samples"""
  anvil.server.task_state['progress'] = 'yes'
  if barcode_type == 'internal':
    database = app_tables.sample_database.search(q.fetch_only("barcode", "study_id","name","status","matrix","ext_barcode",
                                                            "volume","order_number","comment",updated_by=q.fetch_only("email")),barcode=q.any_of(*list_barcodes))
    total_count = len(database)#total count found
    
  elif barcode_type == 'external':

    database = app_tables.sample_database.search(q.fetch_only("barcode", "study_id","name","status","matrix","ext_barcode",
                                                            "volume","order_number","comment",updated_by=q.fetch_only("email")),ext_barcode=q.any_of(*list_barcodes))
    total_count = len(database)#total count found
  return database

Hi @KR1,

The approach you’re taking ought to work! Can you provide a stripped-down sample app that demonstrates it not working?

1 Like

For setting found_rows above, it looks to me like you might be confusing return value and task state. If I read the documentation correctly, as long as the task is running – the condition specified in your if above – then it has not returned yet, so its return value will necessarily be None.

If you want results from the task while self.task.is_running() is True, then

  1. the task should update its anvil.server.task_state with those (partial) results, and
  2. the client should call self.task.get_state() each time it needs to get the latest state.

Caution: I personally haven’t used background tasks in this way (yet). Others have. Please correct me if I’m misreading things.

For setting found_rows above, it looks to me like you might be confusing return value and task state . If I read the documentation correctly, as long as the task is running – the condition specified in your if above – then it has not returned yet, so its return value will necessarily be None.

Yes, that is why that part with if statement is at the beginning of the timer func.
if self.task.is_running():
The code you are reffering to won’t be processed as long it’s still running.
I was playing little around to find why it’s not working. That is why it is so messy.

I want to use both. get_state() to update the user about the progress (change in the text of my form Searching 0% → Searching 100%) and as soon as it is completed get_return_value() to get the final data.

clone link:
Striped to the background task only. Barcodes for testing saved in the module barcodes.
Sorry for the 30.000 row sample database. It was required for the full func. test.

Wouldn’t that require a not before self.task.is_running() ?

1 Like

You are right about it… That happens if you sit too long and look at the same code.
else: is missing there. Thank you very much for your help. I was really blind at this point.

That explains why I couldn’t get the data. it wasn’t truly finished. Pasted 10.000 barcodes and he lost connection to the task and timer shut down.

  def timer_1_tick(self, **event_args):
    """This method is called Every [interval] seconds. Does not trigger if [interval] is 0."""
    with anvil.server.no_loading_indicator:
      # Show progress
      if self.task.is_running():
        state = self.task.get_state()
        test = state.get('progress')
        print (test)
      else:
        self.timer_1.interval = 0
        self.button_1.background = '#1F8008'
        self.button_1.foreground = '#FFFFFF'
        self.button_1.text = 'Completed'
        state = self.task.get_state()
        Notification("List view generated, no problems found",
                      title="Generation completed",
                      style="success", timeout=3).show()
        found_rows = self.task.get_return_value()
        print (found_rows)

Output:
image

That’s happened to all of us more times than we might admit… :weary:

1 Like