Skip to content

Memoize options method on TwoFactorLoginOptionsPresenter#9173

Merged
mitchellhenke merged 1 commit intomainfrom
mitchellhenke/less-queries-on-options-presenter
Sep 8, 2023
Merged

Memoize options method on TwoFactorLoginOptionsPresenter#9173
mitchellhenke merged 1 commit intomainfrom
mitchellhenke/less-queries-on-options-presenter

Conversation

@mitchellhenke
Copy link
Contributor

@mitchellhenke mitchellhenke commented Sep 8, 2023

🛠 Summary of changes

The options presenter calculates the options for each option being presented since options is called in first_enabled_option_index during the loop here.

This can result in a lot of unnecessary database queries or database query cache hits. I suspect this is the reason the template rendering takes most of the time in this controller path (NewRelic):
image

Queries before:

   User Load (0.7ms)  SELECT "users"."id", "users"."reset_password_token", "users"."reset_password_sent_at", "users"."remember_created_at", "users"."created_at", "users"."updated_at", "users"."confirmed_at", "users"."second_factor_attempts_count", "users"."uuid", "users"."second_factor_locked_at", "users"."phone_confirmed_at", "users"."direct_otp", "users"."direct_otp_sent_at", "users"."unique_session_id", "users"."otp_delivery_preference", "users"."encrypted_password_digest", "users"."encrypted_recovery_code_digest", "users"."remember_device_revoked_at", "users"."email_language", "users"."accepted_terms_at", "users"."encrypted_recovery_code_digest_generated_at", "users"."suspended_at", "users"."reinstated_at", "users"."encrypted_password_digest_multi_region", "users"."encrypted_recovery_code_digest_multi_region" FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 5], ["LIMIT", 1]]
  PhoneConfiguration Load (0.6ms)  SELECT "phone_configurations"."id", "phone_configurations"."user_id", "phone_configurations"."encrypted_phone", "phone_configurations"."delivery_preference", "phone_configurations"."mfa_enabled", "phone_configurations"."confirmation_sent_at", "phone_configurations"."confirmed_at", "phone_configurations"."created_at", "phone_configurations"."updated_at", "phone_configurations"."made_default_at" FROM "phone_configurations" WHERE "phone_configurations"."user_id" = $1  [["user_id", 5]]
  WebauthnConfiguration Load (0.6ms)  SELECT "webauthn_configurations"."id", "webauthn_configurations"."user_id", "webauthn_configurations"."name", "webauthn_configurations"."credential_id", "webauthn_configurations"."credential_public_key", "webauthn_configurations"."created_at", "webauthn_configurations"."updated_at", "webauthn_configurations"."platform_authenticator", "webauthn_configurations"."transports", "webauthn_configurations"."authenticator_data_flags" FROM "webauthn_configurations" WHERE "webauthn_configurations"."user_id" = $1  [["user_id", 5]]
  BackupCodeConfiguration Load (0.9ms)  SELECT "backup_code_configurations"."id", "backup_code_configurations"."user_id", "backup_code_configurations"."used_at", "backup_code_configurations"."created_at", "backup_code_configurations"."updated_at", "backup_code_configurations"."salted_code_fingerprint", "backup_code_configurations"."code_salt", "backup_code_configurations"."code_cost" FROM "backup_code_configurations" WHERE "backup_code_configurations"."user_id" = $1 AND "backup_code_configurations"."used_at" IS NULL  [["user_id", 5]]
  PivCacConfiguration Load (1.0ms)  SELECT "piv_cac_configurations"."id", "piv_cac_configurations"."user_id", "piv_cac_configurations"."x509_dn_uuid", "piv_cac_configurations"."name", "piv_cac_configurations"."created_at", "piv_cac_configurations"."updated_at", "piv_cac_configurations"."x509_issuer" FROM "piv_cac_configurations" WHERE "piv_cac_configurations"."user_id" = $1  [["user_id", 5]]
  AuthAppConfiguration Load (0.6ms)  SELECT "auth_app_configurations"."id", "auth_app_configurations"."user_id", "auth_app_configurations"."encrypted_otp_secret_key", "auth_app_configurations"."name", "auth_app_configurations"."totp_timestamp", "auth_app_configurations"."created_at", "auth_app_configurations"."updated_at" FROM "auth_app_configurations" WHERE "auth_app_configurations"."user_id" = $1  [["user_id", 5]]
  Profile Exists? (1.5ms)  SELECT 1 AS one FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
  CACHE BackupCodeConfiguration Load (0.0ms)  SELECT "backup_code_configurations"."id", "backup_code_configurations"."user_id", "backup_code_configurations"."used_at", "backup_code_configurations"."created_at", "backup_code_configurations"."updated_at", "backup_code_configurations"."salted_code_fingerprint", "backup_code_configurations"."code_salt", "backup_code_configurations"."code_cost" FROM "backup_code_configurations" WHERE "backup_code_configurations"."user_id" = $1 AND "backup_code_configurations"."used_at" IS NULL  [["user_id", 5]]
  CACHE Profile Exists? (0.0ms)  SELECT 1 AS one FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
  CACHE BackupCodeConfiguration Load (0.0ms)  SELECT "backup_code_configurations"."id", "backup_code_configurations"."user_id", "backup_code_configurations"."used_at", "backup_code_configurations"."created_at", "backup_code_configurations"."updated_at", "backup_code_configurations"."salted_code_fingerprint", "backup_code_configurations"."code_salt", "backup_code_configurations"."code_cost" FROM "backup_code_configurations" WHERE "backup_code_configurations"."user_id" = $1 AND "backup_code_configurations"."used_at" IS NULL  [["user_id", 5]]
  CACHE Profile Exists? (0.0ms)  SELECT 1 AS one FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
  CACHE BackupCodeConfiguration Load (0.0ms)  SELECT "backup_code_configurations"."id", "backup_code_configurations"."user_id", "backup_code_configurations"."used_at", "backup_code_configurations"."created_at", "backup_code_configurations"."updated_at", "backup_code_configurations"."salted_code_fingerprint", "backup_code_configurations"."code_salt", "backup_code_configurations"."code_cost" FROM "backup_code_configurations" WHERE "backup_code_configurations"."user_id" = $1 AND "backup_code_configurations"."used_at" IS NULL  [["user_id", 5]]
  CACHE Profile Exists? (0.0ms)  SELECT 1 AS one FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
  CACHE BackupCodeConfiguration Load (0.0ms)  SELECT "backup_code_configurations"."id", "backup_code_configurations"."user_id", "backup_code_configurations"."used_at", "backup_code_configurations"."created_at", "backup_code_configurations"."updated_at", "backup_code_configurations"."salted_code_fingerprint", "backup_code_configurations"."code_salt", "backup_code_configurations"."code_cost" FROM "backup_code_configurations" WHERE "backup_code_configurations"."user_id" = $1 AND "backup_code_configurations"."used_at" IS NULL  [["user_id", 5]]
  CACHE Profile Exists? (0.0ms)  SELECT 1 AS one FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
  AccountResetRequest Load (0.7ms)  SELECT "account_reset_requests"."id", "account_reset_requests"."user_id", "account_reset_requests"."requested_at", "account_reset_requests"."request_token", "account_reset_requests"."cancelled_at", "account_reset_requests"."granted_at", "account_reset_requests"."granted_token", "account_reset_requests"."created_at", "account_reset_requests"."updated_at", "account_reset_requests"."requesting_issuer" FROM "account_reset_requests" WHERE "account_reset_requests"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
{"method":"GET","path":"/login/two_factor/options","format":"html","controller":"TwoFactorAuthentication::OptionsController","action":"index","status":200,"duration":190.07,"user_id":"33bf5a4a-13eb-4640-8e30-85f39629b840","git_sha":"67e17028","git_branch":"mitchellhenke/gpo-events-query","timestamp":"2023-09-08T14:59:02Z","uuid":"7b8cbf9a-1182-42f1-91c3-cb5b85b2b39b","pid":3247,"user_agent":"Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/117.0","ip":"127.0.0.1","host":"localhost","trace_id":null}

