What I’m trying to do:
Hey all- I’m in desperate need of help. I’ve spent the past 6 months building a robust AI app and am on the ‘Professional Plan’. I deployed it 4 weeks ago and it was working, but now I’m getting hit with constant "anvil.server.TimeoutError: Server code took too long"
pop up errors. I’m a mediocre programmer, and this app has grown significantly, but this still doesn’t make sense. I’ve speed up the code as fast as I can, I utilize background tasks, launchers, timers (to check for cell contents to tell me a background task is complete).
This app takes the contents of text boxes (like company name and url, ranging from 4 to 15 text boxes), and creates variables, saves the data in the table, then executes server function ‘launchers’, then executes background tasks. There’s a lot of calculations- but I still don’t know where the bottleneck is. It does calcs, executes about 3 out of 5 functions, then times out when it does that loop checking if product boxes are empty and launching that server/background task: deepdive_product_{i} etc.
What I’ve tried and what’s not working:
I’ve read the forums (believe me!). I’ve spliced up tasks, I’ve shortened code, I’ve even sent emails to sales and support asking if this is a sudden issue with their server, or if upgrading will help. I haven’t really gotten an answer.
Code Sample:
CLIENT SIDE CODE
def go_get_all_assets_click(self, **event_args):
# Stop the function if any of the fields are empty
if not self.company_name_input.text or not self.company_url_input.text
anvil.js.window.alert("Please fill in all the required fields before generating the full description.")
return
else:
# Check if the URL starts with "http" (case-insensitive)
company_url = self.company_url_input.text.strip()
product_url = self.product_1_url_input.text.strip()
if not company_url.lower().startswith("http") or not product_url.lower().startswith("http"):
anvil.js.window.alert("Company and Product URLs must include 'http'. For example, use 'https://www.apple.com/', not 'www.apple.com' ")
else:
first_run_complete_row = self.user_table.get(variable='first_run_complete')
first_run_complete_row['variable_value'] = 'yes'
first_run_complete_row.update()
# COMPANY NAME
company_name = self.company_name_input.text
self.company_name = company_name
# Save company name
company_name_row = self.user_table.get(variable='company_name')
company_name_row['variable_value'] = company_name
company_name_row.update()
# COMPANY URL
company_url = self.company_url_input.text
# Save company url
company_url_row = self.user_table.get(variable='company_url')
company_url_row['variable_value'] = company_url
company_url_row.update()
# Brand Tone
brand_tone_title = self.company_name_input.text
# Save Brand Tone
brand_tone_title_row = self.user_table.get(variable='brand_tone')
brand_tone_title_row['variable_title'] = brand_tone_title
brand_tone_title_row.update()
# LAUNCH THE TASKS
self.undertaken_tasks = [] # List to store all task IDs
self.launch_draft_company_summary_scraper(company_name, company_url, self.user_table)
self.launch_brand_tone_research(self.user_table, company_url)
self.draft_deepdive_product_generators(self.user_table, company_name)
### THIS IS THE LOOP THATS CAUSING THE ERROR
def launch_draft_deepdive_product_generators(self,user_table, company_name):
# Launch the background tasks concurrently
tasks_product_research = []
tasks_avatar = []
for i in range(1, 6):
# Get the product name and url from the textboxes
product_name_input = getattr(self, f"product_{i}_name_input").text
product_url_input = getattr(self, f"product_{i}_url_input").text
# Check if the product name is not empty and save it to the user table
if product_name_input:
product_name_row = self.user_table.get(variable=f"product_{i}_latest")
product_name_row['variable_title'] = product_name_input
product_name_row.update()
product_url_row = self.user_table.get(variable=f"product_{i}_url")
product_url_row['variable_value'] = product_url_input
product_url_row.update()
self.undertaken_tasks.append(f"product_{i}_latest")
print(f"Added to undertaken_tasks: product_{i}_latest")
self.check_all_tasks_timer.enabled = True
self.check_all_tasks_timer.interval = 3
anvil.server.call(f"launch_draft_deepdive_product_{i}_generator", self.user_table, company_name, product_name_input, product_url_input)
#task_product_research = anvil.server.call(f"launch_draft_deepdive_product_{i}_generator", self.user_table, company_name, product_name_input, product_url_input)
# print(f"product_{i} analysis initiated")
getattr(self, f"task_check_timer_product_{i}").enabled = True
# Loop through avatars 1 to 3 for each product
for j in range(1, 4):
# Get the avatar description from the textbox
avatar_input = getattr(self, f"avatar_{j}_product_{i}_input").text
# Check if the avatar description is not empty and save it to the user table
if avatar_input.strip():
print(f"Avatar {j} for product {i} input: '{avatar_input}'")
getattr(self, f"task_check_timer_product_{i}_avatar_{j}").enabled = True
# Launch the background task for Avatar
#anvil.server.call(f"launch_draft_deepdive_avatar_{j}_product_{i}_generator", j, i,self.user_table, company_name, getattr(self, f"product_{i}_name_input").text, avatar_input)
# Launch the background task for Avatar
anvil.server.call('launch_draft_deepdive_avatar_generator', j, i, self.user_table, company_name, getattr(self, f"product_{i}_name_input").text, avatar_input)
#task_id_avatar = anvil.server.call(f"launch_draft_deepdive_avatar_{j}_product_{i}_generator", self.user_table, company_name, getattr(self, f"product_{i}_name_input").text, avatar_input)
# print("Deep Dive Draft Avatar Research Started")
# Save it as the preview
variable_name = f"avatar_{j}_product_{i}_preview"
print(f"Searching for: {variable_name}")
avatar_preview_row = self.user_table.get(variable=variable_name)
if avatar_preview_row is None:
print(f"No data found for: {variable_name}")
continue
else:
avatar_preview_row['variable_value'] = avatar_input
avatar_preview_row.update()
getattr(self, f"task_check_timer_product_{i}_avatar_{j}").enabled = True
getattr(self, f"task_check_timer_product_{i}_avatar_{j}").interval = 3
# # Step 2: Append the identifier to the list
self.undertaken_tasks.append(f"avatar_{j}_product_{i}_latest")
print(f"Added to undertaken_tasks: avatar_{j}_product_{i}_latest")
SERVER SIDE CODE
# HERE'S THE FUNCTION CAUSING ISSUES...
@anvil.server.callable
def launch_draft_deepdive_product_1_generator(user_table, company_name, product_name, product_url):
anvil.server.launch_background_task('deepdive_draft_product_1_generator', user_table, company_name, product_name, product_url)
@anvil.server.background_task
def deepdive_draft_product_1_generator(user_table,company_name,product_name,product_url):
#### A BUNCH OF WORK, then when it's done...
# Save it in the table:
product_1_latest_row = user_table.search(variable='product_1_latest')[0]
product_1_latest_row['variable_value'] = product_summary
product_1_latest_row.update()
print("Product Research Complete")
Clone link:
It’s too robust to share, so I was hoping someone could share their theories?