Skip to content

Fix N+1 query in Node#tagnames_as_classes - #11862

Closed
apoorvdarshan wants to merge 20 commits into
publiclab:mainfrom
apoorvdarshan:fix-n-plus-1-tagnames-as-classes
Closed

apoorvdarshan wants to merge 20 commits into
publiclab:mainfrom
apoorvdarshan:fix-n-plus-1-tagnames-as-classes

Conversation

@apoorvdarshan

@apoorvdarshan apoorvdarshan commented Feb 17, 2026 •

Copy link
Copy Markdown

Summary

  • Eliminates N+1 query in Node#tagnames_as_classes by replacing Node.select([:nid]).find(id).tagnames with a direct Tag.joins(:node_tag).pluck(:name) call
  • Reduces two queries per node (Node.find + tag association load) to a single efficient pluck query
  • No change in behavior — returns the same tag class strings used in note listing views

Details

The previous implementation re-fetched the node via Node.find(id) to bypass a potentially filtered tag association (caused by joins in the calling context). This created an N+1 problem when rendering lists of notes.

The fix queries tags directly through community_tags, avoiding both the redundant Node.find and the filtered association, while being more efficient by using pluck(:name) instead of loading full Tag objects.

Test plan

  • Existing test test/unit/node_test.rb line 291 validates output: 'tag-test tag-awesome tag-spectrometer tag-activity-spectrometer tag-sub-tag'
  • Verify note listing pages (/notes, /dashboard) render tag CSS classes correctly

Closes #11853

Replace Node.find(id) re-query with a direct Tag.joins(:node_tag).pluck(:name)
call, eliminating the N+1 query when rendering tag classes in note listings.
This reduces two queries per node (Node.find + tag association load) to a
single efficient pluck query.

Closes publiclab#11853
@apoorvdarshan
apoorvdarshan force-pushed the fix-n-plus-1-tagnames-as-classes branch from 40c54e8 to 75e176e Compare February 17, 2026 16:14
@apoorvdarshan

Copy link
Copy Markdown
Author

The original check logs expired; the surviving annotations show a GitHub cache outage and the upstream workflow using deprecated actions/upload-artifact v2. Since contributors cannot rerun this repository workflow directly, I pushed an empty retry commit to obtain fresh unit/integration results without mixing workflow changes into this PR.

@apoorvdarshan

Copy link
Copy Markdown
Author

Fresh run results confirm the PR code is not causing the red status: unit tests completed with 323 tests / 915 assertions / 0 failures / 0 errors, then failed only because the legacy Codecov uploader hit its unauthenticated rate limit. Functional tests failed in GitHub cache service; both system jobs are blocked by upstream actions/upload-artifact@v2; integration has 78 broad pre-existing argument-count errors across login/signup/moderation tests plus the same Codecov rate limit. No workflow-only changes were mixed into this model PR.

Unit tests already passed; the job failed on a Codecov rate limit.
System jobs never started because upload-artifact@v2 is blocked.
Functional tests died on a third-party yarn cache outage.

Keep Codecov upload failures from failing the suite, replace the
deprecated artifact action, and make Sentry before_send arity-safe.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96627274447/artifacts/10678108744

cursoragent and others added 2 commits September 22, 2026 05:23
Request-level jobs failed because sentry-sidekiq 5.3.1 loaded
sentry-ruby-core 5.3.1, which calls capture_exception(err) while
sentry-rails 5.4.2 expects capture_exception(exception, env).

Pin the Sentry family to 5.4.2, compile webpacker so view tests
can find application.js, and tar screenshots before upload-artifact.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
webpacker:compile failed with digital envelope routines::unsupported
on ubuntu-latest. Pass NODE_OPTIONS=--openssl-legacy-provider so
Webpack 4 can build packs in CI.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96630179438/artifacts/10679355741
https://github.com/publiclab/plots2/suites/96630179438/artifacts/10678985822

