Hello, hope you are all well. I am getting error: server took too long. But all code are correct then how to solve this error?
Thanks is advance
There is a 30 second limit on the server, your functions need to return before then.
You can:
-
Make your code run in less than 30 seconds, or chunk it into <30 seconds of processing at a time while storing the results to be aggregated together later (in a data table or returned to the client)
-
If you are on the free plan you can use
anvil-uplink
to run code longer than 30 seconds on any machine you control that is not anvil. -
If you are on a paid plan you can use a background task to exceed the 30 second limit, but using them is slightly more complex than a normal server call.
(You can also still useanvil-uplink
as well, obviously)
First it was working fine, but now it gives this error on few server request like signup with email and password but its still working for few other requests like signup with google? Right now I am now on paid version of anvil.
Client side code:
def button_1_click(self, **event_args):
email = self.email.text
password = self.password.text
confirm_password = self.confirm_password.text
if password == confirm_password:
try:
# Call server function to initiate OTP verification
result= anvil.server.call('initiate_otp_verification', email, password, _async=True, _timeout=30)
if result:
# Open the MFASetupForm and pass the email argument
open_form('MFASetupForm', email=email)
else:
alert("Failed to initiate OTP verification")
except Exception as e:
alert(f"Error1: {str(e)}")
else:
alert("Passwords do not match")
def button_google_click(self, **event_args):
try:
anvil.users.signup_with_google()
open_form("Dashboard")
except Exception as e:
alert(f"Error: {str(e)}")
server side code:
def generate_otp(length=6):
"""Generate a random OTP code of a given length."""
digits = string.digits
otp = ''.join(random.choice(digits) for _ in range(length))
logging.info(f"Generated OTP: {otp}")
return otp
def hash_password(password):
"""Hash a password for secure storage."""
return hashlib.sha256(password.encode()).hexdigest()
@anvil.server.callable
def save_otp_to_database(email, otp, password):
"""Save OTP and password to the database."""
try:
hashed_password = hash_password(password)
row = app_tables.otp_verifications.get(email=email)
if row:
row.update(otp=otp, password=hashed_password)
else:
app_tables.otp_verifications.add_row(email=email, otp=otp, password=hashed_password)
logging.info(f"Saved OTP {otp} and hashed password for {email} to database")
except Exception as e:
logging.error(f"Error saving OTP to database: {e}")
@anvil.server.callable
def send_otp_email(email, otp):
"""Send OTP code to user's email using Anvil Email Service."""
try:
subject = "Your OTP Code"
message = f"Your OTP code is: {otp}"
anvil.email.send(to=email, subject=subject, text=message)
logging.info(f"Email sent to {email} with OTP {otp}")
except Exception as e:
logging.error(f"Error sending email to {email}: {e}")
@anvil.server.callable
def initiate_otp_verification(email, password):
print("error1")
try:
logging.info(f"Initiating OTP verification for {email}")
# Generate OTP
otp = generate_otp()
# Save OTP and email to the database
save_otp_to_database(email, otp, password)
logging.info(f"Generated OTP: {otp}")
# Send OTP to user's email
send_otp_email(email, otp)
logging.info("OTP email sent")
return True
except Exception as e:
logging.error(f"Error in initiate_otp_verification: {e}")
return str(e)
@anvil.server.callable
def verify_otp(email, otp):
try:
row = app_tables.otp_verifications.get(email=email)
if row and row['otp'] == otp:
# Save user credentials to the users table
app_tables.users.add_row(email=email, password=row['password'])
row.delete()
logging.info(f"OTP verified and user {email} added to users table")
return True
logging.warning(f"Invalid OTP for {email}")
return False
except Exception as e:
logging.error(f"Error verifying OTP: {e}")
return False
@anvil.server.callable
def signup_user(email, password):
try:
print("signup is working")
# Attempt to create a new user with the provided email and password
user = anvil.users.signup_with_email(email, password)
time.sleep(120)
return True # Return True if signup is successful
except anvil.users.AuthenticationFailed as e:
logging.error(f"Signup failed for {email}: {e}")
return False
I am not quite sure what is taking so long, perhaps you should print out some elapsed time statements with something like time.perf_counter()
Are you importing any large libraries in any of your server modules? Every time you launch a server request, all of that code loads. If for example, the imports take 25+ seconds, then you only have 5 seconds left to run your “fast” code.
I am not sure what these extra parameters do or are for.
I see you are storing passwords a sha256, you should probably be using bcrypt
instead, it is included standard in anvil and automatically salts the hash.
This is what I got after performing these steps, still same issue
Running initial tests…
Python version: 3.10.14 (main, May 14 2024, 08:51:34) [GCC 10.2.1 20210110]
Python version: 3.10.14 (main, May 14 2024, 08:51:34) [GCC 10.2.1 20210110]
Testing time.perf_counter() in test_time_perf_counter
Elapsed time: 1.0011 seconds
Elapsed time for test: 1.0011448673903942
Error: Server code took too long
How to adjust anvil default timing of 30 seconds?
Try having the client print time.time()
and then having the very first function you are calling also print time.time()
If the numbers are more than 30 seconds apart, then the server is taking almost or more than 30 seconds to start, and it is not the code you wrote, but the imports that have to run when the server spins up at each server call.
This might not be the answer, but it will at least rule out:
Yes, as i am have to authenticate user and as well as to integrate api so that’s why large libraries are imported
I have use print time.time() but still server code took too long
Try this to see if it works around the problem. It may or may not be your permanent solution but if it works it will quickly tell you that your imported modules are the culprit:
It looks like you misunderstood the goal of printing the timestamps.
It doesn’t make things go faster.
By subtracting two timestamps, you can get the elapsed time between them, i.e., how much time elapsed between the first and second print. By printing a bunch of different timestamps, at different places along your code’s execution path, and computing those differences, you can use the differences to estimate where your code is spending most of its time, i.e., which is the slowest part of it.
I am making scanning system. All the front screens like login and signup work without errors but as the scanning task is heavy on server side so it gives error server code took too long. Can you guys tell me what to do about it? As I have to submit my project soon.
Thanks in advance.
Is this printed on the client or server side?
What is the code that runs on the server side?
Are you using background tasks or calling server functions?
In other words, if you provide more info, it will be easier possible to help you.