Skip to content

Apply hooks search filter before pagination#8368

Open
nitishagar wants to merge 1 commit intotaskcluster:mainfrom
nitishagar:fix/7972-hooks-search
Open

Apply hooks search filter before pagination#8368
nitishagar wants to merge 1 commit intotaskcluster:mainfrom
nitishagar:fix/7972-hooks-search

Conversation

@nitishagar
Copy link
Contributor

@nitishagar nitishagar commented Mar 13, 2026

Summary

Fixes #7972.

Refactors the hooks search to use a dedicated searchHooks API endpoint instead of
overloading listHookGroups. This was done per reviewer feedback in
#8368 (comment).

Root cause: The previous approach added a search query param to listHookGroups,
which didn't match its natural contract (it returns groups but was filtering by hook IDs).
The initial page load was also slow due to N+1 requests when fetching hook IDs per group.

Fix:

  1. New db/versions/0123.yml: adds search_hooks(search_term_in, page_size, page_offset)
    a single ILIKE query across hook_group_id and hook_id, returns full hook rows
  2. New GET /hooks/search?q=<term> API endpoint (searchHooks) — returns matching
    hook definitions across all groups (same shape as listHooks)
  3. listHookGroups reverted to its clean contract (no search param, uses get_hook_groups())
  4. GraphQL: hookGroups no longer takes search; new searchHooks(query: String!): [Hook] added
  5. UI: when a ?search= URL param is present, fetches from searchHooks and renders a flat
    HooksListTable; otherwise renders the normal HookGroupsTable

Initial page load is fast (group IDs only). Searches trigger a single efficient DB query.

Changes

DB:

  • db/versions/0123.yml — new search_hooks function (replaces get_hook_groups_2)
  • db/test/fns/hooks_test.js — tests for search_hooks
  • db/test/versions/0123_test.js — version smoke test

API (services/hooks):

  • services/hooks/schemas/v1/search-hooks-response.yml — new schema (same shape as listHooks)
  • services/hooks/src/api.js — reverted listHookGroups, added searchHooks at /hooks/search
  • services/hooks/test/api_test.js — tests for searchHooks

GraphQL/Web-server:

  • services/web-server/src/graphql/Hooks.graphql — removed search from hookGroups, added searchHooks
  • services/web-server/src/loaders/hooks.js — new hookSearch DataLoader
  • services/web-server/src/resolvers/Hooks.js — new searchHooks resolver

UI:

  • ui/src/views/Hooks/ListHookGroups/hookGroups.graphql — simplified (no $search)
  • ui/src/views/Hooks/ListHookGroups/searchHooks.graphql — new query
  • ui/src/views/Hooks/ListHookGroups/index.jsx — two-mode rendering

Generated (from yarn generate):

  • generated/references.json, generated/db-schema.json
  • libraries/postgres/@types/fns.d.ts, db/fns.md, db/schema.md, db/versions/README.md
  • All client libraries updated with searchHooks method

Test Plan

  • cd db && yarn test — DB function tests pass
  • cd services/hooks && yarn test — API tests pass including new searchHooks suite
  • Navigate to /hooks — groups table loads normally (no regression)
  • Type a search term and submit — flat list of matching hooks appears
  • Search matches hook IDs inside groups whose name doesn't match
  • Search is case-insensitive (e.g. PROJECT matches project-releng)
  • Clear search — groups table reappears

@nitishagar nitishagar requested a review from a team as a code owner March 13, 2026 05:57
@nitishagar nitishagar requested review from lotas, matt-boris and petemoore and removed request for a team March 13, 2026 05:57
@nitishagar nitishagar force-pushed the fix/7972-hooks-search branch from 52be92b to aef4cd2 Compare March 13, 2026 06:16
query HookGroups {
hookGroups {
hookGroupId
hooks {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like the right way to fix the given search issue, but the reason why we have separate HookGroups query is because it is fast.
We had to create a new HookGroups view specifically to make first page load fast - original query takes <300ms to respond with all groups.

Now, when we include hooks inside that is suddenly becomes much slower - takes ~6s to load

Copy link
Contributor

@lotas lotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot accept current changes as it would be a regression.
Plus having client-side only search doesn't help here.

We should probably think about implementing a server-side filtering, or only include nested hooks when search is present.

Another idea on top of my head would be to use different view for the search purposes

@nitishagar nitishagar force-pushed the fix/7972-hooks-search branch 5 times, most recently from 4191d78 to d6f5b5e Compare March 15, 2026 09:09
@nitishagar
Copy link
Contributor Author

Thanks for the review @lotas.

Reworked this with server-side filtering:

  • Added a new DB function get_hook_groups_2(search_term_in text) (db/versions/0123.yml) — uses a single DISTINCT ... WHERE hook_group_id ILIKE OR hook_id ILIKE query. The fast path is preserved when the search term is empty, so the initial page load remains unchanged.
  • Threaded the search query param from listHookGroups → DataLoader → GraphQL → UI. The UI now passes search as a variable, allowing Apollo to re-query on URL changes. This removes the need for client-side filtering and avoids including hooks { hookId } in the initial query.

@lotas
Copy link
Contributor

lotas commented Mar 16, 2026

hey @nitishagar thanks for the refactor, I think this a step in the right direction, since we remove the expensive nested hook loading.

That said, I think we are still overloading listHookGroups with search behavior that does not match its natural ocntract. We filter for both hook group and hook id, but return only hook group. That shape existed mostly because current UI was optimized that way.

I think a cleaner approach would be to introduce a dedicated hook search endpoint and add new UI element that would display filtered hooks.

searchHooks - GET /hooks/search?q=xx that will return same as listHooks is currently reporting but without single hook group constraint.

@nitishagar nitishagar force-pushed the fix/7972-hooks-search branch from d6f5b5e to b0fb28a Compare March 17, 2026 12:33
Previously the hooks search only matched hook group names visible on the
current page, and couldn't search within hook IDs. The fix added
hooks { hookId } to the hookGroups GraphQL query which caused a ~6s
initial page load regression due to N+1 requests (one per group).

This commit reworks the fix with proper server-side filtering:

- db/versions/0123.yml: add get_hook_groups_2(search_term_in text) that
  searches hook_group_id and hook_id via ILIKE in a single DB query;
  deprecate get_hook_groups() per the _2 convention
- services/hooks/src/api.js: add optional `search` query param to
  listHookGroups; call get_hook_groups_2 to filter at the DB layer
- services/web-server/src/loaders/hooks.js: pass search to the TC client
- services/web-server/src/resolvers/Hooks.js: extract search from args
- services/web-server/src/graphql/Hooks.graphql: add search: String arg
- ui/src/views/Hooks/ListHookGroups/hookGroups.graphql: use $search
  variable, remove hooks { hookId } (no longer needed)
- ui/src/views/Hooks/ListHookGroups/index.jsx: pass search as a GraphQL
  variable so the query re-runs on URL change; remove client-side filter
- db/test/fns/hooks_test.js: tests for get_hook_groups_2

Initial page load remains fast (<300ms, group IDs only). Searches trigger
a single efficient DB query matching group or hook IDs case-insensitively.

Closes taskcluster#7972
@nitishagar nitishagar force-pushed the fix/7972-hooks-search branch from b0fb28a to c844c3f Compare March 17, 2026 12:54
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.

hooks ui search only searches what is currently visible

2 participants