Skip to content

fix: install lookup_hash column for existing sites via hook_update_10001#40

Merged
jjroelofs merged 1 commit into
1.xfrom
fix/rl-lookup-hash-update-hook
Apr 21, 2026
Merged

fix: install lookup_hash column for existing sites via hook_update_10001#40
jjroelofs merged 1 commit into
1.xfrom
fix/rl-lookup-hash-update-hook

Conversation

@jjroelofs
Copy link
Copy Markdown
Contributor

Summary

  • Adds rl_page_title_update_10001() and rl_menu_link_update_10001() so existing sites installed before the hash-indexed lookup refactor (commit e215a95) get the new lookup_hash column, backfilled hashes, UNIQUE key, and secondary composite index.
  • Without this, VariantSelectorBase::loadExperimentByLookupHashes() throws QueryException: 'lookup_hash' not found on every page render, 500ing anything that hits hook_page_attachments.
  • The original refactor deliberately skipped a hook_update calling out "modules have not been released." That is not a valid reason to skip schema updates in a contrib module — any preview checkout, -dev follower, or tagged site upgrading across this refactor will crash.

How each update works

  1. $schema->addField() adds lookup_hash varchar(64) NOT NULL DEFAULT '' so the NOT NULL add does not fail on tables with rows.
  2. Direct DB update backfills hashes using {PageTitle,MenuLink}Experiment::computeLookupHash() so values match exactly what preSave() writes at runtime.
  3. A pre-check throws UpdateException with the offending hash set if any rows collide (prevents the UNIQUE key add from exploding mid-migration).
  4. addUniqueKey() + addIndex() apply the schema declared by the storage schema classes.
  5. Field is registered with the entity system via entity.last_installed_schema.repository::setLastInstalledFieldStorageDefinition(), deliberately bypassing EntityDefinitionUpdateManager::installFieldStorageDefinition() because that re-applies the full storage schema and fails on "key already exists".

Test plan

  • drush updb -y on a site with the old schema runs both updates, backfills existing rows, applies indexes.
  • SHOW INDEX FROM rl_page_title_experiment confirms rl_page_title_lookup_hash (UNIQUE) + rl_page_title_path_langcode (composite, 191-char prefix).
  • SHOW INDEX FROM rl_menu_link_experiment confirms rl_menu_link_lookup_hash (UNIQUE) + rl_menu_link_plugin_langcode (composite, 191-char prefix).
  • Previously-500ing /home returns 200 after the update.
  • No new lookup_hash QueryException rows in watchdog after the fix.
  • drush updb re-run shows "No pending updates" (idempotent).
  • Re-run on a multilingual site with per-language experiment rows to confirm hash collisions do not trip the UNIQUE check.
  • Verify on a site with legacy unnormalized paths (trailing slash, missing leading slash) that the backfill does not collide.

…okup_hash

Existing sites installed before the hash-indexed lookup refactor
(commit e215a95) hit a 500 on every page render because
VariantSelectorBase::loadExperimentByLookupHashes() now filters an
entity query on `lookup_hash`, a column that exists in the new storage
schema but was never added to previously-installed tables. The original
refactor deliberately skipped a hook_update with the justification that
the submodules were unreleased, which is not a valid reason to skip
schema updates in a contrib module.

Each update_10001():

1. Adds the lookup_hash varchar(64) NOT NULL column with empty default.
2. Backfills hashes from each row's (path|langcode) or
   (menu_link_plugin_id|langcode) using the entity class's own
   computeLookupHash() helper so values match what preSave() writes.
3. Fails with a listed hash set via UpdateException if pre-existing
   duplicate (target, langcode) rows would violate the UNIQUE key.
4. Adds the rl_*_lookup_hash UNIQUE key and the secondary composite
   index declared by {PageTitle,MenuLink}ExperimentStorageSchema.
5. Registers the base field via the last-installed schema repository
   instead of EntityDefinitionUpdateManager::installFieldStorageDefinition(),
   because the latter would re-apply the full storage schema (including
   the UNIQUE key just added) and fail on "key already exists".

Verified on a preview-checkout install: drush updb ran both updates,
backfilled existing rows, applied all four indexes (SHOW INDEX confirms
the unique and composite indexes on both tables), /home returns 200,
and no new QueryException rows land in watchdog.
@jjroelofs jjroelofs force-pushed the fix/rl-lookup-hash-update-hook branch from c4ee4ee to 010cfea Compare April 14, 2026 14:20
@jjroelofs jjroelofs merged commit 7e56b02 into 1.x Apr 21, 2026
3 checks passed
@jjroelofs jjroelofs deleted the fix/rl-lookup-hash-update-hook branch April 21, 2026 14:44
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.

1 participant