cursoragent and others added 3 commits September 22, 2026 05:44
Functional and image-upload system tests need `identify`. Stop
regenerating webpacker/react on every job so application JS such
as addComment is not overwritten before compile.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
Without the webpacker generator, yarn had no webpack script and
compile failed with Command webpack not found.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
Compiling the full app packs was OOM-killed. The generators produce
a smaller bundle that compiles on ubuntu-latest. ImageMagick remains
so Paperclip identify works in functional and system tests.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96635471754/artifacts/10679489597
https://github.com/publiclab/plots2/suites/96635471754/artifacts/10678659606

System tests died on login when return_to was a short path such as
/login because Array#[] with a range returns nil past the end.
Wiki comments called show then render :show, which double-renders
when show already redirected or rendered the editor.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@cursor
cursor Bot requested a review from a team as a code owner September 22, 2026 06:21
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96640024886/artifacts/10680785096
https://github.com/publiclab/plots2/suites/96640024886/artifacts/10680586217

cursoragent and others added 2 commits September 22, 2026 06:40
webpacker:install was overwriting app JS so addComment and the
editor were missing. Compile the repo packs with a larger Node
heap instead. Also guard TagController wildcard checks when id
is missing.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
Compiling the full app packs is still OOM-killed on ubuntu-latest
even with a 6GB Node heap. Generators produce a smaller bundle so
those jobs can run tests.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96647565707/artifacts/10680789376
https://github.com/publiclab/plots2/suites/96647565707/artifacts/10680599105

react:install overwrites sprockets JS and views, which drops
addComment and comment markup. Keep the generated packs so
compile stays small, then check out app/assets and app/views.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96653339359/artifacts/10682756940
https://github.com/publiclab/plots2/suites/96653339359/artifacts/10682656616

Tag pages crashed in for_question_tagname_and_type when tagname
was nil. Also restore app/javascript after generators so comment
React components exist while webpack config stays generated.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96658297970/artifacts/10683030774
https://github.com/publiclab/plots2/suites/96658297970/artifacts/10682634732

webpacker:install overwrites app JS and can break yarn's
public/lib modules folder, which the editor and comments need.
Compile of the real packs OOMs. Provide a stub manifest instead
and loosen brittle comment toolbar/dropzone selectors.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96663804225/artifacts/10683632371
https://github.com/publiclab/plots2/suites/96663804225/artifacts/10683461976

A stub pack kept public/lib (editor) working but dropped React
comments. rails webpacker:compile OOMs because webpack walks
public/lib. Compile just the application pack with babel limited
to app/javascript.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96668765587/artifacts/10684800161
https://github.com/publiclab/plots2/suites/96668765587/artifacts/10684490495

Webpack 4's bin prompts to install webpack-cli in CI because yarn
installs into public/lib, so the pack was never written and Capybara
hit RoutingError for /packs-test/js/application.js.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96672182611/artifacts/10685245602
https://github.com/publiclab/plots2/suites/96672182611/artifacts/10684344819

Login modal redirects to dashboard after setup returned, so the next
visit was overwritten. Wiki#comments now renders show itself so the
comments pane is actually displayed. tag_stats_path now receives :id.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96680424470/artifacts/10686038985
https://github.com/publiclab/plots2/suites/96680424470/artifacts/10685594901

Fresh wiki comments raced the publish redirect back to wiki#show.
Spam screenshot login raced the visit to /spam.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96685676618/artifacts/10686159001

cursoragent and others added 2 commits September 22, 2026 09:52
Login redirect to dashboard v2 was overwriting the /v1/dashboard visit.

Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
Co-authored-by: Apoorv Darshan <apoorvdarshan@gmail.com>
@github-actions

Copy link
Copy Markdown

This pull request generated screenshots of many common pages in the running app. You should be able to download and view them here:
https://github.com/publiclab/plots2/suites/96690713699/artifacts/10688910260

@TildaDares TildaDares closed this Sep 22, 2026
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.

Avoid N+1 query in Tag#tagnames_as_classes

3 participants