SuffolkLITLab / docassemble-AssemblyLine

Quickly go from a paper court form to a runnable, guided, step-by-step web application powered by Docassemble. Swap out branding and pre-built questions to meet your needs.
https://suffolklitlab.org/docassemble-AssemblyLine-documentation/
MIT License
41 stars 5 forks source link

Stop updating the metadata multiple times per page load #773

Open BryceStevenWilley opened 11 months ago

BryceStevenWilley commented 11 months ago

Since https://github.com/SuffolkLITLab/docassemble-AssemblyLine/pull/747, I've noticed that the the block that updates metadata happens multiple times on the same page load. This routinely lengthens page load times to 0.3 or 0.5 seconds. By itself it's not much, but it is a small irk, does make page load times longer when they don't need to be.

We should check if there's a way to only run initial blocks once per screen load. It's not clear why it's running multiple times IMO.

initial: True
code: |
  ########### Save title and progress to session list ##################
  if get_config("assembly line",{}).get("update session metadata", True):
    al_temp_metadata = get_interview_metadata(
      user_info().filename, user_info().session
    )
    al_temp_metadata["auto_title"] = str(al_sessions_interview_title)
    al_temp_metadata["progress"] = get_progress()
    set_current_session_metadata(al_temp_metadata)
    del(al_temp_metadata)
Full DA stack dump
How question came to be asked
Ran initial code at 0.00000s

(from al_language.yml)

initial: True
code: |
  if enable_al_language:
    set_language(al_user_language)

Ran initial code at 0.00005s

(from al_saved_sessions.yml)

initial: True
code: |
  ########### Save title and progress to session list ##################
  if get_config("assembly line",{}).get("update session metadata", True):
    al_temp_metadata = get_interview_metadata(
      user_info().filename, user_info().session
    )
    al_temp_metadata["auto_title"] = str(al_sessions_interview_title)
    al_temp_metadata["progress"] = get_progress()
    set_current_session_metadata(al_temp_metadata)
    del(al_temp_metadata)

Needed definition of al_sessions_interview_title at 0.00096s
Tried to run block at 0.00110s

(from al_saved_sessions.yml)

template: al_sessions_interview_title
content: |
  % if defined('users[0].name.first'):
  ${ comma_and_list(users.complete_elements()) }
  % if defined('other_parties[0].name.first'):
  v. ${ comma_and_list(other_parties.complete_elements()) }
  % endif
  % else:
  ${ all_variables(special='titles').get('full') }
  % if all_variables(special='titles').get('sub'):
  : ${ all_variables(special='titles').get('sub') }
  % endif
  % endif

Ran initial code at 0.00127s

(from al_language.yml)

initial: True
code: |
  if enable_al_language:
    set_language(al_user_language)

Ran initial code at 0.00132s

(from al_saved_sessions.yml)

initial: True
code: |
  ########### Save title and progress to session list ##################
  if get_config("assembly line",{}).get("update session metadata", True):
    al_temp_metadata = get_interview_metadata(
      user_info().filename, user_info().session
    )
    al_temp_metadata["auto_title"] = str(al_sessions_interview_title)
    al_temp_metadata["progress"] = get_progress()
    set_current_session_metadata(al_temp_metadata)
    del(al_temp_metadata)

Ran initial code at 0.18251s

(from al_visual.yml)

initial: True
code: |
  menu_items = [
    item for item in al_menu_items if not item.get("hidden", False)
  ]

Needed definition of al_menu_items at 0.18265s
Tried to run block at 0.18270s

(from al_visual.yml)

reconsider: True
code: |
  al_menu_items = al_menu_items_custom_items + al_menu_items_default_items

Needed definition of al_menu_items_default_items at 0.18283s
Tried to run block at 0.18286s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Needed definition of al_start_over_string at 0.18313s
Tried to run block at 0.18316s

(from al_visual.yml)

template: al_start_over_string
content: >-
  Start over

Tried to run block at 0.18322s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Needed definition of al_exit_logout_string at 0.18362s
Tried to run block at 0.18366s

(from al_visual.yml)

template: al_exit_logout_string
content: >-
  Exit and delete my answers

Tried to run block at 0.18371s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Needed definition of al_download_progress_string at 0.18401s
Tried to run block at 0.18404s

(from al_visual.yml)

template: al_download_progress_string
content: >-
  Download current progress

Tried to run block at 0.18408s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Needed definition of al_save_answer_set_string at 0.18446s
Tried to run block at 0.18449s

(from al_visual.yml)

template: al_save_answer_set_string
content: >-
  Save answer set

Tried to run block at 0.18453s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Needed definition of al_load_answer_set_string at 0.18495s
Tried to run block at 0.18498s

(from al_visual.yml)

template: al_load_answer_set_string
content: >-
  Load answer set

Tried to run block at 0.18503s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Needed definition of al_download_answer_set_string at 0.18550s
Tried to run block at 0.18552s

(from al_visual.yml)

template: al_download_answer_set_string
content: >-
  Download answer set

