Skip to content

Avoid wide distinct scans for visible captures#1372

Open
Dodothereal wants to merge 2 commits into
RolnickLab:mainfrom
Dodothereal:fix/1370-stop-large-captures-lists-from-spilling-
Open

Avoid wide distinct scans for visible captures#1372
Dodothereal wants to merge 2 commits into
RolnickLab:mainfrom
Dodothereal:fix/1370-stop-large-captures-lists-from-spilling-

Conversation

@Dodothereal

@Dodothereal Dodothereal commented Jul 17, 2026

Copy link
Copy Markdown

Avoid wide distinct scans for visible captures

Summary

Capture-list visibility filtering previously used a full-row DISTINCT after the project-membership join, which can cause PostgreSQL to sort wide capture rows and spill large temporary files. This change filters the outer queryset by a narrow primary-key subquery instead, preserving the visibility rules while avoiding the wide-row distinct operation.

List of Changes

  1. Preserve project and project-related visibility filtering through a primary-key subquery rather than SELECT DISTINCT across full model rows.
  2. Add a regression test that verifies the capture visibility queryset contains the expected capture without generating SELECT DISTINCT.

Related Issues

Fixes #1370

Detailed Description

The owner-or-member visibility condition can join project memberships and multiply result rows. The inner queryset now selects only matching primary keys with default ordering removed; the outer queryset applies pk__in and remains available for callers to order, annotate, paginate, and select the full capture rows normally.

This is autonomous AI-agent work that @Dodothereal operates, monitors, and is accountable for.

How to Test the Changes

Run in the required sandbox:

  • sandbox-run "python -m py_compile ami/base/models.py ami/main/tests.py" — passed.
  • sandbox-run "pip install Django==4.2.10 && python - <<'PY' ..." — passed an isolated Django ORM check confirming the primary-key subquery preserves ordered results and emits no DISTINCT.
  • sandbox-run "python manage.py test ami.main.tests.TestDraftProjectPermissions --keepdb" — could not start because the sandbox had no Django installed.
  • sandbox-run "pip install -r requirements/base.txt && python manage.py test ami.main.tests.TestDraftProjectPermissions --keepdb" — blocked during dependency resolution because the repository pins psycopg[binary]==3.1.9, for which no package is available on the sandbox's Python 3.12 platform.
  • sandbox-run "docker compose -f docker-compose.ci.yml run --rm django python manage.py test ami.main.tests.TestDraftProjectPermissions --keepdb" — unavailable because Docker is not installed in the sandbox.

Deployment Notes

No migration or configuration change is required.

Checklist

  • I have tested these changes appropriately within the available sandbox environment.
  • I have added and/or modified relevant tests.
  • I updated relevant documentation or comments.
  • I have verified that this PR follows the project's coding standards.
  • Any dependent changes have already been merged to main.

AI assistance disclosure

This contribution was produced by an autonomous AI coding agent (Claude Code) that @Dodothereal operates and monitors. @Dodothereal is accountable for it, will address review feedback promptly, and will close this PR immediately if this kind of contribution is unwelcome in this project. Commits carry an Assisted-by: Claude Code trailer.

Summary by CodeRabbit

  • Bug Fixes
    • Improved visibility filtering for project-related content to return accurate, duplicate-free results.
    • Ensured draft-project deployments’ first captures are included in eligible views.
  • Tests
    • Added regression coverage to confirm visibility filtering includes the expected captures and avoids duplicate capture entries in results.

Assisted-by: Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 17, 2026 13:29
@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

👷 Deploy request for antenna-ssec pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 50a4909

@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy Preview for antenna-preview canceled.

Name Link
🔨 Latest commit 50a4909
🔍 Latest deploy log https://app.netlify.com/projects/antenna-preview/deploys/6a5a3097863fae00089bf970

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b7e29b6-2ce1-4f27-b675-b987f628205e

📥 Commits

Reviewing files that changed from the base of the PR and between 86dea98 and 50a4909.

📒 Files selected for processing (2)
  • ami/base/models.py
  • ami/main/tests.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • ami/main/tests.py

📝 Walkthrough

Walkthrough

visible_for_user now deduplicates visible objects through primary-key subqueries for projects and project-related models. A regression test verifies draft-deployment capture visibility and checks that the generated SQL does not use SELECT DISTINCT.

Changes

Visibility deduplication

Layer / File(s) Summary
Primary-key visibility filtering and regression coverage
ami/base/models.py, ami/main/tests.py
Project and project-related visibility filters now collect matching primary keys and filter the outer queryset by pk__in; a source-image regression test verifies capture inclusion and the absence of SELECT DISTINCT.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: replacing wide DISTINCT scans in capture visibility queries.
Description check ✅ Passed The description matches the template well, covering summary, changes, related issue, testing, deployment notes, and checklist.
Linked Issues check ✅ Passed The changes implement #1370 by deduplicating visible captures via a primary-key subquery and adding regression coverage.
Out of Scope Changes check ✅ Passed The PR stays focused on capture visibility filtering and its regression test, with no unrelated code changes apparent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ami/main/tests.py`:
- Around line 3235-3239: Update
test_visible_for_user_deduplicates_captures_in_a_primary_key_subquery to create
a second membership matching the same project, query visibility as the project
owner, and assert the returned primary-key values are unique. Retain the
assertion that the query SQL does not contain SELECT DISTINCT so the test
specifically exercises duplicate membership joins.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 65ceefce-73ac-4cc9-bfd5-23ddfb5e9074

📥 Commits

Reviewing files that changed from the base of the PR and between 3f85d84 and 86dea98.

📒 Files selected for processing (2)
  • ami/base/models.py
  • ami/main/tests.py

Comment thread ami/main/tests.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the core BaseQuerySet.visible_for_user() permission-scoping helper to avoid emitting wide-row SELECT DISTINCT queries (notably for captures / SourceImage), by filtering the outer queryset via a primary-key subquery instead. This targets a known Postgres temp-file spill issue on large deployments while keeping visibility semantics consistent.

Changes:

  • Replace .distinct()-based deduplication in visible_for_user() with a pk__in primary-key subquery that clears ordering in the inner query.
  • Add a regression test asserting that capture visibility works for a member and that the generated SQL does not include SELECT DISTINCT.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
ami/base/models.py Reworks BaseQuerySet.visible_for_user() to avoid full-row DISTINCT by using a primary-key subquery filter.
ami/main/tests.py Adds a regression test to confirm visible captures are returned without generating SELECT DISTINCT.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ami/base/models.py
Comment on lines +69 to +70
visible_project_ids = self.filter(filter_condition).order_by().values_list("pk", flat=True)
return self.filter(pk__in=visible_project_ids)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed in 50a4909: anonymous project visibility now returns the simple draft=False filter directly, avoiding the unnecessary self-referential primary-key subquery.

Assisted-by: Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
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.

Stop large captures lists from spilling gigabytes of database temp files

2 participants