What I’m trying to do:
My app has gotten a number of users and I am encountering a number of errors. I am working with Jay and Stu on them and sent an email to Anvil support, where Ryan asked me to post about them in the forums. I have checked each of these extensively and couldnt solve them, so would love support!
Error:
anvil.server.TimeoutError: Server code took too long
Occurs on a server call that deletes a row. This server call usually takes 1-2 seconds on average (timed it extensively) and is being used very regularly (its the “delete this card” call and there are 100s of cards to delete).
Session IDs:
TUBDVPMGGKJZW7VPNRD47VQP4HGHJEI5
MH5BUQJBJVUAEUYQFSX4XLJXHGA4RPDY
Here’s the code. It happened on delete_merge_learning_card:
@anvil.server.callable
def delete_merge_learning_card(session, learning_card, last_index = None, merged_lc = None, merged_html = None):
timenow = datetime.now()
logged_in_user = anvil.users.get_user()
if session['user'] != logged_in_user and logged_in_user['email'] != 'admin@gmail.com':
raise Exception('This session is not linked to the logged in user (or no user logged in).')
if learning_card['session'] != session:
raise Exception('The learning card does not belong to the current session.')
if isinstance(learning_card, dict):
# If the learning card is a dictionary, it's a newly created and not yet saved card
print('Deleting a newly created dict, no action needed')
return
try:
lc_index = learning_card['lc_index']
except anvil.tables.RowDeleted:
print(f'ERROR: LC {learning_card} has already been deleted.')
raise anvil.tables.RowDeleted('ERROR: This row has already been deleted')
# Prepare to adjust lc_index for subsequent cards
session = learning_card['session']
row_to_delete = app_tables.learning_cards.get(session=session,lc_index=lc_index)
row_to_delete.delete()
if merged_lc:
update_learning_card(session,merged_lc,merged_html)
if last_index is None:
#No lcs existed in the repeating panel anymore, Need to check if there is a next one (e.g. num lcs on page set to 1) or not.
last_index = lc_index
next_learning_card_list = get_learning_cards(session.get_id(),previous_lc_index = last_index, num_lcs = 1)
if next_learning_card_list == []:
next_learning_card = next_learning_card_list
else:
next_learning_card = next_learning_card_list[0]
print(f'Time for serverside deletion: {datetime.now()-timenow}')
return next_learning_card
@anvil.server.callable
def get_learning_cards(session_id, lc_indeces=None, first_card_index=None, previous_lc_index=None, num_lcs = 1):
#NOTE: NOT FETCHING ALL FIELDS IN SOME CASES!!!!
# returns an empty list on no rows
timenow = datetime.now()
session_row = app_tables.session_info.get_by_id(session_id)
if lc_indeces:
# Fetch learning cards by their IDs
learning_cards = app_tables.learning_cards.search(
q.fetch_only('learning_card', 'session', 'lc_index', 'lc_page_num', 'ai_generated', 'pdf_lc_index', 'previously_downloaded'),
tables.order_by("lc_index"),
session = session_row,
lc_index = q.any_of(*lc_indeces) #* unpacks the list into lc_index_1, lc_index2,...
)
elif first_card_index is not None:
# Fetch num_lcs, starting with lc_index_start
page_size = first_card_index + num_lcs
print(f'first_card_index: {first_card_index}')
print(f'num_lcs: {num_lcs}')
print(f'page size: {page_size}')
learning_cards_query = app_tables.learning_cards.search(
q.fetch_only('learning_card', 'session', 'lc_index', 'lc_page_num', 'ai_generated', 'pdf_lc_index', 'previously_downloaded'),
tables.order_by("lc_index"),
q.page_size(page_size),
session = session_row
)
learning_cards = learning_cards_query[first_card_index:page_size]
elif previous_lc_index is not None:
# fetch num_lcs with an lc_index bigger than previous_lc_index
learning_cards_query = app_tables.learning_cards.search(
q.fetch_only('learning_card', 'session', 'lc_index', 'lc_page_num', 'ai_generated', 'pdf_lc_index'),
tables.order_by("lc_index"),
q.page_size(num_lcs),
session = session_row,
lc_index = q.greater_than(previous_lc_index)
)
learning_cards = learning_cards_query[0:num_lcs]
else:
# Fetch all learning cards for the session
learning_cards = app_tables.learning_cards.search(
q.fetch_only('learning_card', 'session', 'lc_index', 'lc_page_num', 'ai_generated', 'pdf_lc_index', 'previously_downloaded'),
tables.order_by("lc_index"),
session=session_row
)
learning_cards = list(learning_cards)
#print(f"Fetching learning cards took {datetime.now() - timenow}")
if learning_cards == []:
serverside_logging.debug(f"No learning cards found for session {session_id}.")
return learning_cards
@anvil.server.callable
def update_learning_card(session, lc, new_html):
logged_in_user = anvil.users.get_user()
if session['user'] != logged_in_user and logged_in_user['email'] != 'admin@gmail.com':
raise Exception('This session is not linked to the logged in user (or no user logged in).')
if lc['session'] != session:
raise Exception('The learning card does not belong to the current session.')
lc['learning_card'] = new_html
@anvil.server.callable
def get_num_learning_cards(session_id):
session_row = app_tables.session_info.get_by_id(session_id)
learning_cards = app_tables.learning_cards.search(
q.fetch_only(),
q.page_size(5000),
session=session_row
)
num_learning_cards = len(learning_cards)
if num_learning_cards == 0:
serverside_logging.debug(f"No learning cards found for session {session_id}.")
return num_learning_cards