Tried to run block at 0.18557s

(from al_visual.yml)

reconsider: True
variable name: al_menu_items_default_items
data from code:
  - url: 
      url_ask(['al_start_over_confirmation','al_start_over'])
    label: str(al_start_over_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_ask(['al_exit_logout_confirmation', 'al_exit_logout'])
    label: str(al_exit_logout_string)
    hidden: _internal.get('steps') < 2
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_progress_string)
    hidden: (not al_enable_incomplete_downloads) or (_internal.get('steps') < 2)
  - url: |
      url_ask(["al_sessions_snapshot_label", {"recompute": ["al_sessions_save_session_snapshot"]}, "al_sessions_save_status"])
    label: str(al_save_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer sets')) or (_internal.get('steps') < 2)
  - url: |
      url_action('al_load_saved_session')
    label: str(al_load_answer_set_string)
    hidden: not get_config('assembly line',{}).get('enable answer sets')
  - url: |
      url_action('al_error_action_download_screen')
    label: str(al_download_answer_set_string)
    hidden: (not get_config('assembly line',{}).get('enable answer set imports')) or (_internal.get('steps') < 2)

Tried to run block at 0.18634s

(from al_visual.yml)

reconsider: True
code: |
  al_menu_items = al_menu_items_custom_items + al_menu_items_default_items

Ran initial code at 0.18651s

(from al_language.yml)

initial: True
code: |
  if enable_al_language:
    set_language(al_user_language)

Ran initial code at 0.18657s

(from al_saved_sessions.yml)

initial: True
code: |
  ########### Save title and progress to session list ##################
  if get_config("assembly line",{}).get("update session metadata", True):
    al_temp_metadata = get_interview_metadata(
      user_info().filename, user_info().session
    )
    al_temp_metadata["auto_title"] = str(al_sessions_interview_title)
    al_temp_metadata["progress"] = get_progress()
    set_current_session_metadata(al_temp_metadata)
    del(al_temp_metadata)

Ran initial code at 0.33288s

(from al_visual.yml)

initial: True
code: |
  menu_items = [
    item for item in al_menu_items if not item.get("hidden", False)
  ]

Ran initial code at 0.33292s

(from al_visual.yml)

initial: True
code: |
  if enable_al_nav_sections:
    nav.set_sections(get_visible_al_nav_items(al_nav_sections))

Tried to run mandatory code at 0.33345s

############################# Main order #######################
id: run main interview
mandatory: True
code: |
  al_intro_screen
  aff_of_indigency_intro
  affidavit_match_to_case_prompts # Make sure people give a docket number
  ask_affidavit_questions # Main questions
  if not is_indigent:
    doesnt_qualify_ending
  # Store anonymous data for analytics / statistics
  store_variables_snapshot(
      persistent=True,
      data={
          "zip": showifdef("users[0].address.zip"),
          "reached_interview_end": True,
      },
  )
  preview
  basic_questions_signature_flow
  download

Needed definition of ask_affidavit_questions at 0.33358s
Tried to run block at 0.33363s

(from affidavit_body.yml)

id: question order
code: |
  # These should be all of the necessary questions, not just the 
  # intro screen/etc.
  if affidavit_is_standalone:
    nav.set_section('review_affidavit_of_indigency')
  user_started_case
  users.gather()
  if len(users) > 1:
    explain_separate_affidavits
  other_parties.gather()
  case_name
  public_assistance_kinds
  if public_assistance_kinds.all_false():
    has_household_members
    if not household_income_qualifies:
      can_afford
  if is_indigent:
    qualify_interstitial
    if need_supplement:
      interview_order_affidavit_of_indigency_supplement
    if affidavit_is_standalone:
      nav.set_section("fees_section")
    fees['Filing fee'].waive
    fees['Costs of an expert witness'].waive
    fees_interstitial
    users[0].name.first
    users[0].address.address
    users[0].mobile_number
    tried_geolocating
    # local_housing_court
    all_matches
    affidavit_of_indigency_filing_court

    set_empty_fees
  ask_affidavit_questions = True

Needed definition of user_started_case at 0.33377s
Tried to run block at 0.33381s

(from ql_baseline.yml)

code: |
  # This will be considered after any code in the parent interview
  # Most likely, user_started_case should be True for form types "other" and "out_of_court" but 
  # we will let form author decide
  if al_form_type in ['letter', 'starts_case']:
    user_started_case = True 

Tried to run block at 0.33391s

(from ql_baseline.yml)

depends on:
  - user_ask_role
code: |
  # If the interview author didn't specify and it's a "court" or "other" case, we just ask
  user_started_case = user_ask_role == 'plaintiff'

Tried to run block at 0.33399s

(from affidavit_body.yml)

id: question order
code: |
  # These should be all of the necessary questions, not just the 
  # intro screen/etc.
  if affidavit_is_standalone:
    nav.set_section('review_affidavit_of_indigency')
  user_started_case
  users.gather()
  if len(users) > 1:
    explain_separate_affidavits
  other_parties.gather()
  case_name
  public_assistance_kinds
  if public_assistance_kinds.all_false():
    has_household_members
    if not household_income_qualifies:
      can_afford
  if is_indigent:
    qualify_interstitial
    if need_supplement:
      interview_order_affidavit_of_indigency_supplement
    if affidavit_is_standalone:
      nav.set_section("fees_section")
    fees['Filing fee'].waive
    fees['Costs of an expert witness'].waive
    fees_interstitial
    users[0].name.first
    users[0].address.address
    users[0].mobile_number
    tried_geolocating
    # local_housing_court
    all_matches
    affidavit_of_indigency_filing_court

    set_empty_fees
  ask_affidavit_questions = True

Needed definition of users at 0.33408s
Tried to run block at 0.33412s

(from affidavit_body.yml)

objects:
  - hh_income: ALJob
  - fees: DADict.using(gathered=True, auto_gather=False, object_type=DAObject)
  - users: ALPeopleList.using(there_are_any=True)

Tried to run block at 0.33431s

(from affidavit_body.yml)

id: question order
code: |
  # These should be all of the necessary questions, not just the 
  # intro screen/etc.
  if affidavit_is_standalone:
    nav.set_section('review_affidavit_of_indigency')
  user_started_case
  users.gather()
  if len(users) > 1:
    explain_separate_affidavits
  other_parties.gather()
  case_name
  public_assistance_kinds
  if public_assistance_kinds.all_false():
    has_household_members
    if not household_income_qualifies:
      can_afford
  if is_indigent:
    qualify_interstitial
    if need_supplement:
      interview_order_affidavit_of_indigency_supplement
    if affidavit_is_standalone:
      nav.set_section("fees_section")
    fees['Filing fee'].waive
    fees['Costs of an expert witness'].waive
    fees_interstitial
    users[0].name.first
    users[0].address.address
    users[0].mobile_number
    tried_geolocating
    # local_housing_court
    all_matches
    affidavit_of_indigency_filing_court

    set_empty_fees
  ask_affidavit_questions = True

Needed definition of users[0].name.first at 0.33472s
Tried to ask question at 0.33493s

(from ql_baseline.yml)

id: your name
sets:
    - users[0].name.first
    - users[0].name.last
    - users[0].name.middle
    - users[0].name.suffix
question:  |
  What is your name?
fields:
  - code: |
      users[0].name_fields()

Needed definition of alkiln_trigger_html at 0.33800s
Tried to run block at 0.33805s

(from al_code.yml)

# A bit of HTML required for ALKiln to be used in interviews.
# To add to your unstyled alkiln interviews, include it in your `default screen parts: post`
template: alkiln_trigger_html
content: |
    

Tried to ask question at 0.33814s

(from ql_baseline.yml)

id: your name
sets:
    - users[0].name.first
    - users[0].name.last
    - users[0].name.middle
    - users[0].name.suffix
question:  |
  What is your name?
fields:
  - code: |
      users[0].name_fields()

Needed definition of users[0].first_name_label at 0.34303s
Tried to run block at 0.34318s

(from ql_baseline.yml)

generic object: ALIndividual
template: x.first_name_label
content: |
  First name

Tried to ask question at 0.34376s

(from ql_baseline.yml)

id: your name
sets:
    - users[0].name.first
    - users[0].name.last
    - users[0].name.middle
    - users[0].name.suffix
question:  |
  What is your name?
fields:
  - code: |
      users[0].name_fields()

Needed definition of users[0].middle_name_label at 0.34868s
Tried to run block at 0.34883s

(from ql_baseline.yml)

generic object: ALIndividual
template: x.middle_name_label
content: |
  Middle name

Tried to ask question at 0.34905s

(from ql_baseline.yml)

id: your name
sets:
    - users[0].name.first
    - users[0].name.last
    - users[0].name.middle
    - users[0].name.suffix
question:  |
  What is your name?
fields:
  - code: |
      users[0].name_fields()

Needed definition of users[0].last_name_label at 0.35318s
Tried to run block at 0.35333s

(from ql_baseline.yml)

generic object: ALIndividual
template: x.last_name_label
content: |
  Last name

Tried to ask question at 0.35355s

(from ql_baseline.yml)

id: your name
sets:
    - users[0].name.first
    - users[0].name.last
    - users[0].name.middle
    - users[0].name.suffix
question:  |
  What is your name?
fields:
  - code: |
      users[0].name_fields()

Needed definition of users[0].suffix_label at 0.35842s
Tried to run block at 0.35856s

(from ql_baseline.yml)

generic object: ALIndividual
template: x.suffix_label
content: |
  Suffix

Completed processing at 0.36634s
nonprofittechy commented 11 months ago
  1. Can we use a different method to update the existing JSON blob? I don't know what options we have with Postgres' JSONB column type. (I have a suspicion that loading the JSON and creating a variable for it in order to edit it has some overhead).
  2. Previously we checked the step. Perhaps we can use DA's task system? That uses Redis and is pretty lightweight. But I assume not zero weight.