Update table records in a label using Timer

Hello,

I am trying to make a progress notification in a label that is updated based on the entry values in table.
When I run the function that counts rows added to the table, it is like the Timer stops and only in the end of the function the label is updated with the last entry.

Below is the code used also a clone link

What am I missing in order to reflect in real time the changes from the table in the label using the Timer.

Thank you,
Besar

Code Sample:

#class Form1(Form1Template):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    now = datetime.now() 
    app_tables.table_0.add_row(rows=0,total=0,time=now,process='start')
    # Any code you write here will run before the form opens.
  def button_1_click(self, **event_args):
    #self.timer_1.interval = 2
    anvil.server.call('count')


  def timer_1_tick(self, **event_args):
    timing = anvil.server.call_s('numbers')
    progress = row['process']
    print(progress)
    if progress == 'done':
        self.timer_1.interval = 0
        t.sleep(1)
        self.label_1.text = ""

Server side

@anvil.server.callable
def count():
  time = datetime.now()
  from_zone = tz.gettz('UTC')
  to_zone = tz.gettz('Africa/Algiers')
  time = time.replace(tzinfo=from_zone)
  central = time.astimezone(to_zone)
  now = central   
  app_tables.table_0.add_row(rows=0,total=0,time=now,process='start')
  x = 0
  y = 9
  for i in range(y):
    t.sleep(3)
    x = x+1
    if x<y:
     progress = "Process"
    else:
      progress = "done"
    app_tables.table_0.add_row(rows=x,total=y,time=now,process=progress)
    print(x)
       

@anvil.server.callable
def numbers():    
  row = app_tables.table_0.search(tables.order_by('rows',ascending=False))[0]
  count = row['rows']
  total = row['total']
  print(count)
  print(total)
  
  task = f'{count} row counted on {total} Total rows'
  return task

**Clone link: **

https://anvil.works/classic-build#clone:Z27CDRIJPFHQBYLE=PQ7CH652NQOKWUOK4UN3FKCN

I think the problem is that you are calling the count server function, which will return the control to the form when itā€™s done with its job.

You should instead launch a background task, so (1) the control returns immediately back to the form and (2) it doesnā€™t crash if the background task takes longer than 30 seconds.

I would have the form calling a start_counting server function and that server function launching the count background task. You may be able to launch the background task directly from the form, maybe, I have never done it.

This should put you in the correct direction. Let me know if you need more details about launching the background task.

1 Like

FYI, ā€œBackground Tasks can only be launched from Server Modules and Uplink scripts.ā€:

Anvil Docs | Defining and Running.

1 Like

Thank you very much. I have tested and from Anvil server it works smoothly involving background task in this function , now I have to test this from uplink server how it works, or should I use background task for the Timer that is in Anvil environment

Background tasks defined in an uplink work, but I like to have the background tasks running on the Anvil server.

If I need a long background process to run in an uplink machine, I launch the background task on the Anvil server, then that task calls the function defined in the uplink.

I finally made it thank to your instructions, but now I am missing some error messages as alerts because now are showed only in App logs. Is there a way to have them shown as alerts?

Thank you

I usually have one table row per background task. The row has a status column and maybe other notes or errors columns, as described here.

You can use the Task object to communicate with background tasks as described here, but I like to use a datatable row, for many reasons, including I can search for rows with status=='running' and restart a task after it crashes.

In this case I donā€™t need the status or if the task is running, but when I have during the long function TimeoutException: Message ā€¦(instruction on how to procide) now they are shown only in App logs. Before using the Backgorund task this message was visible as alert. Now they are not visible for clients. Is any way to display this message was visible as alert?

Thank you

A Neither the uplink nor the Anvil server can show an alert on the form. Showing something on the form must initiate from the form, and using the tick event of a timer is a good option for it.

B A background task can only communicate with other functions via the Task object or via a row object.

A + B = Sorry, you do need the status.

You could wrap the whole background task like this:

try
    # do your job
except Exception as e:
    row['status'] = f'Failed: {e}'

You could even include the whole traceback if you want.

On the bright side you will never get a TimeoutException, because background tasks can work for unlimited time (unless you are on the free plan, in which case the usual 30 second limit applies).

Sorry maybe I expressed my self wrong, for alert I mean as the photo below. The Timeout is causing during selenium automation and not by function itself(Background task).

image

def error_handler(err):
user = anvil.users.get_user()
#email = user[ā€˜emailā€™]
#print(email)
#err = err
#anvil.server.call(ā€˜send_pdf_emailā€™,email,err)
alert(str(err))

set_default_error_handling(error_handler)

The server functions run in the Anvil server, the uplink code in another uplink server, the form code inside the browser.

The alert function is a function that only works in the browser, you canā€™t call it from the server or the uplink.

The only way to call an alert is from the form. And the only way to call it from the form is with an event, either triggered by an user action or by a tick event.

Your task running on the server will update a row, then the tick event running on the form will call a server function that will return the content of the status column of that row, and show it with an alert.

1 Like