I am building a photo contest website with bitcoin prizes awarded to lucky voters. Here is a link to the work in progress build: https://votegoodlooks.anvil.app/
Each election has a start and end date/time, and I would like to trigger the tallying of the ballots and allocation of the prizes when the election period ends.
I saw the Server Side Scheduled Jobs post and the suggestion to use https://www.setcronjob.com/ to periodically check if there are any elections that have recently ended will probably work, but since the elections may not take place in regular intervals it seems like it isn’t the ideal solution.
Would a constantly running background task be suitable? Or should I explore other techniques like checking if there are recently finished elections each time a user clicks on the results page and do the tallying in a just-in-time fashion?
I looked more into cronjobs and it is exactly what I want to do and it was terribly easy to implement with https://cron-job.org
here is my solution, for anyone in the future that might be searching “scheduled tasks”, “endpoint credential authorization”, " “TypeError: Unicode-objects must be encoded before hashing”
@anvil.server.http_endpoint("/check_elections",require_credentials=True)
def check_elections():
email = anvil.server.request.username
password = anvil.server.request.password
admins = app_tables.users.search(admin=True)
for admin in admins:
if email == admin['email'] and bcrypt.hashpw(password.encode('utf-8'),
admin['password_hash'].encode('utf-8')) == admin['password_hash']:
completed_elections = app_tables.election.search(END=q.less_than(datetime.datetime.now()))
for election in completed_elections:
if election['WINNERS'] is None:
election['WINNERS'] = calculate_winners(election['RESULTS'])
Thanks for the sample, I intend to use cron-job.org at some point, but haven’t gotten there yet. I’m curious, though, you pass the admin email and password in via the endpoint call. It doesn’t look like calling the endpoint can cause any harm (it only calculates winners for completed elections, and then only if the winner hasn’t already been calculated).
Does it need to be protected by an email and password? I ask because that’s a level of exposure for the credentials.
I’d always intended for my eventual cron endpoints to be okay to call at any point, and to not require credentials. Now I’m wondering if I’m missing something that I need to rethink.
hmm, that’s a great point. I think you are right. I probably don’t need to authenticate credentials in this case.
At first, it felt like good practice to protect the endpoint, but when you put it that way, perhaps the risk profile of exposing my credentials to cron-job.org is greater than if a hater was to bombard this endpoint.
Although there appears to be no material difference between the winner selection being triggered by a malicious/curious person/bot instead of our scheduled task, I decided to keep the authentication but only from an account that has no other admin capabilities other than authenticating chron jobs.
This will help prevent endpoint funny business while reducing the consequence of a potential chron-job.org breach of trust.
Can Anvil Scheduled Tasks run scheduled tasks at time stored in data table?
I haven’t found a way to do so since what available is to run every minutes/hours …
12 times a day, an action is to be done at a specific time. The task can be done by an authorised personel clicking a button to triger code. Scheduled task running every minute is kind of overkill since there are a lot of data while every hour doesn’t meet the requriment.
True, @stefano.menci, if only one app is doing it. But over many apps, all the behind-the-scenes work adds up: firing up a (light) vm, loading the interpreter, loading the source code, connecting to the database, querying a database table, … to complete a test that will fail 99% (or more) of the time.
Compare that to running one task, and then only when needed.
If your traffic is 1 request per minute, then adding this background task will double the server load (actually less, because real requests will do much more than checking one row on a table) and reach 2 requests per minute. This is a very very very low load on the server.
If your traffic is hundreds of requests per minute, then adding this background task will add less than 1% to the load.
I agree, it would be nice to be able to schedule tasks from code and it doesn’t feel right to have this task running so often doing nothing. But I use Anvil because it makes my life easy, not the server life. If I wanted to be nice on the server I would work in C++ rather than Python, I would have my own server and manage the full stack, and save 90% of the load. Instead I work in the very slow Python and I leave everything else to the Anvil team. I end up with apps served from UK and used by US clients. That’s really horrible, much worse than wasting 0.1 second per minute, but I love it because it saves 90% of my time.
PS: If you keep the server running then the interpreter doesn’t need to fire up every time.