Background task any opportunity to have the output in client app?

Hello! I’m trying to write a program that at certain intervals will display the price taken from the API online (constantly updated value, the update of which the user will see).

Before that, I tried using an infinite While True loop, but my application just crashed. One of the users hinted that there are Background Tasks for this. I upgraded the plan, and wrote a function, for starters, which will simply request and display the price. But the output looks like this: LiveObject: anvil.private.BackgroundTask instead of the value the function should return.

Tell me, please, maybe there are ideas on how to implement this, maybe I’m doing something wrong:

Server module code:

@anvil.server.background_task
def getActualPrice(ticker):
  r = requests.get(f'https://api.binance.com/api/v3/ticker/price?symbol={ticker}')
  price = r.json()['price']
  return price
  

@anvil.server.callable
def launch_my_task(ticker):
  task = anvil.server.launch_background_task('getActualPrice',ticker)
  return task

Client Code:

def drop_down_crypto_change(self, **event_args):
	self.CryptoActualPrice.text = anvil.server.call('launch_my_task', ticker)

You can return an actual value by setting the background task’s task_state and accessing it on the client side with the get_state method on the background task object you already have.

See this Doc for more information:

3 Likes

Your getActualPrice(ticker) is a very fast function, there is need to make a background task for something that fast.

You can make it a callable and call that directly from the form.

1 Like

The eventual goal, based on another post (Time.sleep in anvil ), is to have that background task be running as a scheduled task so prices are polled on a regular basis. Eventually they’ll need to log the prices to a data table and have server functions that query that table.

1 Like

If that’s the case then you need to make sure things work even when you have more than one client asking for the same ticker, so you shouldn’t start the background task from the client, otherwise you end up with many background tasks running in parallel getting the same ticker value.

I would have:

  1. a table with 3 columns: ticker, the id of the client asking for it and timestamp of last read
  2. when the client needs a ticker, call a server function that adds the ticker and client id to that table
  3. a background task scheduled to run every x seconds or minutes or hours, gets the list of unique tickers from the table (ie removing the duplicates in case two clients are waiting for the same ticker), gets the prices and updates the table
  4. the tick event of a timer on the form calls a server function every few seconds to get the values from the table. When the server function returns the value to the tick event, it also updates the timestamp
  5. a second scheduled task runs every hour and deletes all the rows that have the timestamp older than a minute or an hour or whatever suggests that the client is not reading that value any longer

On step 2, if the interval for the scheduled task is longer than a few seconds, it should also launch the background task, so the value is quickly available

4 Likes

Guys, hello! @jshaffstall @stefano.menci @duncan_richards12

Thanks a lot for your ideas and help. I have already made some changes to the code and found that the background_task is executed correctly based on the logs in the editor. But there is a problem, I can’t set up the correct output in the Client App in any way. I’m requesting the price of a ticker from the API and putting that value in get_state and therefore for some reason I get only “{}” without the price.

The documentation, unfortunately, explains the output format of the get_state object very poorly. I’m sure I’m doing something wrong. Tell me, please, what’s the matter?

I am attaching a screenshot.

You can’t launch and get the returned value of a background task in the same function.

You only launch a background task when you have a long running process and you want to see the result later, after some time or after another user’s click.


If you have only one user at a time, then this is the answer for you: Background task any opportunity to have the output in client app? - #3 by stefano.menci

If you have more concurrent users, then this is: Background task any opportunity to have the output in client app? - #5 by stefano.menci

2 Likes

So, my solution is a scheduled background task with a connected database. Thanks a lot, guys!

Have you read Anvil Docs | Communicating with Background Tasks ? It expressly defines what the get_state() function returns (a dict), and how the background task can update that dict.

I did, but as you see it doesn’t work in my case, therefore I need help.