Queries after:

  User Load (0.5ms)  SELECT "users"."id", "users"."reset_password_token", "users"."reset_password_sent_at", "users"."remember_created_at", "users"."created_at", "users"."updated_at", "users"."confirmed_at", "users"."second_factor_attempts_count", "users"."uuid", "users"."second_factor_locked_at", "users"."phone_confirmed_at", "users"."direct_otp", "users"."direct_otp_sent_at", "users"."unique_session_id", "users"."otp_delivery_preference", "users"."encrypted_password_digest", "users"."encrypted_recovery_code_digest", "users"."remember_device_revoked_at", "users"."email_language", "users"."accepted_terms_at", "users"."encrypted_recovery_code_digest_generated_at", "users"."suspended_at", "users"."reinstated_at", "users"."encrypted_password_digest_multi_region", "users"."encrypted_recovery_code_digest_multi_region" FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 5], ["LIMIT", 1]]
  PhoneConfiguration Load (0.5ms)  SELECT "phone_configurations"."id", "phone_configurations"."user_id", "phone_configurations"."encrypted_phone", "phone_configurations"."delivery_preference", "phone_configurations"."mfa_enabled", "phone_configurations"."confirmation_sent_at", "phone_configurations"."confirmed_at", "phone_configurations"."created_at", "phone_configurations"."updated_at", "phone_configurations"."made_default_at" FROM "phone_configurations" WHERE "phone_configurations"."user_id" = $1  [["user_id", 5]]
  WebauthnConfiguration Load (3.3ms)  SELECT "webauthn_configurations"."id", "webauthn_configurations"."user_id", "webauthn_configurations"."name", "webauthn_configurations"."credential_id", "webauthn_configurations"."credential_public_key", "webauthn_configurations"."created_at", "webauthn_configurations"."updated_at", "webauthn_configurations"."platform_authenticator", "webauthn_configurations"."transports", "webauthn_configurations"."authenticator_data_flags" FROM "webauthn_configurations" WHERE "webauthn_configurations"."user_id" = $1  [["user_id", 5]]
  BackupCodeConfiguration Load (0.4ms)  SELECT "backup_code_configurations"."id", "backup_code_configurations"."user_id", "backup_code_configurations"."used_at", "backup_code_configurations"."created_at", "backup_code_configurations"."updated_at", "backup_code_configurations"."salted_code_fingerprint", "backup_code_configurations"."code_salt", "backup_code_configurations"."code_cost" FROM "backup_code_configurations" WHERE "backup_code_configurations"."user_id" = $1 AND "backup_code_configurations"."used_at" IS NULL  [["user_id", 5]]
  PivCacConfiguration Load (0.4ms)  SELECT "piv_cac_configurations"."id", "piv_cac_configurations"."user_id", "piv_cac_configurations"."x509_dn_uuid", "piv_cac_configurations"."name", "piv_cac_configurations"."created_at", "piv_cac_configurations"."updated_at", "piv_cac_configurations"."x509_issuer" FROM "piv_cac_configurations" WHERE "piv_cac_configurations"."user_id" = $1  [["user_id", 5]]
  AuthAppConfiguration Load (0.5ms)  SELECT "auth_app_configurations"."id", "auth_app_configurations"."user_id", "auth_app_configurations"."encrypted_otp_secret_key", "auth_app_configurations"."name", "auth_app_configurations"."totp_timestamp", "auth_app_configurations"."created_at", "auth_app_configurations"."updated_at" FROM "auth_app_configurations" WHERE "auth_app_configurations"."user_id" = $1  [["user_id", 5]]
  Profile Exists? (0.4ms)  SELECT 1 AS one FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
  AccountResetRequest Load (0.6ms)  SELECT "account_reset_requests"."id", "account_reset_requests"."user_id", "account_reset_requests"."requested_at", "account_reset_requests"."request_token", "account_reset_requests"."cancelled_at", "account_reset_requests"."granted_at", "account_reset_requests"."granted_token", "account_reset_requests"."created_at", "account_reset_requests"."updated_at", "account_reset_requests"."requesting_issuer" FROM "account_reset_requests" WHERE "account_reset_requests"."user_id" = $1 LIMIT $2  [["user_id", 5], ["LIMIT", 1]]
{"method":"GET","path":"/login/two_factor/options","format":"html","controller":"TwoFactorAuthentication::OptionsController","action":"index","status":200,"duration":49.15,"user_id":"33bf5a4a-13eb-4640-8e30-85f39629b840","git_sha":"67e17028","git_branch":"mitchellhenke/gpo-events-query","timestamp":"2023-09-08T15:14:43Z","uuid":"29f90827-d19c-416d-829d-2bab6e91a601","pid":4600,"user_agent":"Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/117.0","ip":"127.0.0.1","host":"localhost","trace_id":null}

@mitchellhenke mitchellhenke requested a review from aduth September 8, 2023 15:57
changelog: Internal, Performance, Memoize options method on TwoFactorLoginOptionsPresenter
@mitchellhenke mitchellhenke force-pushed the mitchellhenke/less-queries-on-options-presenter branch from 5ad9bc3 to ba72f9d Compare September 8, 2023 16:05
@mitchellhenke mitchellhenke merged commit ba80260 into main Sep 8, 2023
@mitchellhenke mitchellhenke deleted the mitchellhenke/less-queries-on-options-presenter branch September 8, 2023 16:23
@aduth aduth mentioned this pull request Sep 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants