Server Code Took too long - Error

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

Um, we can’t see the relevant code, unless you post it here, or post a clone link, per

1 Like